ILIAS  release_4-4 Revision
All Data Structures Namespaces Files Functions Variables Modules Pages
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 
4 require_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 
50  private $availableTaxonomyIds = array();
51 
57  private $fieldFilters = array();
58 
64  private $taxFilters = array();
65 
71  private $answerStatusActiveId = null;
72 
76  private $forcedQuestionIds = array();
77 
81  const QUESTION_ANSWER_STATUS_NON_ANSWERED = 'nonAnswered';
82  const QUESTION_ANSWER_STATUS_WRONG_ANSWERED = 'wrongAnswered';
83  const QUESTION_ANSWER_STATUS_CORRECT_ANSWERED = 'correctAnswered';
84 
88  const ANSWER_STATUS_FILTER_ALL_NON_CORRECT = 'allNonCorrect';
91 
97  private $answerStatusFilter = null;
98 
104  private $questions = array();
105 
113  {
114  $this->db = $db;
115  $this->lng = $lng;
116  $this->pluginAdmin = $pluginAdmin;
117  $this->parentObjId = $parentObjId;
118  }
119 
120  public function addFieldFilter($fieldName, $fieldValue)
121  {
122  $this->fieldFilters[$fieldName] = $fieldValue;
123  }
124 
125  public function addTaxonomyFilter($taxId, $taxNodes)
126  {
127  $this->taxFilters[$taxId] = $taxNodes;
128  }
129 
131  {
132  $this->availableTaxonomyIds = $availableTaxonomyIds;
133  }
134 
135  public function getAvailableTaxonomyIds()
136  {
138  }
139 
141  {
142  $this->answerStatusActiveId = $answerStatusActiveId;
143  }
144 
145  public function getAnswerStatusActiveId()
146  {
148  }
149 
151  {
152  $this->answerStatusFilter = $answerStatusFilter;
153  }
154 
155  public function getAnswerStatusFilter()
156  {
158  }
159 
164  {
165  $this->forcedQuestionIds = $forcedQuestionIds;
166  }
167 
171  public function getForcedQuestionIds()
172  {
174  }
175 
176  private function getFieldFilterExpressions()
177  {
178  $expressions = array();
179 
180  foreach($this->fieldFilters as $fieldName => $fieldValue)
181  {
182  switch($fieldName)
183  {
184  case 'title':
185  case 'description':
186  case 'author':
187 
188  $expressions[] = $this->db->like('qpl_questions.' . $fieldName, 'text', "%%$fieldValue%%");
189  break;
190 
191  case 'type':
192 
193  $expressions[] = "qpl_qst_type.type_tag = {$this->db->quote($fieldValue, 'text')}";
194  break;
195  }
196  }
197 
198  return $expressions;
199  }
200 
201  private function getTaxonomyFilterExpressions()
202  {
203  $expressions = array();
204 
205  require_once 'Services/Taxonomy/classes/class.ilTaxonomyTree.php';
206  require_once 'Services/Taxonomy/classes/class.ilTaxNodeAssignment.php';
207 
208  foreach($this->taxFilters as $taxId => $taxNodes)
209  {
210  $questionIds = array();
211 
212  $forceBypass = true;
213 
214  foreach($taxNodes as $taxNode)
215  {
216  $forceBypass = false;
217 
218  $taxTree = new ilTaxonomyTree($taxId);
219 
220  $taxNodeAssignment = new ilTaxNodeAssignment('qpl', $this->parentObjId, 'quest', $taxId);
221 
222  $subNodes = $taxTree->getSubTreeIds($taxNode);
223  $subNodes[] = $taxNode;
224 
225  $taxItems = $taxNodeAssignment->getAssignmentsOfNode($subNodes);
226 
227  foreach($taxItems as $taxItem)
228  {
229  $questionIds[$taxItem['item_id']] = $taxItem['item_id'];
230  }
231  }
232 
233  if( !$forceBypass )
234  {
235  $expressions[] = $this->db->in('question_id', $questionIds, false, 'integer');
236  }
237  }
238 
239  return $expressions;
240  }
241 
243  {
244  $expressions = array();
245 
246  switch( $this->getAnswerStatusFilter() )
247  {
248  case self::ANSWER_STATUS_FILTER_ALL_NON_CORRECT:
249 
250  $expressions[] = '
251  (tst_test_result.question_fi IS NULL OR tst_test_result.points < qpl_questions.points)
252  ';
253  break;
254 
255  case self::ANSWER_STATUS_FILTER_NON_ANSWERED_ONLY:
256 
257  $expressions[] = 'tst_test_result.question_fi IS NULL';
258  break;
259 
260  case self::ANSWER_STATUS_FILTER_WRONG_ANSWERED_ONLY:
261 
262  $expressions[] = 'tst_test_result.question_fi IS NOT NULL';
263  $expressions[] = 'tst_test_result.points < qpl_questions.points';
264  break;
265  }
266 
267  return $expressions;
268  }
269 
270  private function getTableJoinExpression()
271  {
272  $tableJoin = "
273  INNER JOIN qpl_qst_type
274  ON qpl_qst_type.question_type_id = qpl_questions.question_type_fi
275  ";
276 
277  if( $this->getAnswerStatusActiveId() )
278  {
279  $tableJoin .= "
280  LEFT JOIN tst_test_result
281  ON tst_test_result.question_fi = qpl_questions.question_id
282  AND tst_test_result.active_fi = {$this->db->quote($this->getAnswerStatusActiveId(), 'integer')}
283  ";
284  }
285 
286  return $tableJoin;
287  }
288 
290  {
291  $CONDITIONS = array_merge(
292  $this->getFieldFilterExpressions(),
295  );
296 
297  $CONDITIONS = implode(' AND ', $CONDITIONS);
298 
299  return strlen($CONDITIONS) ? 'AND '.$CONDITIONS : '';
300  }
301 
302  private function getSelectFieldsExpression()
303  {
304  $selectFields = array(
305  'qpl_questions.*',
306  'qpl_qst_type.type_tag',
307  'qpl_qst_type.plugin',
308  'qpl_questions.points max_points'
309  );
310 
311  if( $this->getAnswerStatusActiveId() )
312  {
313  $selectFields[] = 'tst_test_result.points reached_points';
314  $selectFields[] = "CASE
315  WHEN tst_test_result.points IS NULL THEN '".self::QUESTION_ANSWER_STATUS_NON_ANSWERED."'
316  WHEN tst_test_result.points < qpl_questions.points THEN '".self::QUESTION_ANSWER_STATUS_WRONG_ANSWERED."'
317  ELSE '".self::QUESTION_ANSWER_STATUS_CORRECT_ANSWERED."'
318  END question_answer_status
319  ";
320  }
321 
322  $selectFields = implode(",\n\t\t\t\t", $selectFields);
323 
324  return "
325  SELECT {$selectFields}
326  ";
327  }
328 
329  private function buildBasicQuery()
330  {
331  return "
332  {$this->getSelectFieldsExpression()}
333 
334  FROM qpl_questions
335 
336  {$this->getTableJoinExpression()}
337 
338  WHERE qpl_questions.original_id IS NULL
339  AND qpl_questions.obj_fi = {$this->db->quote($this->parentObjId, 'integer')}
340  AND qpl_questions.tstamp > 0
341  ";
342  }
343 
344  private function buildQuery()
345  {
346  $query = $this->buildBasicQuery()."
347  {$this->getConditionalFilterExpression()}
348  ";
349 
350  if( count($this->getForcedQuestionIds()) )
351  {
352  $query .= "
353  UNION {$this->buildBasicQuery()}
354  AND {$this->db->in('qpl_questions.question_id', $this->getForcedQuestionIds(), false, 'integer')}
355  ";
356  }
357 
358  return $query;
359  }
360 
361  public function load()
362  {
363  $this->checkFilters();
364 
365  $query = $this->buildQuery();
366 
367  #vd($query);
368 
369  $res = $this->db->query($query);
370 
371  #vd($this->db->db->last_query);
372 
373  while( $row = $this->db->fetchAssoc($res) )
374  {
375  if( !$this->isActiveQuestionType($row) )
376  {
377  continue;
378  }
379 
380  $row['taxonomies'] = $this->loadTaxonomyAssignmentData($row['question_id']);
381 
382  $row['ttype'] = $this->lng->txt($row['type_tag']);
383 
384  $this->questions[ $row['question_id'] ] = $row;
385  }
386  }
387 
388  private function loadTaxonomyAssignmentData($questionId)
389  {
390  $taxAssignmentData = array();
391 
392  foreach($this->getAvailableTaxonomyIds() as $taxId)
393  {
394  require_once 'Services/Taxonomy/classes/class.ilTaxonomyTree.php';
395  require_once 'Services/Taxonomy/classes/class.ilTaxNodeAssignment.php';
396 
397  $taxTree = new ilTaxonomyTree($taxId);
398 
399  $taxAssignment = new ilTaxNodeAssignment('qpl', $this->parentObjId, 'quest', $taxId);
400 
401  $assignments = $taxAssignment->getAssignmentsOfItem($questionId);
402 
403  foreach($assignments as $assData)
404  {
405  if( !isset($taxAssignmentData[ $assData['tax_id'] ]) )
406  {
407  $taxAssignmentData[ $assData['tax_id'] ] = array();
408  }
409 
410  $nodeData = $taxTree->getNodeData($assData['node_id']);
411 
412  $assData['node_lft'] = $nodeData['lft'];
413 
414  $taxAssignmentData[ $assData['tax_id'] ][ $assData['node_id'] ] = $assData;
415  }
416  }
417 
418  return $taxAssignmentData;
419  }
420 
421  private function isActiveQuestionType($questionData)
422  {
423  if( !isset($questionData['plugin']) )
424  {
425  return false;
426  }
427 
428  if( !$questionData['plugin'] )
429  {
430  return true;
431  }
432 
433  return $this->pluginAdmin->isActive(IL_COMP_MODULE, 'TestQuestionPool', 'qst', $questionData['type_tag']);
434  }
435 
436  public function getQuestionDataArray()
437  {
438  return $this->questions;
439  }
440 
450  public function getTitle($a_comp_id, $a_item_type, $a_item_id)
451  {
452  if( $a_comp_id != 'qpl' || $a_item_type != 'quest' || !(int)$a_item_id )
453  {
454  return '';
455  }
456 
457  if( !isset($this->questions[$a_item_id]) )
458  {
459  return '';
460  }
461 
462  return $this->questions[$a_item_id]['title'];
463  }
464 
465  private function checkFilters()
466  {
467  if( strlen($this->getAnswerStatusFilter()) && !$this->getAnswerStatusActiveId() )
468  {
469  require_once 'Modules/TestQuestionPool/exceptions/class.ilTestQuestionPoolException.php';
470 
471  throw new ilTestQuestionPoolException(
472  'No active id given! You cannot use the answer status filter without giving an active id.'
473  );
474  }
475 
476  }
477 }
setAnswerStatusFilter($answerStatusFilter)
Taxonomy node <-> item assignment.
isActiveQuestionType($questionData)
addTaxonomyFilter($taxId, $taxNodes)
setAnswerStatusActiveId($answerStatusActiveId)
Administration class for plugins.
const IL_COMP_MODULE
const ANSWER_STATUS_FILTER_ALL_NON_CORRECT
answer status filter value domain
Interface for assigned items of taxonomies.
setForcedQuestionIds($forcedQuestionIds)
Database Wrapper.
Definition: class.ilDB.php:28
getTitle($a_comp_id, $a_item_type, $a_item_id)
Get title of an assigned item.
addFieldFilter($fieldName, $fieldValue)
language handling
loadTaxonomyAssignmentData($questionId)
__construct(ilDB $db, ilLanguage $lng, ilPluginAdmin $pluginAdmin, $parentObjId)
Constructor.
const QUESTION_ANSWER_STATUS_NON_ANSWERED
answer status domain for single questions
setAvailableTaxonomyIds($availableTaxonomyIds)