ILIAS  release_8 Revision v8.19
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilPRGAssignmentDBRepository.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
26 {
27  public const ASSIGNMENT_TABLE = 'prg_usr_assignments';
28  public const ASSIGNMENT_FIELD_ID = 'id';
29  public const ASSIGNMENT_FIELD_USR_ID = 'usr_id';
30  public const ASSIGNMENT_FIELD_ROOT_PRG_ID = 'root_prg_id';
31  public const ASSIGNMENT_FIELD_LAST_CHANGE = 'last_change';
32  public const ASSIGNMENT_FIELD_LAST_CHANGE_BY = 'last_change_by';
33  public const ASSIGNMENT_FIELD_RESTART_DATE = 'restart_date';
34  public const ASSIGNMENT_FIELD_RESTARTED_ASSIGNMENT_ID = 'restarted_assignment_id';
35  public const ASSIGNMENT_FIELD_RESTART_MAIL = 'restart_mail_send';
36  public const ASSIGNMENT_FIELD_MANUALLY_ASSIGNED = 'assigned_manually';
37 
38  public const PROGRESS_TABLE = 'prg_usr_progress';
39  public const PROGRESS_FIELD_ASSIGNMENT_ID = 'assignment_id';
40  public const PROGRESS_FIELD_USR_ID = 'usr_id';
41  public const PROGRESS_FIELD_PRG_ID = 'prg_id';
42  public const PROGRESS_FIELD_POINTS = 'points';
43  public const PROGRESS_FIELD_POINTS_CUR = 'points_cur';
44  public const PROGRESS_FIELD_STATUS = 'status';
45  public const PROGRESS_FIELD_COMPLETION_BY = 'completion_by';
46  public const PROGRESS_FIELD_ASSIGNMENT_DATE = 'assignment_date';
47  public const PROGRESS_FIELD_LAST_CHANGE = 'last_change'; //'p_' .
48  public const PROGRESS_FIELD_LAST_CHANGE_BY = 'last_change_by'; //'p_' .
49  public const PROGRESS_FIELD_COMPLETION_DATE = 'completion_date';
50  public const PROGRESS_FIELD_DEADLINE = 'deadline';
51  public const PROGRESS_FIELD_VQ_DATE = 'vq_date';
52  public const PROGRESS_FIELD_INVALIDATED = 'invalidated';
53  public const PROGRESS_FIELD_MAIL_SENT_RISKYTOFAIL = 'sent_mail_risky_to_fail';
54  public const PROGRESS_FIELD_MAIL_SENT_WILLEXPIRE = 'sent_mail_expires';
55  public const PROGRESS_FIELD_IS_INDIVIDUAL = 'individual';
56 
57  public const DATE_FORMAT_ENDOFDAY = 'Y-m-d 23:59:59';
58 
59  protected ilDBInterface $db;
60  protected ilTree $tree;
65  protected array $progresses = [];
67 
68  public function __construct(
69  ilDBInterface $db,
70  ilTree $tree,
72  PRGEventsDelayed $events
73  ) {
74  $this->db = $db;
75  $this->tree = $tree;
76  $this->settings_repo = $settings_repo;
77  $this->events = $events;
78  }
79 
80  public function getDashboardInstancesforUser(int $usr_id): array
81  {
82  $assignments = $this->getForUser($usr_id);
83  //TODO: decide, which ones are relevant for the dashboard
84  return $assignments;
85  }
86 
87  public function createFor(
88  int $prg_obj_id,
89  int $usr_id,
90  int $assigning_usr_id
91  ): ilPRGAssignment {
92  $manually = false;
93  if (ilObject::_lookupType($assigning_usr_id) === "usr") {
94  $manually = true;
95  }
96  $row = [
97  self::ASSIGNMENT_FIELD_ID => $this->nextId(),
98  self::ASSIGNMENT_FIELD_USR_ID => $usr_id,
99  self::ASSIGNMENT_FIELD_ROOT_PRG_ID => $prg_obj_id,
100  self::ASSIGNMENT_FIELD_LAST_CHANGE_BY => $assigning_usr_id,
101  self::ASSIGNMENT_FIELD_LAST_CHANGE => ilUtil::now(),
102  self::ASSIGNMENT_FIELD_RESTART_DATE => null,
103  self::ASSIGNMENT_FIELD_RESTARTED_ASSIGNMENT_ID => ilPRGAssignment::NO_RESTARTED_ASSIGNMENT,
104  self::ASSIGNMENT_FIELD_MANUALLY_ASSIGNED => $manually
105  ];
106  $this->insertAssignmentRowDB($row);
107  $this->progresses = [];
108 
109  //add user_colums : ilPRGUserInformation::COLNAMES
110  $query = 'SELECT ' . implode(' ,', ilPRGUserInformation::COLNAMES) . PHP_EOL
111  . 'FROM usr_data WHERE usr_id = ' . $this->db->quote($usr_id, 'integer');
112  $res = $this->db->query($query);
113  $row = array_merge($row, $this->db->fetchAssoc($res));
114 
115 
116  $ass = $this->assignmentByRow($row);
117  return $ass;
118  }
119 
120  public function store(ilPRGAssignment $assignment): void
121  {
122  $row = [
123  self::ASSIGNMENT_FIELD_ID => $assignment->getId(),
124  self::ASSIGNMENT_FIELD_USR_ID => $assignment->getUserId(),
125  self::ASSIGNMENT_FIELD_ROOT_PRG_ID => $assignment->getRootId(),
126  self::ASSIGNMENT_FIELD_LAST_CHANGE_BY => $assignment->getLastChangeBy(),
127  self::ASSIGNMENT_FIELD_LAST_CHANGE => $assignment->getLastChange()->format(ilPRGAssignment::DATE_TIME_FORMAT),
128  self::ASSIGNMENT_FIELD_RESTART_DATE => $assignment->getRestartDate() ? $assignment->getRestartDate()->format(ilPRGAssignment::DATE_TIME_FORMAT) : null,
129  self::ASSIGNMENT_FIELD_RESTARTED_ASSIGNMENT_ID => $assignment->getRestartedAssignmentId(),
130  self::ASSIGNMENT_FIELD_MANUALLY_ASSIGNED => $assignment->isManuallyAssigned()
131  ];
132  $this->updateAssignmentRowDB($row);
133  foreach ($assignment->getProgresses() as $pgs) {
134  $this->storeProgressRow(
135  $assignment->getId(),
136  $assignment->getUserId(),
137  $pgs
138  );
139  }
140 
141  $this->events->raiseCollected();
142  }
143 
144  public function delete(ilPRGAssignment $assignment): void
145  {
146  $ass_id = $assignment->getId();
147  $query = 'DELETE FROM ' . self::ASSIGNMENT_TABLE . PHP_EOL
148  . 'WHERE ' . self::ASSIGNMENT_FIELD_ID . ' = ' . $ass_id;
149  $this->db->manipulate($query);
150 
151  $query = 'DELETE FROM ' . self::PROGRESS_TABLE . PHP_EOL
152  . 'WHERE ' . self::PROGRESS_FIELD_ASSIGNMENT_ID . ' = ' . $ass_id;
153  $this->db->manipulate($query);
154  }
155 
156  public function deleteAllAssignmentsForProgrammeId(int $prg_obj_id): void
157  {
158  $query = 'DELETE FROM ' . self::ASSIGNMENT_TABLE . PHP_EOL
159  . 'WHERE ' . self::ASSIGNMENT_FIELD_ROOT_PRG_ID . '=' . $this->db->quote($prg_obj_id, 'integer');
160  $this->db->manipulate($query);
162  }
163  protected function deleteAllOrphanedProgresses(): void
164  {
165  $query = 'DELETE FROM ' . self::PROGRESS_TABLE . PHP_EOL
166  . 'WHERE ' . self::PROGRESS_FIELD_ASSIGNMENT_ID . PHP_EOL
167  . 'NOT IN (' . PHP_EOL
168  . 'SELECT ' . $this->db->quoteIdentifier(self::ASSIGNMENT_FIELD_ID)
169  . ' FROM ' . $this->db->quoteIdentifier(self::ASSIGNMENT_TABLE) . PHP_EOL
170  . ');' . PHP_EOL;
171  $this->db->manipulate($query);
172  }
173 
174 
175  public function get(int $id): ilPRGAssignment
176  {
177  $ass = $this->read([
178  'ass.' . self::ASSIGNMENT_FIELD_ID . ' = ' . $this->db->quote($id, 'integer')
179  ]);
180 
181  return $ass->current();
182  }
183 
184  public function getForUser(int $usr_id): array
185  {
186  $assignments = array_filter(iterator_to_array(
187  $this->read([
188  'ass.' . self::ASSIGNMENT_FIELD_USR_ID . ' = ' . $this->db->quote($usr_id, 'integer')
189  ])
190  ));
191  return $assignments;
192  }
193 
194  public function getAllForNodeIsContained(
195  int $prg_obj_id,
196  array $user_filter = null,
197  ilPRGAssignmentFilter $custom_filters = null
198  ): array {
199  $conditions = [
200  'pgs.' . self::PROGRESS_FIELD_PRG_ID . ' = ' . $this->db->quote($prg_obj_id, 'integer')
201  ];
202  if ($user_filter) {
203  $conditions[] = $this->db->in('ass.' . self::ASSIGNMENT_FIELD_USR_ID, $user_filter, false, 'integer');
204  }
205  if ($custom_filters) {
206  $conditions = array_merge($conditions, $custom_filters->toConditions());
207  }
208 
209  $assignments = array_filter(iterator_to_array(
210  $this->read($conditions)
211  ));
212  return $assignments;
213  }
214 
215  public function countAllForNodeIsContained(
216  int $prg_obj_id,
217  array $user_filter = null,
218  ilPRGAssignmentFilter $custom_filters = null
219  ): int {
220  $conditions = [
221  'pgs.' . self::PROGRESS_FIELD_PRG_ID . ' = ' . $this->db->quote($prg_obj_id, 'integer')
222  ];
223  if ($user_filter) {
224  $conditions[] = $this->db->in('ass.' . self::ASSIGNMENT_FIELD_USR_ID, $user_filter, false, 'integer');
225  }
226  if ($custom_filters) {
227  $conditions = array_merge($conditions, $custom_filters->toConditions());
228  }
229  return $this->count($conditions);
230  }
231 
232  public function getAllForSpecificNode(int $prg_obj_id, array $user_filter = null): array
233  {
234  $conditions = [
235  self::ASSIGNMENT_FIELD_ROOT_PRG_ID . ' = ' . $this->db->quote($prg_obj_id, 'integer')
236  ];
237  if ($user_filter) {
238  $conditions[] = $this->db->in('ass.' . self::ASSIGNMENT_FIELD_USR_ID, $user_filter, false, 'integer');
239  }
240 
241  $assignments = array_filter(iterator_to_array(
242  $this->read($conditions)
243  ));
244  return $assignments;
245  }
246 
247  public function getPassedDeadline(\DateTimeImmutable $deadline): array
248  {
249  $deadline = $this->db->quote(
250  $deadline->format(ilPRGProgress::DATE_FORMAT),
251  'text'
252  );
253 
254  $conditions = [
255  $this->db->in(
256  self::PROGRESS_FIELD_STATUS,
257  [
260  ],
261  false,
262  'integer'
263  ),
264  self::PROGRESS_FIELD_DEADLINE . ' IS NOT NULL',
265  self::PROGRESS_FIELD_DEADLINE . ' < ' . $deadline
266  ];
267 
268  $assignments = array_filter(iterator_to_array(
269  $this->read($conditions)
270  ));
271  return $assignments;
272  }
273 
274  public function getAboutToExpire(
275  array $programmes_and_due,
276  bool $discard_formerly_notified = true
277  ): array {
278  $ret = [];
279  if (count($programmes_and_due) == 0) {
280  return $ret;
281  }
282 
283  $where = [];
284  foreach ($programmes_and_due as $prg_obj_id => $due) {
285  $due = $due->format(self::DATE_FORMAT_ENDOFDAY);
286 
287  $where_clause = '('
288  . self::PROGRESS_FIELD_VQ_DATE . '<=' . $this->db->quote($due, 'text')
289  . ' AND (pgs.' . self::PROGRESS_FIELD_PRG_ID . '=' . $prg_obj_id
290  . ' OR ' . self::ASSIGNMENT_FIELD_ROOT_PRG_ID . '=' . $prg_obj_id . ')';
291 
292  if ($discard_formerly_notified) {
293  $where_clause .= ' AND ' . self::PROGRESS_FIELD_MAIL_SENT_WILLEXPIRE . ' IS NULL';
294  }
295 
296  $where_clause .= ')';
297  $where[] = $where_clause;
298  }
299 
300  $conditions = [
301  implode(' OR ', $where)
302  ];
303  $assignments = array_filter(iterator_to_array(
304  $this->read($conditions)
305  ));
306  return $assignments;
307  }
308 
309  public function getExpiredAndNotInvalidated(): array
310  {
311  $now = (new \DateTimeImmutable())->format(self::DATE_FORMAT_ENDOFDAY);
312  $conditions = [
313  $this->db->in(
314  self::PROGRESS_FIELD_STATUS,
315  [
318  ],
319  false,
320  'integer'
321  ),
322  self::PROGRESS_FIELD_VQ_DATE . ' IS NOT NULL',
323  self::PROGRESS_FIELD_VQ_DATE . ' < ' . $this->db->quote($now, 'text'),
324  self::PROGRESS_FIELD_INVALIDATED . ' = 0 ',
325  ];
326 
327  $assignments = array_filter(iterator_to_array(
328  $this->read($conditions)
329  ));
330  return $assignments;
331  }
332 
333 
334  public function getRiskyToFail(
335  array $programmes_and_due,
336  bool $discard_formerly_notified = true
337  ): array {
338  $ret = [];
339  if (count($programmes_and_due) == 0) {
340  return $ret;
341  }
342 
343  $where = [];
344  foreach ($programmes_and_due as $prg_obj_id => $due) {
345  $due = $due->format(ilPRGProgress::DATE_FORMAT);
346 
347  $where_clause = '('
348  . self::PROGRESS_FIELD_DEADLINE . '<=' . $this->db->quote($due, 'text')
349  . 'AND (pgs.' . self::PROGRESS_FIELD_PRG_ID . '=' . $prg_obj_id
350  . ' OR ' . self::ASSIGNMENT_FIELD_ROOT_PRG_ID . '=' . $prg_obj_id . ')'
351  . ' AND ' . $this->db->in(
352  self::PROGRESS_FIELD_STATUS,
353  [
357  ],
358  true,
359  'integer'
360  );
361 
362  if ($discard_formerly_notified) {
363  $where_clause .= ' AND ' . self::PROGRESS_FIELD_MAIL_SENT_RISKYTOFAIL . ' IS NULL';
364  }
365 
366  $where_clause .= ')';
367  $where[] = $where_clause;
368  }
369 
370  $conditions = [
371  implode(' OR ', $where)
372  ];
373  $assignments = array_filter(iterator_to_array(
374  $this->read($conditions)
375  ));
376  return $assignments;
377  }
378 
379 
380 
381  protected function query($filter): ilDBStatement
382  {
383  $q = 'SELECT'
384  . ' ass.' . self::ASSIGNMENT_FIELD_ID . ' AS ' . self::ASSIGNMENT_FIELD_ID
385  . ', ass.' . self::ASSIGNMENT_FIELD_USR_ID . ' AS ' . self::ASSIGNMENT_FIELD_USR_ID
386  . ',' . self::ASSIGNMENT_FIELD_ROOT_PRG_ID
387  . ', ass.' . self::ASSIGNMENT_FIELD_LAST_CHANGE
388  . ', ass.' . self::ASSIGNMENT_FIELD_LAST_CHANGE_BY
389  . ',' . self::ASSIGNMENT_FIELD_RESTART_DATE
390  . ',' . self::ASSIGNMENT_FIELD_RESTARTED_ASSIGNMENT_ID
391  . ',' . self::ASSIGNMENT_FIELD_MANUALLY_ASSIGNED
392  . ',' . self::PROGRESS_FIELD_PRG_ID
393  . ',' . self::PROGRESS_FIELD_POINTS
394  . ',' . self::PROGRESS_FIELD_POINTS_CUR
395  . ',' . self::PROGRESS_FIELD_STATUS
396  . ',' . self::PROGRESS_FIELD_COMPLETION_BY
397  . ',' . self::PROGRESS_FIELD_ASSIGNMENT_DATE
398  . ', pgs.' . self::PROGRESS_FIELD_LAST_CHANGE . ' AS p_' . self::PROGRESS_FIELD_LAST_CHANGE
399  . ', pgs.' . self::PROGRESS_FIELD_LAST_CHANGE_BY . ' AS p_' . self::PROGRESS_FIELD_LAST_CHANGE_BY
400  . ',' . self::PROGRESS_FIELD_COMPLETION_DATE
401  . ',' . self::PROGRESS_FIELD_DEADLINE
402  . ',' . self::PROGRESS_FIELD_VQ_DATE
403  . ',' . self::PROGRESS_FIELD_INVALIDATED
404  . ',' . self::PROGRESS_FIELD_MAIL_SENT_RISKYTOFAIL
405  . ',' . self::PROGRESS_FIELD_MAIL_SENT_WILLEXPIRE
406  . ',' . self::PROGRESS_FIELD_IS_INDIVIDUAL
407 
408  . ', ' . implode(', ', ilPRGUserInformation::COLNAMES)
409 
410  . ' FROM ' . self::ASSIGNMENT_TABLE . ' ass '
411  . ' JOIN ' . self::PROGRESS_TABLE . ' pgs '
412  . ' ON ass.' . self::ASSIGNMENT_FIELD_ID . ' = pgs.' . self::PROGRESS_FIELD_ASSIGNMENT_ID
413 
414 
415  . ' JOIN usr_data memberdata ON ass.usr_id = memberdata.usr_id '
416 
417  . ' WHERE TRUE AND ';
418  $q = $q . implode(' AND ', $filter);
419  $q = $q . ' ORDER BY assignment_id, ass.usr_id';
420 
421  $res = $this->db->query($q);
422  return $res;
423  }
424 
425  protected function nextId()
426  {
427  return $this->db->nextId(self::ASSIGNMENT_TABLE);
428  }
429 
430  protected function count(array $filter): int
431  {
432  $res = $this->query($filter);
433  return $this->db->numRows($res);
434  }
435 
436  protected function read(array $filter): Generator
437  {
438  $res = $this->query($filter);
439 
440  $current_ass = -1;
441  $ass = null;
442 
443  while ($row = $this->db->fetchAssoc($res)) {
444  if ($row[self::ASSIGNMENT_FIELD_ID] !== $current_ass) {
445  $current_ass = $row[self::ASSIGNMENT_FIELD_ID];
446  if (!is_null($ass)) {
447  yield $ass;
448  }
449  $this->progresses = $this->prebuildProgressesForAssingment((int) $row[self::ASSIGNMENT_FIELD_ID]);
450  $ass = $this->assignmentByRow($row); //amend all progresses based on tree
451  }
452  }
453 
454  yield $ass;
455  }
456 
457 
458  protected function prebuildProgressesForAssingment(int $assignment_id): array
459  {
460  $q = 'SELECT * FROM ' . self::PROGRESS_TABLE
461  . ' WHERE ' . self::PROGRESS_FIELD_ASSIGNMENT_ID . ' = ' . $assignment_id;
462  $res = $this->db->query($q);
463  while ($row = $this->db->fetchAssoc($res)) {
464  $ret[$row[self::PROGRESS_FIELD_PRG_ID]] = $this->buildProgressByRow($row);
465  }
466  return $ret;
467  }
468 
469  protected function assignmentByRow(array $row): ilPRGAssignment
470  {
471  $ass = new ilPRGAssignment(
472  (int) $row[self::ASSIGNMENT_FIELD_ID],
473  (int) $row[self::ASSIGNMENT_FIELD_USR_ID]
474  );
475  $ass = $ass
476  ->withEvents($this->events)
477  ->withLastChange(
478  (int) $row[self::ASSIGNMENT_FIELD_LAST_CHANGE_BY],
479  \DateTimeImmutable::createFromFormat(
481  $row[self::ASSIGNMENT_FIELD_LAST_CHANGE]
482  )
483  )
484  ->withRestarted(
485  (int) $row[self::ASSIGNMENT_FIELD_RESTARTED_ASSIGNMENT_ID],
486  $row[self::ASSIGNMENT_FIELD_RESTART_DATE] ?
487  \DateTimeImmutable::createFromFormat(ilPRGAssignment::DATE_TIME_FORMAT, $row[self::ASSIGNMENT_FIELD_RESTART_DATE]) :
488  null
489  )
490  ->withManuallyAssigned((bool) $row[self::ASSIGNMENT_FIELD_MANUALLY_ASSIGNED]);
491 
492 
493  $root_pgs_id = (int) $row[self::ASSIGNMENT_FIELD_ROOT_PRG_ID];
494  $pgs = $this->buildProgressTreeFor($root_pgs_id);
495 
496  $user_information = $this->buildUserInformation($row);
497 
498  $ass = $ass
499  ->withProgressTree($pgs)
500  ->withUserInformation($user_information);
501  return $ass;
502  }
503 
504 
505  protected function buildProgressTreeFor(int $node_obj_id): ilPRGProgress
506  {
507  $children = array_filter(
508  $this->tree->getChilds($this->getRefIdFor($node_obj_id)),
509  fn ($c) => in_array($c['type'], ['prg', 'prgr']),
510  );
511  $children = array_map(
512  fn ($c) => $c['type'] === 'prg' ? (int) $c['obj_id'] : ilContainerReference::_lookupTargetId((int) $c['obj_id']),
513  $children
514  );
515 
516  $pgss = [];
517  foreach ($children as $child_obj_id) {
518  $pgss[] = $this->buildProgressTreeFor($child_obj_id);
519  }
520 
521  if (!array_key_exists($node_obj_id, $this->progresses)) {
522  $pgs = new ilPRGProgress((int) $node_obj_id);
523  } else {
524  $pgs = $this->progresses[$node_obj_id];
525  }
526  $pgs->setSubnodes($pgss);
527  return $pgs;
528  }
529 
530 
531  protected function getRefIdFor(int $obj_id): int
532  {
533  $refs = ilObject::_getAllReferences($obj_id);
534  if (count($refs) < 1) {
535  throw new ilException("Could not find ref_id for programme with obj_id $obj_id");
536  }
537  return (int) array_shift($refs);
538  }
539  protected function getObjIdFor(int $ref_id): int
540  {
541  return (int) ilObject::_lookupObjectId($ref_id);
542  }
543 
544  protected function buildProgressByRow(array $row): ilPRGProgress
545  {
546  $pgs = new ilPRGProgress(
547  (int) $row[self::PROGRESS_FIELD_PRG_ID],
548  (int) $row[self::PROGRESS_FIELD_STATUS]
549  );
550 
551  $pgs = $pgs
552  ->withAmountOfPoints((int) $row[self::PROGRESS_FIELD_POINTS])
553  ->withCurrentAmountOfPoints((int) $row[self::PROGRESS_FIELD_POINTS_CUR])
554  ->withAssignmentDate(
555  $row[self::PROGRESS_FIELD_ASSIGNMENT_DATE] ?
556  \DateTimeImmutable::createFromFormat(ilPRGProgress::DATE_TIME_FORMAT, $row[self::PROGRESS_FIELD_ASSIGNMENT_DATE]) :
557  null
558  )
559  ->withDeadline(
560  $row[self::PROGRESS_FIELD_DEADLINE] ?
561  \DateTimeImmutable::createFromFormat(ilPRGProgress::DATE_FORMAT, $row[self::PROGRESS_FIELD_DEADLINE]) :
562  null
563  )
564  ->withCompletion(
565  (int) $row[self::PROGRESS_FIELD_COMPLETION_BY],
566  $row[self::PROGRESS_FIELD_COMPLETION_DATE] ?
567  \DateTimeImmutable::createFromFormat(ilPRGProgress::DATE_TIME_FORMAT, $row[self::PROGRESS_FIELD_COMPLETION_DATE]) :
568  null
569  )
570  ->withLastChange(
571  (int) $row[self::PROGRESS_FIELD_LAST_CHANGE_BY],
572  $row[self::PROGRESS_FIELD_LAST_CHANGE] ?
573  \DateTimeImmutable::createFromFormat(ilPRGProgress::DATE_TIME_FORMAT, $row[self::PROGRESS_FIELD_LAST_CHANGE]) :
574  null
575  )
576  ->withValidityOfQualification(
577  $row[self::PROGRESS_FIELD_VQ_DATE] ?
578  \DateTimeImmutable::createFromFormat(ilPRGProgress::DATE_TIME_FORMAT, $row[self::PROGRESS_FIELD_VQ_DATE]) :
579  null
580  )
581  ->withIndividualModifications((bool) $row[self::PROGRESS_FIELD_IS_INDIVIDUAL])
582  ->withInvalidated((bool) $row[self::PROGRESS_FIELD_INVALIDATED]);
583 
584  return $pgs;
585  }
586 
587 
591  protected function interimOrguLookup(int $usr_id): string
592  {
594  $orgus = array_values($orgu_repo->findAllUserAssingmentsByUserIds([$usr_id]));
595  if ($orgus) {
596  $orgu_ref_ids = array_map(
597  fn ($orgu_assignment) => $orgu_assignment->getOrguId(),
598  $orgus[0]
599  );
600  $orgus = array_map(
601  fn ($orgu_ref_id) => ilObject::_lookupTitle(ilObject::_lookupObjId($orgu_ref_id)),
602  $orgu_ref_ids
603  );
604  }
605  return implode(', ', $orgus);
606  }
607 
608  protected function buildUserInformation(array $row): ilPRGUserInformation
609  {
610  $udf_data = new ilUserDefinedData((int) $row[self::ASSIGNMENT_FIELD_USR_ID]);
611  $orgu_repr = ilObjUser::lookupOrgUnitsRepresentation((int) $row[self::ASSIGNMENT_FIELD_USR_ID]);
612 
613  $orgu_repr = $this->interimOrguLookup((int) $row[self::ASSIGNMENT_FIELD_USR_ID]);
614 
615  return new ilPRGUserInformation(
616  $udf_data,
617  $orgu_repr,
618  (string) $row['firstname'],
619  (string) $row['lastname'],
620  (string) $row['login'],
621  (bool) $row['active'],
622  (string) $row['email'],
623  (string) $row['gender'],
624  (string) $row['title']
625  );
626  }
627 
628  protected function insertAssignmentRowDB(array $row)
629  {
630  $this->db->insert(
631  self::ASSIGNMENT_TABLE,
632  [
633  self::ASSIGNMENT_FIELD_ID => ['integer', $row[self::ASSIGNMENT_FIELD_ID]]
634  , self::ASSIGNMENT_FIELD_USR_ID => ['integer', $row[self::ASSIGNMENT_FIELD_USR_ID]]
635  , self::ASSIGNMENT_FIELD_ROOT_PRG_ID => ['integer', $row[self::ASSIGNMENT_FIELD_ROOT_PRG_ID]]
636  , self::ASSIGNMENT_FIELD_LAST_CHANGE => ['text', $row[self::ASSIGNMENT_FIELD_LAST_CHANGE]]
637  , self::ASSIGNMENT_FIELD_LAST_CHANGE_BY => ['integer', $row[self::ASSIGNMENT_FIELD_LAST_CHANGE_BY]]
638  , self::ASSIGNMENT_FIELD_RESTART_DATE => ['timestamp', $row[self::ASSIGNMENT_FIELD_RESTART_DATE]]
639  , self::ASSIGNMENT_FIELD_RESTARTED_ASSIGNMENT_ID => ['integer', $row[self::ASSIGNMENT_FIELD_RESTARTED_ASSIGNMENT_ID]]
640  , self::ASSIGNMENT_FIELD_MANUALLY_ASSIGNED => ['integer', $row[self::ASSIGNMENT_FIELD_MANUALLY_ASSIGNED]]
641  ]
642  );
643  }
644 
645  protected function updateAssignmentRowDB(array $values)
646  {
647  $q = 'UPDATE ' . self::ASSIGNMENT_TABLE
648  . ' SET'
649  . ' ' . self::ASSIGNMENT_FIELD_USR_ID . ' = ' . $this->db->quote($values[self::ASSIGNMENT_FIELD_USR_ID], 'integer')
650  . ' ,' . self::ASSIGNMENT_FIELD_ROOT_PRG_ID . ' = ' . $this->db->quote($values[self::ASSIGNMENT_FIELD_ROOT_PRG_ID], 'integer')
651  . ' ,' . self::ASSIGNMENT_FIELD_LAST_CHANGE . ' = ' . $this->db->quote($values[self::ASSIGNMENT_FIELD_LAST_CHANGE], 'text')
652  . ' ,' . self::ASSIGNMENT_FIELD_LAST_CHANGE_BY . ' = ' . $this->db->quote($values[self::ASSIGNMENT_FIELD_LAST_CHANGE_BY], 'integer')
653  . ' ,' . self::ASSIGNMENT_FIELD_RESTART_DATE . ' = ' . $this->db->quote($values[self::ASSIGNMENT_FIELD_RESTART_DATE], 'timestamp')
654  . ' ,' . self::ASSIGNMENT_FIELD_RESTARTED_ASSIGNMENT_ID . ' = ' . $this->db->quote($values[self::ASSIGNMENT_FIELD_RESTARTED_ASSIGNMENT_ID], 'integer')
655  . ' ,' . self::ASSIGNMENT_FIELD_MANUALLY_ASSIGNED . ' = ' . $this->db->quote($values[self::ASSIGNMENT_FIELD_MANUALLY_ASSIGNED], 'integer')
656  . ' WHERE ' . self::ASSIGNMENT_FIELD_ID . ' = ' . $this->db->quote($values[self::ASSIGNMENT_FIELD_ID], 'integer');
657  $this->db->manipulate($q);
658  }
659 
660  protected function storeProgressRow(
661  int $assignment_id,
662  int $usr_id,
663  ilPRGProgress $pgs
664  ) {
665  //TODO: move into type?
666  $lastchange = is_null($pgs->getLastChange()) ? 'NULL' : $this->db->quote($pgs->getLastChange()->format(ilPRGProgress::DATE_TIME_FORMAT), 'text');
667  $assign_date = is_null($pgs->getAssignmentDate()) ? 'NULL' : $this->db->quote($pgs->getAssignmentDate()->format(ilPRGProgress::DATE_TIME_FORMAT), 'text');
668  $completion_date = is_null($pgs->getCompletionDate()) ? 'NULL' : $this->db->quote($pgs->getCompletionDate()->format(ilPRGProgress::DATE_TIME_FORMAT), 'text');
669  $deadline = is_null($pgs->getDeadline()) ? 'NULL' : $this->db->quote($pgs->getDeadline()->format(ilPRGProgress::DATE_FORMAT), 'text');
670  $validity = is_null($pgs->getValidityOfQualification()) ? 'NULL' : $this->db->quote($pgs->getValidityOfQualification()->format(ilPRGProgress::DATE_FORMAT), 'text');
671  $invalidated = $pgs->isInvalidated() ? 1 : 0;
672  $individual = $pgs->hasIndividualModifications() ? 1 : 0;
673  $completion = $pgs->getCompletionBy() ?? 'NULL';
674 
675  $q = 'INSERT INTO ' . self::PROGRESS_TABLE
676  . '('
677  . self::PROGRESS_FIELD_ASSIGNMENT_ID . ','
678  . self::PROGRESS_FIELD_USR_ID . ','
679  . self::PROGRESS_FIELD_PRG_ID . ','
680 
681  . self::PROGRESS_FIELD_STATUS . ','
682  . self::PROGRESS_FIELD_POINTS . ','
683  . self::PROGRESS_FIELD_POINTS_CUR . ','
684  . self::PROGRESS_FIELD_COMPLETION_BY . ','
685  . self::PROGRESS_FIELD_LAST_CHANGE_BY . ','
686  . self::PROGRESS_FIELD_LAST_CHANGE . ','
687  . self::PROGRESS_FIELD_ASSIGNMENT_DATE . ','
688  . self::PROGRESS_FIELD_COMPLETION_DATE . ','
689  . self::PROGRESS_FIELD_DEADLINE . ','
690  . self::PROGRESS_FIELD_VQ_DATE . ','
691  . self::PROGRESS_FIELD_INVALIDATED . ','
692  . self::PROGRESS_FIELD_IS_INDIVIDUAL
693 
694  . PHP_EOL . ') VALUES (' . PHP_EOL
695  . $assignment_id
696  . ' ,' . $usr_id
697  . ' ,' . $pgs->getNodeId()
698 
699  . ' ,' . $pgs->getStatus()
700  . ' ,' . $pgs->getAmountOfPoints()
701  . ' ,' . $pgs->getCurrentAmountOfPoints()
702  . ' ,' . $completion
703  . ' ,' . $pgs->getLastChangeBy()
704  . ' ,' . $lastchange
705  . ' ,' . $assign_date
706  . ' ,' . $completion_date
707  . ' ,' . $deadline
708  . ' ,' . $validity
709  . ' ,' . $invalidated
710  . ' ,' . $individual
711  . ')' . PHP_EOL
712  . 'ON DUPLICATE KEY UPDATE' . PHP_EOL
713  . self::PROGRESS_FIELD_STATUS . '=' . $pgs->getStatus() . ','
714  . self::PROGRESS_FIELD_POINTS . '=' . $pgs->getAmountOfPoints() . ','
715  . self::PROGRESS_FIELD_POINTS_CUR . '=' . $pgs->getCurrentAmountOfPoints() . ','
716  . self::PROGRESS_FIELD_COMPLETION_BY . '=' . $completion . ','
717  . self::PROGRESS_FIELD_LAST_CHANGE_BY . '=' . $pgs->getLastChangeBy() . ','
718  . self::PROGRESS_FIELD_LAST_CHANGE . '=' . $lastchange . ','
719  . self::PROGRESS_FIELD_ASSIGNMENT_DATE . '=' . $assign_date . ','
720  . self::PROGRESS_FIELD_COMPLETION_DATE . '=' . $completion_date . ','
721  . self::PROGRESS_FIELD_DEADLINE . '=' . $deadline . ','
722  . self::PROGRESS_FIELD_VQ_DATE . '=' . $validity . ','
723  . self::PROGRESS_FIELD_INVALIDATED . '=' . $invalidated . ','
724  . self::PROGRESS_FIELD_IS_INDIVIDUAL . '=' . $individual
725  ;
726  $this->db->manipulate($q);
727  }
728 
729 
730  public function storeExpiryInfoSentFor(ilPRGAssignment $ass): void
731  {
732  $where = [
733  self::PROGRESS_FIELD_ASSIGNMENT_ID => ['integer', $ass->getId()],
734  self::PROGRESS_FIELD_PRG_ID => ['integer', $ass->getRootId()]
735  ];
736 
737  $values = [
738  self::PROGRESS_FIELD_MAIL_SENT_WILLEXPIRE => [
739  'timestamp',
740  date('Y-m-d H:i:s')
741  ]
742  ];
743  $this->db->update(self::PROGRESS_TABLE, $values, $where);
744  }
745 
746  public function resetExpiryInfoSentFor(ilPRGAssignment $ass): void
747  {
748  $where = [
749  self::PROGRESS_FIELD_ASSIGNMENT_ID => ['integer', $ass->getId()],
750  self::PROGRESS_FIELD_PRG_ID => ['integer', $ass->getRootId()]
751  ];
752 
753  $values = [
754  self::PROGRESS_FIELD_MAIL_SENT_WILLEXPIRE => ['null', null]
755  ];
756  $this->db->update(self::PROGRESS_TABLE, $values, $where);
757  }
758 
759  public function storeRiskyToFailSentFor(ilPRGAssignment $ass): void
760  {
761  $where = [
762  self::PROGRESS_FIELD_ASSIGNMENT_ID => ['integer', $ass->getId()],
763  self::PROGRESS_FIELD_PRG_ID => ['integer', $ass->getRootId()]
764  ];
765 
766  $values = [
767  self::PROGRESS_FIELD_MAIL_SENT_RISKYTOFAIL => [
768  'timestamp',
769  date('Y-m-d H:i:s')
770  ]
771  ];
772  $this->db->update(self::PROGRESS_TABLE, $values, $where);
773  }
774 
775  public function resetRiskyToFailSentFor(ilPRGAssignment $ass): void
776  {
777  $where = [
778  self::PROGRESS_FIELD_ASSIGNMENT_ID => ['integer', $ass->getId()],
779  self::PROGRESS_FIELD_PRG_ID => ['integer', $ass->getRootId()]
780  ];
781 
782  $values = [
783  self::PROGRESS_FIELD_MAIL_SENT_RISKYTOFAIL => ['null', null]
784  ];
785  $this->db->update(self::PROGRESS_TABLE, $values, $where);
786  }
787 }
__construct(ilDBInterface $db, ilTree $tree, ilStudyProgrammeSettingsRepository $settings_repo, PRGEventsDelayed $events)
getForUser(int $usr_id)
get all assignments for a user
$res
Definition: ltiservices.php:69
$c
Definition: cli.php:38
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getRiskyToFail(array $programmes_and_due, bool $discard_formerly_notified=true)
static _getAllReferences(int $id)
get all reference ids for object ID
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getAllForSpecificNode(int $prg_obj_id, array $user_filter=null)
get all assignments for all (or given) users, where the given node is the root-node of the assignment...
createFor(int $prg_obj_id, int $usr_id, int $assigning_usr_id)
static lookupOrgUnitsRepresentation(int $a_usr_id)
lookup org unit representation
static now()
Return current timestamp in Y-m-d H:i:s format.
static _lookupObjId(int $ref_id)
A Progress is the status of a user on a single node of an assignment; it is unique by assignment_id:u...
$ref_id
Definition: ltiauth.php:67
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _lookupTitle(int $obj_id)
countAllForNodeIsContained(int $prg_obj_id, array $user_filter=null, ilPRGAssignmentFilter $custom_filters=null)
Count all assignments for all (or given) users, where the given node is part of the assignment...
getProgresses(array &$ret=[], ilPRGProgress $pgs=null)
static _lookupObjectId(int $ref_id)
$query
getPassedDeadline(\DateTimeImmutable $deadline)
storeProgressRow(int $assignment_id, int $usr_id, ilPRGProgress $pgs)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
static _lookupTargetId(int $a_obj_id)
ilStudyProgrammeSettingsRepository $settings_repo
getAllForNodeIsContained(int $prg_obj_id, array $user_filter=null, ilPRGAssignmentFilter $custom_filters=null)
get all assignments for all (or given) users, where the given node is part of the assignment ...
Assignments are relations of users to a PRG; They hold progress-information for (sub-)nodes of the PR...
getAboutToExpire(array $programmes_and_due, bool $discard_formerly_notified=true)
static _lookupType(int $id, bool $reference=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...