ILIAS  trunk Revision v13.0_alpha-52-g21c366bbdd4
class.ilBadgeHandler.php
Go to the documentation of this file.
1<?php
2
25
31{
32 public const GENERAL_INFO = 'inform_about_badges';
33
35 protected ilDBInterface $db;
36 protected ilTree $tree;
37 protected ilLanguage $lng;
39 protected static ?ilBadgeHandler $instance = null;
40
41 protected function __construct()
42 {
43 global $DIC;
44
45 if (isset($DIC['component.repository'])) {
46 $this->component_repository = $DIC['component.repository'];
47 }
48 $this->db = $DIC->database();
49 if (isset($DIC['tree'])) {
50 $this->tree = $DIC->repositoryTree();
51 }
52 $this->settings = new ilSetting('bdga');
53 }
54
55 public static function getInstance(): self
56 {
57 if (!self::$instance) {
58 self::$instance = new self();
59 }
60 return self::$instance;
61 }
62
63
64 //
65 // setter/getter
66 //
67
68 public function isActive(): bool
69 {
70 return (bool) $this->settings->get('active', '');
71 }
72
73 public function setActive(bool $a_value): void
74 {
75 $this->settings->set('active', (string) $a_value);
76 }
77
81 public function getComponents(): array
82 {
83 $components = $this->settings->get('components', null);
84 if ($components) {
85 return unserialize($components, ['allowed_classes' => false]);
86 }
87
88 return [];
89 }
90
91
95 public function setComponents(?array $a_components = null): void
96 {
97 if (isset($a_components) && count($a_components) === 0) {
98 $a_components = null;
99 }
100 $this->settings->set(
101 'components',
102 $a_components !== null
103 ? serialize(array_unique($a_components))
104 : ''
105 );
106 }
107
108
109 //
110 // component handling
111 //
112
113 protected function getComponent(string $a_id): ?array
114 {
115 if (!$this->component_repository->hasComponentId($a_id)) {
116 return null;
117 }
118 $component = $this->component_repository->getComponentById($a_id);
119 return [
120 'type' => $component->getType(),
121 'name' => $component->getName()
122 ];
123 }
124
125 public function getProviderInstance(string $a_component_id): ?ilBadgeProvider
126 {
127 $comp = $this->getComponent($a_component_id);
128 if ($comp) {
129 $class = 'il' . $comp['name'] . 'BadgeProvider';
130 $file = '../' . $comp['type'] . '/' . $comp['name'] . '/classes/class.' . $class . '.php';
131 if (file_exists($file)) {
132 $obj = new $class();
133 if ($obj instanceof ilBadgeProvider) {
134 return $obj;
135 }
136 }
137 }
138 return null;
139 }
140
141 public function getComponentCaption(string $a_component_id): string
142 {
143 $comp = $this->getComponent($a_component_id);
144 if ($comp) {
145 return $comp['type'] . '/' . $comp['name'];
146 }
147 return '';
148 }
149
150 //
151 // types
152 //
153
154 public function getUniqueTypeId(
155 string $a_component_id,
156 ilBadgeType $a_badge
157 ): string {
158 return $a_component_id . '/' . $a_badge->getId();
159 }
160
165 string $a_id
166 ): ?ilBadgeType {
167 $parts = explode('/', $a_id);
168 $comp_id = $parts[0];
169 $type_id = $parts[1];
170
171 $provider = $this->getProviderInstance($comp_id);
172 if ($provider) {
173 foreach ($provider->getBadgeTypes() as $type) {
174 if ($type->getId() === $type_id) {
175 return $type;
176 }
177 }
178 }
179 return null;
180 }
181
185 public function getInactiveTypes(): array
186 {
187 $types = $this->settings->get('inactive_types', null);
188 if ($types) {
189 return unserialize($types, ['allowed_classes' => false]);
190 }
191
192 return [];
193 }
194
198 public function setInactiveTypes(?array $a_types = null): void
199 {
200 if (is_array($a_types) &&
201 !count($a_types)) {
202 $a_types = null;
203 }
204 $this->settings->set(
205 'inactive_types',
206 $a_types !== null
207 ? serialize(array_unique($a_types))
208 : ''
209 );
210 }
211
216 public function getAvailableTypes(bool $exclude_inactive = true): array
217 {
218 $res = [];
219
220 $inactive = $this->getInactiveTypes();
221 foreach ($this->getComponents() as $component_id) {
222 $provider = $this->getProviderInstance($component_id);
223 if ($provider) {
224 foreach ($provider->getBadgeTypes() as $type) {
225 $id = $this->getUniqueTypeId($component_id, $type);
226 if (!$exclude_inactive || !in_array($id, $inactive, true)) {
227 $res[$id] = $type;
228 }
229 }
230 }
231 }
232
233 return $res;
234 }
235
240 public function getAvailableTypesForObjType(string $a_object_type): array
241 {
242 $res = [];
243
244 foreach ($this->getAvailableTypes() as $id => $type) {
245 if (in_array($a_object_type, $type->getValidObjectTypes(), true)) {
246 $res[$id] = $type;
247 }
248 }
249
250 return $res;
251 }
252
258 int $a_parent_obj_id,
259 ?string $a_parent_obj_type = null
260 ): array {
261 $res = [];
262
263 if (!$a_parent_obj_type) {
264 $a_parent_obj_type = ilObject::_lookupType($a_parent_obj_id);
265 }
266
267 $badges = ilBadge::getInstancesByParentId($a_parent_obj_id);
268 foreach (self::getInstance()->getAvailableTypesForObjType($a_parent_obj_type) as $type_id => $type) {
269 if (!$type instanceof ilBadgeAuto) {
270 foreach ($badges as $badge) {
271 if ($badge->getTypeId() === $type_id &&
272 $badge->isActive()) {
273 $res[$badge->getId()] = $badge->getTitle();
274 }
275 }
276 }
277 }
278
279 asort($res);
280 return $res;
281 }
282
283
284
285 //
286 // service/module definition
287 //
288
292 public static function updateFromXML(string $a_component_id): void
293 {
294 $handler = self::getInstance();
295 $components = $handler->getComponents();
296 $components[] = $a_component_id;
297 $handler->setComponents($components);
298 }
299
303 public static function clearFromXML(string $a_component_id): void
304 {
305 $handler = self::getInstance();
306 $components = $handler->getComponents();
307 foreach ($components as $idx => $component) {
308 if ($component === $a_component_id) {
309 unset($components[$idx]);
310 }
311 }
312 $handler->setComponents($components);
313 }
314
315
316 //
317 // helper
318 //
319
320 public function isObjectActive(
321 int $a_obj_id,
322 ?string $a_obj_type = null
323 ): bool {
324 if (!$this->isActive()) {
325 return false;
326 }
327
328 if (!$a_obj_type) {
329 $a_obj_type = ilObject::_lookupType($a_obj_id);
330 }
331
332 if ($a_obj_type !== 'bdga' && !ilContainer::_lookupContainerSetting(
333 $a_obj_id,
335 false
336 )) {
337 return false;
338 }
339
340 return true;
341 }
342
343 public function triggerEvaluation(
344 string $a_type_id,
345 int $a_user_id,
346 ?array $a_params = null
347 ): void {
348 if (!$this->isActive() || in_array($a_type_id, $this->getInactiveTypes(), true)) {
349 return;
350 }
351
352 $type = $this->getTypeInstanceByUniqueId($a_type_id);
353 if (!$type instanceof ilBadgeAuto) {
354 return;
355 }
356
357 $new_badges = [];
358 foreach (ilBadge::getInstancesByType($a_type_id) as $badge) {
359 if ($badge->isActive()) {
360 // already assigned?
361 if (!ilBadgeAssignment::exists($badge->getId(), $a_user_id)) {
362 if ($type->evaluate($a_user_id, (array) $a_params, $badge->getConfiguration())) {
363 $ass = new ilBadgeAssignment($badge->getId(), $a_user_id);
364 $ass->store();
365
366 $new_badges[$a_user_id][] = $badge->getId();
367 }
368 }
369 }
370 }
371
372 $this->sendNotification($new_badges);
373 }
374
380 public function getUserIds(
381 int $a_parent_ref_id,
382 ?int $a_parent_obj_id = null,
383 ?string $a_parent_type = null
384 ): array {
385 $tree = $this->tree;
386
387 if (!$a_parent_obj_id) {
388 $a_parent_obj_id = ilObject::_lookupObjectId($a_parent_ref_id);
389 }
390 if (!$a_parent_type) {
391 $a_parent_type = ilObject::_lookupType($a_parent_obj_id);
392 }
393
394 // try to get participants from (parent) course/group
395 switch ($a_parent_type) {
396 case 'crs':
397 $member_obj = ilCourseParticipants::_getInstanceByObjId($a_parent_obj_id);
398 return $member_obj->getMembers();
399
400 case 'grp':
401 $member_obj = ilGroupParticipants::_getInstanceByObjId($a_parent_obj_id);
402 return $member_obj->getMembers();
403
404 default:
405 // walk path to find course or group object and use members of that object
406 /* this does not work since getParticipantsForObject does not exist
407 $path = $tree->getPathId($a_parent_ref_id);
408 array_pop($path);
409 foreach (array_reverse($path) as $path_ref_id) {
410 $type = ilObject::_lookupType($path_ref_id, true);
411 if ($type == "crs" || $type == "grp") {
412 return $this->getParticipantsForObject($path_ref_id, null, $type);
413 }
414 }*/
415 break;
416 }
417 return [];
418 }
419
420
421 //
422 // PATH HANDLING (PUBLISHING)
423 //
424
425 protected function getBasePath(): string
426 {
427 return ilFileUtils::getWebspaceDir() . '/pub_badges/';
428 }
429
430 public function getInstancePath(ilBadgeAssignment $a_ass): string
431 {
432 $hash = md5($a_ass->getBadgeId() . '_' . $a_ass->getUserId());
433
434 $path = $this->getBasePath() . 'instances/' .
435 $a_ass->getBadgeId() . '/' .
436 floor($a_ass->getUserId() / 1000) . '/';
437
439
440 $path .= $hash . '.json';
441
442 return $path;
443 }
444
445 public function countStaticBadgeInstances(ilBadge $a_badge): int
446 {
447 $path = $this->getBasePath() . 'instances/' . $a_badge->getId();
448 $cnt = 0;
449 if (is_dir($path)) {
450 $this->countStaticBadgeInstancesHelper($cnt, $path);
451 }
452 return $cnt;
453 }
454
456 int &$a_cnt,
457 string $a_path
458 ): void {
459 foreach (glob($a_path . '/*') as $item) {
460 if (is_dir($item)) {
461 $this->countStaticBadgeInstancesHelper($a_cnt, $item);
462 } elseif (str_ends_with($item, '.json')) {
463 $a_cnt++;
464 }
465 }
466 }
467
468 public function getBadgePath(ilBadge $a_badge): string
469 {
470 $hash = md5($a_badge->getId());
471
472 $path = $this->getBasePath() . 'badges/' .
473 floor($a_badge->getId() / 100) . '/' .
474 $hash . '/';
475
477
478 return $path;
479 }
480
481
482 //
483 // notification
484 //
485
486 public function sendNotification(
487 array $a_user_map,
488 ?int $a_parent_ref_id = null
489 ): void {
490 $badges = [];
491
492 foreach ($a_user_map as $user_id => $badge_ids) {
493 $user_badges = [];
494
495 foreach ($badge_ids as $badge_id) {
496 // making extra sure
497 if (!ilBadgeAssignment::exists($badge_id, $user_id)) {
498 continue;
499 }
500
501 if (!array_key_exists($badge_id, $badges)) {
502 $badges[$badge_id] = new ilBadge($badge_id);
503 }
504
505 $badge = $badges[$badge_id];
506
507 $user_badges[] = $badge->getTitle();
508 }
509
510 if (count($user_badges)) {
511 // compose and send mail
512
513 $ntf = new ilSystemNotification(false);
514 $ntf->setLangModules(['badge']);
515
516 if (isset($a_parent_ref_id)) {
517 $ntf->setRefId($a_parent_ref_id);
518 }
519 $ntf->setGotoLangId('badge_notification_parent_goto');
520
521 // user specific language
522 $lng = $ntf->getUserLanguage($user_id);
523
524 $ntf->setIntroductionLangId('badge_notification_body');
525
526 $ntf->addAdditionalInfo('badge_notification_badges', implode("\n", $user_badges), true);
527
528 $url = ilLink::_getLink(null, 'badge', ['profile']);
529 $ntf->addAdditionalInfo('badge_notification_badges_goto', $url);
530
531 $ntf->setReasonLangId('badge_notification_reason');
532
533 // force email
534 $mail = new ilMail(ANONYMOUS_USER_ID);
535 $mail->enqueue(
537 '',
538 '',
539 $lng->txt('badge_notification_subject'),
540 $ntf->composeAndGetMessage($user_id, null, 'read', true),
541 MailAttachments::empty()
542 );
543
544
545 // osd
546 // bug #24562
547 if (ilContext::hasHTML()) {
548 $url = new ilNotificationLink(new ilNotificationParameter('badge_notification_badges_goto', [], 'badge'), $url);
549 $osd_params = ['badge_list' => implode(', ', $user_badges)];
550
551 $notification = new ilNotificationConfig(BadgeNotificationProvider::NOTIFICATION_TYPE);
552 $notification->setTitleVar('badge_notification_subject', [], 'badge');
553 $notification->setShortDescriptionVar('badge_notification_osd', $osd_params, 'badge');
554 $notification->setLongDescriptionVar('');
555 $notification->setLinks([$url]);
556 $notification->setIconPath(ilUtil::getImagePath('standard/icon_bdga.svg'));
557 $notification->setValidForSeconds(ilNotificationConfig::TTL_SHORT);
558 $notification->setVisibleForSeconds(ilNotificationConfig::DEFAULT_TTS);
559 $notification->setIdentification(new NotificationIdentification(
560 BadgeNotificationProvider::NOTIFICATION_TYPE,
561 self::GENERAL_INFO
562 ));
563 $notification->notifyByUsers([$user_id]);
564 }
565 }
566 }
567 }
568}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
$components
description of a localized parameter this information is used locate translations while processing no...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static exists(int $a_badge_id, int $a_user_id)
Class ilBadgeHandler.
static ilBadgeHandler $instance
getAvailableTypes(bool $exclude_inactive=true)
Get badges types.
getUniqueTypeId(string $a_component_id, ilBadgeType $a_badge)
static updateFromXML(string $a_component_id)
Import component definition.
setComponents(?array $a_components=null)
getProviderInstance(string $a_component_id)
setActive(bool $a_value)
getComponent(string $a_id)
getUserIds(int $a_parent_ref_id, ?int $a_parent_obj_id=null, ?string $a_parent_type=null)
sendNotification(array $a_user_map, ?int $a_parent_ref_id=null)
static clearFromXML(string $a_component_id)
Remove component definition.
triggerEvaluation(string $a_type_id, int $a_user_id, ?array $a_params=null)
getAvailableManualBadges(int $a_parent_obj_id, ?string $a_parent_obj_type=null)
Get available manual badges for object id.
getInstancePath(ilBadgeAssignment $a_ass)
getTypeInstanceByUniqueId(string $a_id)
Get type instance by unique id (component, type)
getBadgePath(ilBadge $a_badge)
getAvailableTypesForObjType(string $a_object_type)
Get valid badges types for object type.
ilComponentRepository $component_repository
countStaticBadgeInstances(ilBadge $a_badge)
isObjectActive(int $a_obj_id, ?string $a_obj_type=null)
countStaticBadgeInstancesHelper(int &$a_cnt, string $a_path)
getComponentCaption(string $a_component_id)
setInactiveTypes(?array $a_types=null)
static getInstancesByType(string $a_type_id)
static getInstancesByParentId(int $a_parent_id, ?array $a_filter=null)
static _lookupContainerSetting(int $a_id, string $a_keyword, ?string $a_default_value=null)
static hasHTML()
Has HTML output.
Definition: ilContext.php:125
static _getInstanceByObjId(int $a_obj_id)
static makeDirParents(string $a_dir)
Create a new directory and all parent directories.
static getWebspaceDir(string $mode="filesystem")
get webspace directory
static _getInstanceByObjId(int $a_obj_id)
Get singleton instance.
language handling
static _lookupEmail(int $a_user_id)
static _lookupObjectId(int $ref_id)
static _lookupType(int $id, bool $reference=false)
ILIAS Setting Class.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Tree class data representation in hierachical trees using the Nested Set Model with Gaps by Joe Celco...
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
const ANONYMOUS_USER_ID
Definition: constants.php:27
foreach( $report as $row)
return['3gp', '7z', 'ai', 'aif', 'aifc', 'aiff', 'au', 'arw', 'avi', 'backup', 'bak', 'bas', 'bpmn', 'bpmn2', 'bmp', 'bib', 'bibtex', 'bz', 'bz2', 'c', 'c++', 'cc', 'cct', 'cdf', 'cer', 'class', 'cls', 'conf', 'cpp', 'crt', 'crs', 'crw', 'cr2', 'css', 'cst', 'csv', 'cur', 'db', 'dcr', 'des', 'dng', 'doc', 'docx', 'dot', 'dotx', 'dtd', 'dvi', 'el', 'eps', 'epub', 'f', 'f77', 'f90', 'flv', 'for', 'g3', 'gif', 'gl', 'gan', 'ggb', 'gsd', 'gsm', 'gtar', 'gz', 'gzip', 'h', 'hpp', 'htm', 'html', 'htmls', 'ibooks', 'ico', 'ics', 'ini', 'ipynb', 'java', 'jbf', 'jpeg', 'jpg', 'js', 'jsf', 'jso', 'json', 'latex', 'lang', 'less', 'log', 'lsp', 'ltx', 'm1v', 'm2a', 'm2v', 'm3u', 'm4a', 'm4v', 'markdown', 'm', 'mat', 'md', 'mdl', 'mdown', 'mid', 'min', 'midi', 'mobi', 'mod', 'mov', 'movie', 'mp2', 'mp3', 'mp4', 'mpa', 'mpeg', 'mpg', 'mph', 'mpga', 'mpp', 'mpt', 'mpv', 'mpx', 'mv', 'mw', 'mv4', 'nb', 'nbp', 'nef', 'nif', 'niff', 'obj', 'obm', 'odt', 'ods', 'odp', 'odg', 'odf', 'oga', 'ogg', 'ogv', 'old', 'p', 'pas', 'pbm', 'pcl', 'pct', 'pcx', 'pdf', 'pgm', 'pic', 'pict', 'png', 'por', 'pov', 'project', 'properties', 'ppa', 'ppm', 'pps', 'ppsx', 'ppt', 'pptx', 'ppz', 'ps', 'psd', 'pwz', 'qt', 'qtc', 'qti', 'qtif', 'r', 'ra', 'ram', 'rar', 'rast', 'rda', 'rev', 'rexx', 'ris', 'rf', 'rgb', 'rm', 'rmd', 'rmi', 'rmm', 'rmp', 'rt', 'rtf', 'rtx', 'rv', 's', 's3m', 'sav', 'sbs', 'sec', 'sdml', 'sgm', 'sgml', 'smi', 'smil', 'srt', 'sps', 'spv', 'stl', 'svg', 'swa', 'swf', 'swz', 'tar', 'tex', 'texi', 'texinfo', 'text', 'tgz', 'tif', 'tiff', 'ttf', 'txt', 'tmp', 'uvproj', 'vdf', 'vimeo', 'viv', 'vivo', 'vrml', 'vsdx', 'vtt', 'wav', 'webm', 'wmv', 'wmx', 'wmz', 'woff', 'wwd', 'xhtml', 'xif', 'xls', 'xlsx', 'xmind', 'xml', 'xsl', 'xsd', 'zip']
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...
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...
Readable part of repository interface to ilComponentDataDB.
Interface ilDBInterface.
$handler
Definition: oai.php:31
global $lng
Definition: privfeed.php:26
foreach($_POST as $key=> $value) $res
if(!file_exists('../ilias.ini.php'))
global $DIC
Definition: shib_login.php:26