ILIAS  release_5-0 Revision 5.0.0-1144-gc4397b1f870
class.ilAssQuestionList.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/Taxonomy/interfaces/interface.ilTaxAssignedItemInfo.php';
5
16{
22 private $db = null;
23
29 private $lng = null;
30
36 private $pluginAdmin = null;
37
43 private $parentObjId = null;
44
45 private $parentObjType = 'qpl';
46
52 private $availableTaxonomyIds = array();
53
59 private $fieldFilters = array();
60
66 private $taxFilters = array();
67
73 private $answerStatusActiveId = null;
74
78 private $forcedQuestionIds = array();
79
85 const QUESTION_ANSWER_STATUS_CORRECT_ANSWERED = 'correctAnswered';
86
90 const ANSWER_STATUS_FILTER_ALL_NON_CORRECT = 'allNonCorrect';
93
99 private $answerStatusFilter = null;
100
106 private $questions = array();
107
108
109 const QUESTION_INSTANCE_TYPE_ORIGINALS = 'QST_INSTANCE_TYPE_ORIGINALS';
110 const QUESTION_INSTANCE_TYPE_DUPLICATES = 'QST_INSTANCE_TYPE_DUPLICATES';
112
113 private $questionIdsFilter = null;
114
122 {
123 $this->db = $db;
124 $this->lng = $lng;
125 $this->pluginAdmin = $pluginAdmin;
126 $this->parentObjId = $parentObjId;
127 }
128
130 {
131 $this->parentObjType = $parentObjType;
132 }
133
134 public function getParentObjectType()
135 {
137 }
138
140 {
141 $this->questionInstanceTypeFilter = $questionInstanceTypeFilter;
142 }
143
145 {
147 }
148
150 {
151 $this->questionIdsFilter = $questionIdsFilter;
152 }
153
154 public function getQuestionIdsFilter()
155 {
157 }
158
159 public function addFieldFilter($fieldName, $fieldValue)
160 {
161 $this->fieldFilters[$fieldName] = $fieldValue;
162 }
163
164 public function addTaxonomyFilter($taxId, $taxNodes)
165 {
166 $this->taxFilters[$taxId] = $taxNodes;
167 }
168
170 {
171 $this->availableTaxonomyIds = $availableTaxonomyIds;
172 }
173
174 public function getAvailableTaxonomyIds()
175 {
177 }
178
180 {
181 $this->answerStatusActiveId = $answerStatusActiveId;
182 }
183
184 public function getAnswerStatusActiveId()
185 {
187 }
188
190 {
191 $this->answerStatusFilter = $answerStatusFilter;
192 }
193
194 public function getAnswerStatusFilter()
195 {
197 }
198
203 {
204 $this->forcedQuestionIds = $forcedQuestionIds;
205 }
206
210 public function getForcedQuestionIds()
211 {
213 }
214
215 private function getFieldFilterExpressions()
216 {
217 $expressions = array();
218
219 foreach($this->fieldFilters as $fieldName => $fieldValue)
220 {
221 switch($fieldName)
222 {
223 case 'title':
224 case 'description':
225 case 'author':
226
227 $expressions[] = $this->db->like('qpl_questions.' . $fieldName, 'text', "%%$fieldValue%%");
228 break;
229
230 case 'type':
231
232 $expressions[] = "qpl_qst_type.type_tag = {$this->db->quote($fieldValue, 'text')}";
233 break;
234
235 case 'question_id':
236 if ($fieldValue != "" && !is_array($fieldValue))
237 {
238 $fieldValue = array($fieldValue);
239 }
240 $expressions[] = $this->db->in("qpl_questions.question_id", $fieldValue, false, "integer");
241 break;
242 }
243 }
244
245 return $expressions;
246 }
247
249 {
250 $expressions = array();
251
252 require_once 'Services/Taxonomy/classes/class.ilTaxonomyTree.php';
253 require_once 'Services/Taxonomy/classes/class.ilTaxNodeAssignment.php';
254
255 foreach($this->taxFilters as $taxId => $taxNodes)
256 {
257 $questionIds = array();
258
259 $forceBypass = true;
260
261 foreach($taxNodes as $taxNode)
262 {
263 $forceBypass = false;
264
265 $taxTree = new ilTaxonomyTree($taxId);
266
267 $taxNodeAssignment = new ilTaxNodeAssignment($this->parentObjType, $this->parentObjId, 'quest', $taxId);
268
269 $subNodes = $taxTree->getSubTreeIds($taxNode);
270 $subNodes[] = $taxNode;
271
272 $taxItems = $taxNodeAssignment->getAssignmentsOfNode($subNodes);
273
274 foreach($taxItems as $taxItem)
275 {
276 $questionIds[$taxItem['item_id']] = $taxItem['item_id'];
277 }
278 }
279
280 if( !$forceBypass )
281 {
282 $expressions[] = $this->db->in('question_id', $questionIds, false, 'integer');
283 }
284 }
285
286 return $expressions;
287 }
288
290 {
291 switch( $this->getQuestionInstanceTypeFilter() )
292 {
294
295 return 'qpl_questions.original_id IS NULL';
296
298
299 return 'qpl_questions.original_id IS NOT NULL';
300 }
301
302 return null;
303 }
304
306 {
307 if( is_array($this->getQuestionIdsFilter()) )
308 {
309 return $this->db->in('qpl_questions.question_id', $this->getQuestionIdsFilter(), false, 'integer');
310 }
311
312 return null;
313 }
314
316 {
317 if( $this->parentObjId )
318 {
319 return "qpl_questions.obj_fi = {$this->db->quote($this->parentObjId, 'integer')}";
320 }
321
322 return null;
323 }
324
326 {
327 $expressions = array();
328
329 switch( $this->getAnswerStatusFilter() )
330 {
332
333 $expressions[] = '
334 (tst_test_result.question_fi IS NULL OR tst_test_result.points < qpl_questions.points)
335 ';
336 break;
337
339
340 $expressions[] = 'tst_test_result.question_fi IS NULL';
341 break;
342
344
345 $expressions[] = 'tst_test_result.question_fi IS NOT NULL';
346 $expressions[] = 'tst_test_result.points < qpl_questions.points';
347 break;
348 }
349
350 return $expressions;
351 }
352
353 private function getTableJoinExpression()
354 {
355 $tableJoin = "
356 INNER JOIN qpl_qst_type
357 ON qpl_qst_type.question_type_id = qpl_questions.question_type_fi
358 ";
359
360 if( $this->getAnswerStatusActiveId() )
361 {
362 $tableJoin .= "
363 LEFT JOIN tst_test_result
364 ON tst_test_result.question_fi = qpl_questions.question_id
365 AND tst_test_result.active_fi = {$this->db->quote($this->getAnswerStatusActiveId(), 'integer')}
366 ";
367 }
368
369 return $tableJoin;
370 }
371
373 {
374 $CONDITIONS = array();
375
376 if( $this->getQuestionInstanceTypeFilterExpression() !== null )
377 {
378 $CONDITIONS[] = $this->getQuestionInstanceTypeFilterExpression();
379 }
380
381 if( $this->getQuestionIdsFilterExpression() !== null )
382 {
383 $CONDITIONS[] = $this->getQuestionIdsFilterExpression();
384 }
385
386 if( $this->getParentObjectIdFilterExpression() !== null )
387 {
388 $CONDITIONS[] = $this->getParentObjectIdFilterExpression();
389 }
390
391 $CONDITIONS = array_merge($CONDITIONS,
395 );
396
397 $CONDITIONS = implode(' AND ', $CONDITIONS);
398
399 return strlen($CONDITIONS) ? 'AND '.$CONDITIONS : '';
400 }
401
402 private function getSelectFieldsExpression()
403 {
404 $selectFields = array(
405 'qpl_questions.*',
406 'qpl_qst_type.type_tag',
407 'qpl_qst_type.plugin',
408 'qpl_questions.points max_points'
409 );
410
411 if( $this->getAnswerStatusActiveId() )
412 {
413 $selectFields[] = 'tst_test_result.points reached_points';
414 $selectFields[] = "CASE
415 WHEN tst_test_result.points IS NULL THEN '".self::QUESTION_ANSWER_STATUS_NON_ANSWERED."'
416 WHEN tst_test_result.points < qpl_questions.points THEN '".self::QUESTION_ANSWER_STATUS_WRONG_ANSWERED."'
417 ELSE '".self::QUESTION_ANSWER_STATUS_CORRECT_ANSWERED."'
418 END question_answer_status
419 ";
420 }
421
422 $selectFields = implode(",\n\t\t\t\t", $selectFields);
423
424 return "
425 SELECT {$selectFields}
426 ";
427 }
428
429 private function buildBasicQuery()
430 {
431 return "
432 {$this->getSelectFieldsExpression()}
433
434 FROM qpl_questions
435
436 {$this->getTableJoinExpression()}
437
438 WHERE qpl_questions.tstamp > 0
439 ";
440 }
441
442 private function buildQuery()
443 {
444 $query = $this->buildBasicQuery()."
445 {$this->getConditionalFilterExpression()}
446 ";
447
448 if( count($this->getForcedQuestionIds()) )
449 {
450 $query .= "
451 UNION {$this->buildBasicQuery()}
452 AND {$this->db->in('qpl_questions.question_id', $this->getForcedQuestionIds(), false, 'integer')}
453 ";
454 }
455
456 return $query;
457 }
458
459 public function load()
460 {
461 $this->checkFilters();
462
463 $query = $this->buildQuery();
464
465 #vd($query);
466
467 $res = $this->db->query($query);
468
469 //echo $this->db->db->last_query;
470
471 #vd($this->db->db->last_query);
472
473 while( $row = $this->db->fetchAssoc($res) )
474 {
475 if( !$this->isActiveQuestionType($row) )
476 {
477 continue;
478 }
479
480 $row['taxonomies'] = $this->loadTaxonomyAssignmentData($row['question_id']);
481
482 $row['ttype'] = $this->lng->txt($row['type_tag']);
483
484 $this->questions[ $row['question_id'] ] = $row;
485 }
486 }
487
488 private function loadTaxonomyAssignmentData($questionId)
489 {
490 $taxAssignmentData = array();
491
492 foreach($this->getAvailableTaxonomyIds() as $taxId)
493 {
494 require_once 'Services/Taxonomy/classes/class.ilTaxonomyTree.php';
495 require_once 'Services/Taxonomy/classes/class.ilTaxNodeAssignment.php';
496
497 $taxTree = new ilTaxonomyTree($taxId);
498
499 $taxAssignment = new ilTaxNodeAssignment('qpl', $this->parentObjId, 'quest', $taxId);
500
501 $assignments = $taxAssignment->getAssignmentsOfItem($questionId);
502
503 foreach($assignments as $assData)
504 {
505 if( !isset($taxAssignmentData[ $assData['tax_id'] ]) )
506 {
507 $taxAssignmentData[ $assData['tax_id'] ] = array();
508 }
509
510 $nodeData = $taxTree->getNodeData($assData['node_id']);
511
512 $assData['node_lft'] = $nodeData['lft'];
513
514 $taxAssignmentData[ $assData['tax_id'] ][ $assData['node_id'] ] = $assData;
515 }
516 }
517
518 return $taxAssignmentData;
519 }
520
521 private function isActiveQuestionType($questionData)
522 {
523 if( !isset($questionData['plugin']) )
524 {
525 return false;
526 }
527
528 if( !$questionData['plugin'] )
529 {
530 return true;
531 }
532
533 return $this->pluginAdmin->isActive(IL_COMP_MODULE, 'TestQuestionPool', 'qst', $questionData['type_tag']);
534 }
535
536 public function getQuestionDataArray()
537 {
538 return $this->questions;
539 }
540
541 public function isInList($questionId)
542 {
543 return isset($this->questions[$questionId]);
544 }
545
555 public function getTitle($a_comp_id, $a_item_type, $a_item_id)
556 {
557 if( $a_comp_id != 'qpl' || $a_item_type != 'quest' || !(int)$a_item_id )
558 {
559 return '';
560 }
561
562 if( !isset($this->questions[$a_item_id]) )
563 {
564 return '';
565 }
566
567 return $this->questions[$a_item_id]['title'];
568 }
569
570 private function checkFilters()
571 {
572 if( strlen($this->getAnswerStatusFilter()) && !$this->getAnswerStatusActiveId() )
573 {
574 require_once 'Modules/TestQuestionPool/exceptions/class.ilTestQuestionPoolException.php';
575
577 'No active id given! You cannot use the answer status filter without giving an active id.'
578 );
579 }
580
581 }
582}
const IL_COMP_MODULE
loadTaxonomyAssignmentData($questionId)
setAnswerStatusActiveId($answerStatusActiveId)
const ANSWER_STATUS_FILTER_ALL_NON_CORRECT
answer status filter value domain
__construct(ilDB $db, ilLanguage $lng, ilPluginAdmin $pluginAdmin, $parentObjId)
Constructor.
setParentObjectType($parentObjType)
setForcedQuestionIds($forcedQuestionIds)
isActiveQuestionType($questionData)
addTaxonomyFilter($taxId, $taxNodes)
setQuestionIdsFilter($questionIdsFilter)
setAvailableTaxonomyIds($availableTaxonomyIds)
setAnswerStatusFilter($answerStatusFilter)
setQuestionInstanceTypeFilter($questionInstanceTypeFilter)
const QUESTION_ANSWER_STATUS_NON_ANSWERED
answer status domain for single questions
addFieldFilter($fieldName, $fieldValue)
getTitle($a_comp_id, $a_item_type, $a_item_id)
Get title of an assigned item.
Database Wrapper.
Definition: class.ilDB.php:29
language handling
Administration class for plugins.
Taxonomy node <-> item assignment.
Interface for assigned items of taxonomies.