ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.ilTimingsUser.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
13 {
14  private static $instances = array();
15 
16  private $container_obj_id = 0;
17  private $container_ref_id = 0;
18 
19  private $initialized = false;
20  private $item_ids = array();
21 
22 
23 
24 
28  protected function __construct($a_container_obj_id)
29  {
30  $this->container_obj_id = $a_container_obj_id;
31 
32  $refs = ilObject::_getAllReferences($a_container_obj_id);
33  $this->container_ref_id = end($refs);
34  }
35 
41  public static function getInstanceByContainerId($a_container_obj_id)
42  {
43  if (array_key_exists($a_container_obj_id, self::$instances)) {
44  return self::$instances[$a_container_obj_id];
45  }
46  return self::$instances[$a_container_obj_id] = new self($a_container_obj_id);
47  }
48 
52  public function getContainerObjId()
53  {
55  }
56 
60  public function getContainerRefId()
61  {
63  }
64 
65  public function getItemIds()
66  {
67  return $this->item_ids;
68  }
69 
73  public function init()
74  {
75  if ($this->initialized) {
76  return true;
77  }
78  $this->item_ids = $GLOBALS['tree']->getSubTreeIds($this->getContainerRefId());
79 
80  include_once './Services/Object/classes/class.ilObjectActivation.php';
81  ilObjectActivation::preloadData($this->item_ids);
82 
83  $this->initialized = true;
84  }
85 
86 
92  public function handleNewMembership($a_usr_id, ilDateTime $sub_date)
93  {
94  foreach ($this->getItemIds() as $item_ref_id) {
95  include_once './Services/Object/classes/class.ilObjectActivation.php';
96  $item = ilObjectActivation::getItem($item_ref_id);
97 
98  if ($item['timing_type'] != ilObjectActivation::TIMINGS_PRESETTING) {
99  continue;
100  }
101 
102  include_once './Modules/Course/classes/Timings/class.ilTimingUser.php';
103  $user_item = new ilTimingUser($item['obj_id'], $a_usr_id);
104 
105  $user_start = clone $sub_date;
106  $user_start->increment(IL_CAL_DAY, $item['suggestion_start_rel']);
107  $user_item->getStart()->setDate($user_start->get(IL_CAL_UNIX), IL_CAL_UNIX);
108 
109  $user_end = clone $sub_date;
110  $user_end->increment(IL_CAL_DAY, $item['suggestion_end_rel']);
111  $user_item->getEnd()->setDate($user_end->get(IL_CAL_UNIX), IL_CAL_UNIX);
112 
113  $user_item->update();
114  }
115  }
116 
121  public function handleUnsubscribe($a_usr_id)
122  {
123  global $DIC;
124 
125  $ilDB = $DIC->database();
126 
127  $query = 'DELETE FROM crs_timings_user WHERE ' . $ilDB->in('ref_id', $this->item_ids, false, 'integer') . ' ' .
128  'AND usr_id = ' . $ilDB->quote($a_usr_id, 'integer');
129 
130  $ilDB->manipulate($query);
131  }
132 
139  public static function lookupTimingsExceededByUser(array $a_user_ids)
140  {
141  $res = array();
142 
143  $meta = [];
144  foreach (self::lookupTimings($a_user_ids, $meta, true, true) as $user_ids) {
145  foreach ($user_ids as $user_id) {
146  $res[$user_id] = $user_id;
147  }
148  }
149  return array_values($res);
150  }
151 
160  public static function lookupTimings(array $a_user_ids, array &$a_meta = null, $a_only_exceeded = true)
161  {
162  global $DIC;
163 
164  $ilDB = $DIC->database();
165  $logger = $DIC->logger()->crs();
166 
167  $res = array();
168  $now = time();
169 
170 
171  // get all relevant courses
172  $course_members_map = ilParticipants::getUserMembershipAssignmentsByType($a_user_ids, ['crs'], true);
173  $logger->debug('Course membership assignments');
174  $logger->dump($course_members_map, \ilLogLevel::DEBUG);
175 
176  // lookup (course) timing settings
177  $query = 'SELECT crsi.obj_id sub_ref_id, oref.ref_id, oref.obj_id, crsi.suggestion_start' .
178  ',crsi.suggestion_end,crsi.changeable, crss.timing_mode' .
179  ' FROM crs_settings crss' .
180  ' JOIN object_reference oref ON (oref.obj_id = crss.obj_id AND oref.deleted IS NULL) ' .
181  ' JOIN crs_items crsi ON (crsi.parent_id = oref.ref_id)' .
182  ' JOIN object_reference iref ON (crsi.obj_id = iref.ref_id AND iref.deleted IS NULL) ' .
183  ' WHERE crss.view_mode = ' . $ilDB->quote(ilCourseConstants::IL_CRS_VIEW_TIMING, 'integer') .
184  ' AND ' . $ilDB->in('crss.obj_id', array_keys($course_members_map), false, 'integer') .
185  ' AND crsi.timing_type = ' . $ilDB->quote(ilObjectActivation::TIMINGS_PRESETTING, 'integer');
186 
187  $logger->debug($query);
188 
189  $set = $ilDB->query($query);
190  $user_relevant = $course_map = $course_parent_map = [];
191  while ($row = $ilDB->fetchAssoc($set)) {
192  $obj_id = $row['obj_id'];
193  $sub_ref_id = $row['sub_ref_id'];
194  $mode = $row['timing_mode'];
195 
196  // needed for course_map-lookup for user-relevant data (see below)
197  $course_parent_map[$row['sub_ref_id']] = $row['obj_id'];
198  $course_map[$row['obj_id']] = $row['ref_id'];
199 
200  // gather meta data
201  if (is_array($a_meta)) {
202  foreach ($a_user_ids as $user_id) {
203  // only if course member
204  if (in_array($user_id, $course_members_map[$obj_id])) {
205  $a_meta[$user_id][$sub_ref_id] = array(
206  'parent' => $row['ref_id']
207  );
208  }
209  }
210  }
211 
212  // preset all users with object setting
214  // gather meta data
215  if (is_array($a_meta)) {
216  foreach ($a_user_ids as $user_id) {
217  // only if course member
218  if (in_array($user_id, $course_members_map[$obj_id])) {
219  $a_meta[$user_id][$sub_ref_id]['start'] = $row['suggestion_start'];
220  $a_meta[$user_id][$sub_ref_id]['end'] = $row['suggestion_end'];
221  }
222  }
223  }
224 
225  if (
226  ($a_only_exceeded && ($row['suggestion_end'] && $row['suggestion_end'] < $now)) ||
227  (!$a_only_exceeded && ($row['suggestion_start'] && $row['suggestion_start'] < $now))
228  ) {
229  foreach ($a_user_ids as $user_id) {
230  // only if course member
231  if (in_array($user_id, $course_members_map[$obj_id])) {
232  $res[$sub_ref_id][$user_id] = $user_id;
233  }
234  }
235  }
236  }
237 
238  // gather all objects which might have user-specific settings
239  if ($row['changeable'] ||
241  $user_relevant[] = $sub_ref_id;
242  }
243  }
244 
245  if (count($user_relevant)) {
246  // get user-specific data
247  $query = 'SELECT * FROM crs_timings_user' .
248  ' WHERE ' . $ilDB->in('usr_id', $a_user_ids, false, 'integer') .
249  ' AND ' . $ilDB->in('ref_id', $user_relevant, false, 'integer');
250  $set = $ilDB->query($query);
251  ;
252  while ($row = $ilDB->fetchAssoc($set)) {
253  $ref_id = $row['ref_id'];
254  $user_id = $row['usr_id'];
255 
256  // only if course member
257  $crs_obj_id = $course_parent_map[$ref_id];
258  if (!in_array($user_id, $course_members_map[$crs_obj_id])) {
259  continue;
260  }
261 
262  // gather meta data
263  if (is_array($a_meta)) {
264  $a_meta[$user_id][$ref_id]['start'] = $row['sstart'];
265  $a_meta[$user_id][$ref_id]['end'] = $row['ssend'];
266  }
267 
268  if (
269  ($a_only_exceeded && $row['ssend'] && $row['ssend'] < $now) ||
270  (!$a_only_exceeded && $row['sstart'] && $row['sstart'] < $now)
271  ) {
272  $res[$ref_id][$user_id] = $user_id;
273  } else {
274  // if not exceeded remove preset data
275  unset($res[$ref_id][$user_id]);
276  }
277  }
278  }
279 
280 
281 
282  // clean-up/minimize the result
283  foreach (array_keys($res) as $ref_id) {
284  if (!sizeof($res[$ref_id])) {
285  if (isset($res['ref_id']) && !count($res['ref_id'])) {
286  unset($res[$ref_id]);
287  } else {
288  $res[$ref_id] = array_values($res[$ref_id]);
289  }
290  }
291  }
292 
293  if (isset($res) && count($res)) {
294  $obj_map = array();
295  $invalid_lp = self::getObjectsWithInactiveLP(array_keys($res), $obj_map);
296 
297  foreach (array_keys($res) as $ref_id) {
298  // invalid LP?
299  if (in_array($ref_id, $invalid_lp)) {
300  $res[$ref_id] = array();
301  }
302  // LP completed?
303  else {
304  $user_ids = $res[$ref_id];
305  if (count($user_ids)) {
306  $res[$ref_id] = array_diff(
307  $user_ids,
308  ilLPStatus::_lookupCompletedForObject($obj_map[$ref_id], $user_ids)
309  );
310  }
311  }
312 
313  // delete reference array, if no users are given anymore
314  if (!sizeof($res[$ref_id])) {
315  unset($res[$ref_id]);
316  }
317  }
318  }
319 
320  // #2176 - add course entries (1 exceeded sub-item is enough)
321  foreach ($res as $ref_id => $user_ids) {
322  // making sure one last time
323  if (!count($user_ids) && isset($res['ref_id'])) {
324  unset($res[$ref_id]);
325  } else {
326  $crs_obj_id = $course_parent_map[$ref_id];
327  $crs_ref_id = $course_map[$crs_obj_id];
328  if (!array_key_exists($crs_ref_id, $res)) {
329  $res[$crs_ref_id] = $user_ids;
330  } else {
331  $res[$crs_ref_id] = array_unique(array_merge($user_ids, $res[$crs_ref_id]));
332  }
333  }
334  }
335  return $res;
336  }
337 
345  public static function getObjectsWithInactiveLP(array $a_ref_ids, array &$a_obj_map = null)
346  {
347  global $DIC;
348 
349  $ilDB = $DIC->database();
350 
351  $res = array();
352  $query = 'SELECT oref.ref_id, oref.obj_id, od.type' .
353  ' FROM object_reference oref' .
354  ' JOIN object_data od ON (oref.obj_id = od.obj_id)' .
355  ' WHERE ' . $ilDB->in('oref.ref_id', $a_ref_ids, false, 'integer');
356  $set = $ilDB->query($query);
357  $item_map = $item_types = array();
358  while ($row = $ilDB->fetchAssoc($set)) {
359  $item_map[$row['ref_id']] = $row['obj_id'];
360  $item_types[$row['obj_id']] = $row['type'];
361  }
362 
363  $a_obj_map = $item_map;
364 
365  // LP modes
366  $db_modes = ilLPObjSettings::_lookupDBModeForObjects(array_values($item_map));
367 
368  $type_modes = array();
369  foreach ($a_ref_ids as $ref_id) {
370  $obj_id = $item_map[$ref_id];
371  $type = $item_types[$obj_id];
372 
374  $res[] = $ref_id;
375  continue;
376  }
377 
378  // use db mode
379  if (array_key_exists($obj_id, $db_modes)) {
380  $mode = $db_modes[$obj_id];
381  }
382  // use default
383  else {
384  if (!array_key_exists($type, $type_modes)) {
385  $type_modes[$type] = ilObjectLP::getInstance($obj_id);
386  $type_modes[$type] = $type_modes[$type]->getDefaultMode();
387  }
388  $mode = $type_modes[$type];
389  }
390 
393  $res[] = $ref_id;
394  }
395  }
396  return $res;
397  }
398 }
static getInstanceByContainerId($a_container_obj_id)
Get instance by container id.
__construct($a_container_obj_id)
Singleton constructor.
$type
global $DIC
Definition: saml.php:7
static isSupportedObjectType($a_type)
TableGUI class for timings administration.
static getItem($a_ref_id)
Get item data.
getContainerObjId()
Get container obj id.
handleNewMembership($a_usr_id, ilDateTime $sub_date)
const IL_CAL_UNIX
handleUnsubscribe($a_usr_id)
Handle unsubscribe.
static _getAllReferences($a_id)
get all reference ids of object
Handle user timings.
init()
Init activation items.
const IL_CAL_DAY
foreach($_POST as $key=> $value) $res
static lookupTimings(array $a_user_ids, array &$a_meta=null, $a_only_exceeded=true)
Lookup references, users with exceeded timings.
Date and time handling
$query
static preloadData(array $a_ref_ids)
Preload data to internal cache.
increment($a_type, $a_count=1)
increment
static _lookupDBModeForObjects(array $a_obj_ids)
$row
static getObjectsWithInactiveLP(array $a_ref_ids, array &$a_obj_map=null)
Check object LP modes.
global $ilDB
static lookupTimingsExceededByUser(array $a_user_ids)
Check if users currently exceeded ANY object.
static _lookupCompletedForObject($a_obj_id, $a_user_ids=null)
Get completed users for object.
static getUserMembershipAssignmentsByType($a_user_ids, $a_type, $a_only_member_roles)
Get user membership assignments by type.
static getInstance($a_obj_id)
getContainerRefId()
Get container ref_id.
$GLOBALS['JPEG_Segment_Names']
Global Variable: XMP_tag_captions.