ILIAS  release_8 Revision v8.24
class.ilBadgeHandler.php
Go to the documentation of this file.
1<?php
2
24
30{
31 public const GENERAL_INFO = 'inform_about_badges';
32
34 protected ilDBInterface $db;
35 protected ilTree $tree;
36 protected ilLanguage $lng;
38 protected static ?ilBadgeHandler $instance = null;
39
40 protected function __construct()
41 {
42 global $DIC;
43
44 if (isset($DIC["component.repository"])) {
45 $this->component_repository = $DIC["component.repository"];
46 }
47 $this->db = $DIC->database();
48 if (isset($DIC["tree"])) {
49 $this->tree = $DIC->repositoryTree();
50 }
51 $this->settings = new ilSetting("bdga");
52 }
53
54 public static function getInstance(): self
55 {
56 if (!self::$instance) {
57 self::$instance = new self();
58 }
59 return self::$instance;
60 }
61
62
63 //
64 // setter/getter
65 //
66
67 public function isActive(): bool
68 {
69 return (bool) $this->settings->get("active", "");
70 }
71
72 public function setActive(bool $a_value): void
73 {
74 $this->settings->set("active", (string) $a_value);
75 }
76
80 public function getComponents(): array
81 {
82 $components = $this->settings->get("components", null);
83 if ($components) {
84 return unserialize($components, ["allowed_classes" => false]);
85 }
86
87 return [];
88 }
89
90
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("components", $a_components !== null
101 ? serialize(array_unique($a_components))
102 : "");
103 }
104
105
106 //
107 // component handling
108 //
109
110 protected function getComponent(string $a_id): ?array
111 {
112 if (!$this->component_repository->hasComponentId($a_id)) {
113 return null;
114 }
115 $component = $this->component_repository->getComponentById($a_id);
116 return [
117 "type" => $component->getType(),
118 "name" => $component->getName()
119 ];
120 }
121
122 public function getProviderInstance(string $a_component_id): ?ilBadgeProvider
123 {
124 $comp = $this->getComponent($a_component_id);
125 if ($comp) {
126 $class = "il" . $comp["name"] . "BadgeProvider";
127 $file = $comp["type"] . "/" . $comp["name"] . "/classes/class." . $class . ".php";
128 if (file_exists($file)) {
129 $obj = new $class();
130 if ($obj instanceof ilBadgeProvider) {
131 return $obj;
132 }
133 }
134 }
135 return null;
136 }
137
138 public function getComponentCaption(string $a_component_id): string
139 {
140 $comp = $this->getComponent($a_component_id);
141 if ($comp) {
142 return $comp["type"] . "/" . $comp["name"];
143 }
144 return "";
145 }
146
147 //
148 // types
149 //
150
151 public function getUniqueTypeId(
152 string $a_component_id,
153 ilBadgeType $a_badge
154 ): string {
155 return $a_component_id . "/" . $a_badge->getId();
156 }
157
162 string $a_id
163 ): ?ilBadgeType {
164 $parts = explode("/", $a_id);
165 $comp_id = $parts[0];
166 $type_id = $parts[1];
167
168 $provider = $this->getProviderInstance($comp_id);
169 if ($provider) {
170 foreach ($provider->getBadgeTypes() as $type) {
171 if ($type->getId() === $type_id) {
172 return $type;
173 }
174 }
175 }
176 return null;
177 }
178
182 public function getInactiveTypes(): array
183 {
184 $types = $this->settings->get("inactive_types", null);
185 if ($types) {
186 return unserialize($types, ["allowed_classes" => false]);
187 }
188
189 return [];
190 }
191
196 public function setInactiveTypes(array $a_types = null): void
197 {
198 if (is_array($a_types) &&
199 !count($a_types)) {
200 $a_types = null;
201 }
202 $this->settings->set("inactive_types", $a_types !== null
203 ? serialize(array_unique($a_types))
204 : "");
205 }
206
211 public function getAvailableTypes(bool $exclude_inactive = true): array
212 {
213 $res = [];
214
215 $inactive = $this->getInactiveTypes();
216 foreach ($this->getComponents() as $component_id) {
217 $provider = $this->getProviderInstance($component_id);
218 if ($provider) {
219 foreach ($provider->getBadgeTypes() as $type) {
220 $id = $this->getUniqueTypeId($component_id, $type);
221 if (!$exclude_inactive || !in_array($id, $inactive, true)) {
222 $res[$id] = $type;
223 }
224 }
225 }
226 }
227
228 return $res;
229 }
230
235 public function getAvailableTypesForObjType(string $a_object_type): array
236 {
237 $res = [];
238
239 foreach ($this->getAvailableTypes() as $id => $type) {
240 if (in_array($a_object_type, $type->getValidObjectTypes(), true)) {
241 $res[$id] = $type;
242 }
243 }
244
245 return $res;
246 }
247
253 int $a_parent_obj_id,
254 string $a_parent_obj_type = null
255 ): array {
256 $res = [];
257
258 if (!$a_parent_obj_type) {
259 $a_parent_obj_type = ilObject::_lookupType($a_parent_obj_id);
260 }
261
262 $badges = ilBadge::getInstancesByParentId($a_parent_obj_id);
263 foreach (self::getInstance()->getAvailableTypesForObjType($a_parent_obj_type) as $type_id => $type) {
264 if (!$type instanceof ilBadgeAuto) {
265 foreach ($badges as $badge) {
266 if ($badge->getTypeId() === $type_id &&
267 $badge->isActive()) {
268 $res[$badge->getId()] = $badge->getTitle();
269 }
270 }
271 }
272 }
273
274 asort($res);
275 return $res;
276 }
277
278
279
280 //
281 // service/module definition
282 //
283
287 public static function updateFromXML(string $a_component_id): void
288 {
289 $handler = self::getInstance();
290 $components = $handler->getComponents();
291 $components[] = $a_component_id;
292 $handler->setComponents($components);
293 }
294
298 public static function clearFromXML(string $a_component_id): void
299 {
300 $handler = self::getInstance();
301 $components = $handler->getComponents();
302 foreach ($components as $idx => $component) {
303 if ($component === $a_component_id) {
304 unset($components[$idx]);
305 }
306 }
307 $handler->setComponents($components);
308 }
309
310
311 //
312 // helper
313 //
314
315 public function isObjectActive(
316 int $a_obj_id,
317 ?string $a_obj_type = null
318 ): bool {
319 if (!$this->isActive()) {
320 return false;
321 }
322
323 if (!$a_obj_type) {
324 $a_obj_type = ilObject::_lookupType($a_obj_id);
325 }
326
327 if ($a_obj_type !== "bdga" && !ilContainer::_lookupContainerSetting(
328 $a_obj_id,
330 false
331 )) {
332 return false;
333 }
334
335 return true;
336 }
337
338 public function triggerEvaluation(
339 string $a_type_id,
340 int $a_user_id,
341 array $a_params = null
342 ): void {
343 if (!$this->isActive() || in_array($a_type_id, $this->getInactiveTypes(), true)) {
344 return;
345 }
346
347 $type = $this->getTypeInstanceByUniqueId($a_type_id);
348 if (!$type instanceof ilBadgeAuto) {
349 return;
350 }
351
352 $new_badges = [];
353 foreach (ilBadge::getInstancesByType($a_type_id) as $badge) {
354 if ($badge->isActive()) {
355 // already assigned?
356 if (!ilBadgeAssignment::exists($badge->getId(), $a_user_id)) {
357 if ($type->evaluate($a_user_id, (array) $a_params, $badge->getConfiguration())) {
358 $ass = new ilBadgeAssignment($badge->getId(), $a_user_id);
359 $ass->store();
360
361 $new_badges[$a_user_id][] = $badge->getId();
362 }
363 }
364 }
365 }
366
367 $this->sendNotification($new_badges);
368 }
369
376 public function getUserIds(
377 int $a_parent_ref_id,
378 int $a_parent_obj_id = null,
379 string $a_parent_type = null
380 ): array {
381 $tree = $this->tree;
382
383 if (!$a_parent_obj_id) {
384 $a_parent_obj_id = ilObject::_lookupObjectId($a_parent_ref_id);
385 }
386 if (!$a_parent_type) {
387 $a_parent_type = ilObject::_lookupType($a_parent_obj_id);
388 }
389
390 // try to get participants from (parent) course/group
391 switch ($a_parent_type) {
392 case "crs":
393 $member_obj = ilCourseParticipants::_getInstanceByObjId($a_parent_obj_id);
394 return $member_obj->getMembers();
395
396 case "grp":
397 $member_obj = ilGroupParticipants::_getInstanceByObjId($a_parent_obj_id);
398 return $member_obj->getMembers();
399
400 default:
401 // walk path to find course or group object and use members of that object
402 /* this does not work since getParticipantsForObject does not exist
403 $path = $tree->getPathId($a_parent_ref_id);
404 array_pop($path);
405 foreach (array_reverse($path) as $path_ref_id) {
406 $type = ilObject::_lookupType($path_ref_id, true);
407 if ($type == "crs" || $type == "grp") {
408 return $this->getParticipantsForObject($path_ref_id, null, $type);
409 }
410 }*/
411 break;
412 }
413 return [];
414 }
415
416
417 //
418 // PATH HANDLING (PUBLISHING)
419 //
420
421 protected function getBasePath(): string
422 {
423 return ilFileUtils::getWebspaceDir() . "/pub_badges/";
424 }
425
426 public function getInstancePath(ilBadgeAssignment $a_ass): string
427 {
428 $hash = md5($a_ass->getBadgeId() . "_" . $a_ass->getUserId());
429
430 $path = $this->getBasePath() . "instances/" .
431 $a_ass->getBadgeId() . "/" .
432 floor($a_ass->getUserId() / 1000) . "/";
433
435
436 $path .= $hash . ".json";
437
438 return $path;
439 }
440
441 public function countStaticBadgeInstances(ilBadge $a_badge): int
442 {
443 $path = $this->getBasePath() . "instances/" . $a_badge->getId();
444 $cnt = 0;
445 if (is_dir($path)) {
446 $this->countStaticBadgeInstancesHelper($cnt, $path);
447 }
448 return $cnt;
449 }
450
452 int &$a_cnt,
453 string $a_path
454 ): void {
455 foreach (glob($a_path . "/*") as $item) {
456 if (is_dir($item)) {
457 $this->countStaticBadgeInstancesHelper($a_cnt, $item);
458 } elseif (substr($item, -5) === ".json") {
459 $a_cnt++;
460 }
461 }
462 }
463
464 public function getBadgePath(ilBadge $a_badge): string
465 {
466 $hash = md5($a_badge->getId());
467
468 $path = $this->getBasePath() . "badges/" .
469 floor($a_badge->getId() / 100) . "/" .
470 $hash . "/";
471
473
474 return $path;
475 }
476
477
478 //
479 // notification
480 //
481
482 public function sendNotification(
483 array $a_user_map,
484 int $a_parent_ref_id = null
485 ): void {
486 $badges = [];
487
488 foreach ($a_user_map as $user_id => $badge_ids) {
489 $user_badges = [];
490
491 foreach ($badge_ids as $badge_id) {
492 // making extra sure
493 if (!ilBadgeAssignment::exists($badge_id, $user_id)) {
494 continue;
495 }
496
497 if (!array_key_exists($badge_id, $badges)) {
498 $badges[$badge_id] = new ilBadge($badge_id);
499 }
500
501 $badge = $badges[$badge_id];
502
503 $user_badges[] = $badge->getTitle();
504 }
505
506 if (count($user_badges)) {
507 // compose and send mail
508
509 $ntf = new ilSystemNotification(false);
510 $ntf->setLangModules(["badge"]);
511
512 if (isset($a_parent_ref_id)) {
513 $ntf->setRefId($a_parent_ref_id);
514 }
515 $ntf->setGotoLangId("badge_notification_parent_goto");
516
517 // user specific language
518 $lng = $ntf->getUserLanguage($user_id);
519
520 $ntf->setIntroductionLangId("badge_notification_body");
521
522 $ntf->addAdditionalInfo("badge_notification_badges", implode("\n", $user_badges), true);
523
524 $url = ilLink::_getLink($user_id, "usr", [], "_bdg");
525 $ntf->addAdditionalInfo("badge_notification_badges_goto", $url);
526
527 $ntf->setReasonLangId("badge_notification_reason");
528
529 // force email
530 $mail = new ilMail(ANONYMOUS_USER_ID);
531 $mail->enqueue(
532 ilObjUser::_lookupEmail($user_id),
533 "",
534 "",
535 $lng->txt("badge_notification_subject"),
536 $ntf->composeAndGetMessage($user_id, null, "read", true),
537 []
538 );
539
540
541 // osd
542 // bug #24562
543 if (ilContext::hasHTML()) {
544 $url = new ilNotificationLink(new ilNotificationParameter('badge_notification_badges_goto', [], 'badge'), $url);
545 $osd_params = ["badge_list" => implode(", ", $user_badges)];
546
547 $notification = new ilNotificationConfig(BadgeNotificationProvider::NOTIFICATION_TYPE);
548 $notification->setTitleVar("badge_notification_subject", [], "badge");
549 $notification->setShortDescriptionVar("badge_notification_osd", $osd_params, "badge");
550 $notification->setLongDescriptionVar("");
551 $notification->setLinks([$url]);
552 $notification->setIconPath(ilUtil::getImagePath('icon_bdga.svg'));
553 $notification->setValidForSeconds(ilNotificationConfig::TTL_SHORT);
554 $notification->setVisibleForSeconds(ilNotificationConfig::DEFAULT_TTS);
555 $notification->setIdentification(new NotificationIdentification(
556 BadgeNotificationProvider::NOTIFICATION_TYPE,
557 self::GENERAL_INFO
558 ));
559 $notification->notifyByUsers([$user_id]);
560 }
561 }
562 }
563 }
564}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
description of a localized parameter this information is used locate translations while processing no...
return true
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
setInactiveTypes(array $a_types=null)
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)
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.
getAvailableManualBadges(int $a_parent_obj_id, string $a_parent_obj_type=null)
Get available manual badges for object id.
getProviderInstance(string $a_component_id)
setActive(bool $a_value)
setComponents(array $a_components=null)
getComponent(string $a_id)
static clearFromXML(string $a_component_id)
Remove component definition.
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
triggerEvaluation(string $a_type_id, int $a_user_id, array $a_params=null)
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)
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.
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)
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...
static getImagePath(string $img, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
if(!file_exists(getcwd() . '/ilias.ini.php'))
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: confirmReg.php:20
const ANONYMOUS_USER_ID
Definition: constants.php:27
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', 'wav', 'webm', 'wmv', 'wmx', 'wmz', 'woff', 'wwd', 'xhtml', 'xif', 'xls', 'xlsx', 'xmind', 'xml', 'xsl', 'xsd', 'zip']
global $DIC
Definition: feed.php:28
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.
$path
Definition: ltiservices.php:32
$res
Definition: ltiservices.php:69
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
Definition: ltitoken.php:64
$provider
Definition: ltitoken.php:83
$type
$url
$lng