ILIAS  release_7 Revision v7.30-3-g800a261c036
class.ilBadgeHandler.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
3
10{
14 protected $db;
15
19 protected $tree;
20
24 protected $lng;
25
26 protected $settings; // [ilSetting]
27
28 protected static $instance; // [ilBadgeHandler]
29
35 protected function __construct()
36 {
37 global $DIC;
38
39 $this->db = $DIC->database();
40 if (isset($DIC["tree"])) {
41 $this->tree = $DIC->repositoryTree();
42 }
43 $this->settings = new ilSetting("bdga");
44 }
45
51 public static function getInstance()
52 {
53 if (!self::$instance) {
54 self::$instance = new self();
55 }
56 return self::$instance;
57 }
58
59
60 //
61 // setter/getter
62 //
63
64 public function isActive()
65 {
66 return $this->settings->get("active", false);
67 }
68
69 public function setActive($a_value)
70 {
71 $this->settings->set("active", (bool) $a_value);
72 }
73
74 public function isObiActive()
75 {
76 // see bug #20124
77 return false;
78
79 return $this->settings->get("obi_active", false);
80 }
81
82 public function setObiActive($a_value)
83 {
84 $this->settings->set("obi_active", (bool) $a_value);
85 }
86
87 public function getObiOrganistation()
88 {
89 return $this->settings->get("obi_organisation", null);
90 }
91
92 public function setObiOrganisation($a_value)
93 {
94 $this->settings->set("obi_organisation", trim($a_value));
95 }
96
97 public function getObiContact()
98 {
99 return $this->settings->get("obi_contact", null);
100 }
101
102 public function setObiContact($a_value)
103 {
104 $this->settings->set("obi_contact", trim($a_value));
105 }
106
107 public function getObiSalt()
108 {
109 return $this->settings->get("obi_salt", null);
110 }
111
112 public function setObiSalt($a_value)
113 {
114 $this->settings->set("obi_salt", trim($a_value));
115 }
116
117 public function getComponents()
118 {
119 $components = $this->settings->get("components", null);
120 if ($components) {
121 return unserialize($components);
122 }
123 return array();
124 }
125
126 public function setComponents(array $a_components = null)
127 {
128 if (is_array($a_components) &&
129 !sizeof($a_components)) {
130 $a_components = null;
131 }
132 $this->settings->set("components", $a_components !== null
133 ? serialize(array_unique($a_components))
134 : null);
135 }
136
137
138 //
139 // component handling
140 //
141
142 protected function getComponent($a_id)
143 {
145
146 // see ilCtrl
147 $set = $ilDB->query("SELECT * FROM il_component" .
148 " WHERE id = " . $ilDB->quote($a_id, "text"));
149 $rec = $ilDB->fetchAssoc($set);
150 if ($rec["type"]) {
151 return $rec;
152 }
153 }
154
161 public function getProviderInstance($a_component_id)
162 {
163 $comp = $this->getComponent($a_component_id);
164 if ($comp) {
165 $class = "il" . $comp["name"] . "BadgeProvider";
166 $file = $comp["type"] . "/" . $comp["name"] . "/classes/class." . $class . ".php";
167 if (file_exists($file)) {
168 $obj = new $class;
169 if ($obj instanceof ilBadgeProvider) {
170 return $obj;
171 }
172 }
173 }
174 }
175
176 public function getComponentCaption($a_component_id)
177 {
178 $comp = $this->getComponent($a_component_id);
179 if ($comp) {
180 return $comp["type"] . "/" . $comp["name"];
181 }
182 }
183
184 //
185 // types
186 //
187
188 public function getUniqueTypeId($a_component_id, ilBadgeType $a_badge)
189 {
190 return $a_component_id . "/" . $a_badge->getId();
191 }
192
198 public function getTypeInstanceByUniqueId($a_id)
199 {
200 $parts = explode("/", $a_id);
201 $comp_id = $parts[0];
202 $type_id = $parts[1];
203 $provider = $this->getProviderInstance($comp_id);
204 if ($provider) {
205 foreach ($provider->getBadgeTypes() as $type) {
206 if ($type->getId() == $type_id) {
207 return $type;
208 }
209 }
210 }
211 }
212
213 public function getInactiveTypes()
214 {
215 $types = $this->settings->get("inactive_types", null);
216 if ($types) {
217 return unserialize($types);
218 }
219 return array();
220 }
221
222 public function setInactiveTypes(array $a_types = null)
223 {
224 if (is_array($a_types) &&
225 !sizeof($a_types)) {
226 $a_types = null;
227 }
228 $this->settings->set("inactive_types", $a_types !== null
229 ? serialize(array_unique($a_types))
230 : null);
231 }
232
238 public function getAvailableTypes()
239 {
240 $res = array();
241
242 $inactive = $this->getInactiveTypes();
243 foreach ($this->getComponents() as $component_id) {
244 $provider = $this->getProviderInstance($component_id);
245 if ($provider) {
246 foreach ($provider->getBadgeTypes() as $type) {
247 $id = $this->getUniqueTypeId($component_id, $type);
248 if (!in_array($id, $inactive)) {
249 $res[$id] = $type;
250 }
251 }
252 }
253 }
254
255 return $res;
256 }
257
264 public function getAvailableTypesForObjType($a_object_type)
265 {
266 $res = array();
267
268 foreach ($this->getAvailableTypes() as $id => $type) {
269 if (in_array($a_object_type, $type->getValidObjectTypes())) {
270 $res[$id] = $type;
271 }
272 }
273
274 return $res;
275 }
276
284 public function getAvailableManualBadges($a_parent_obj_id, $a_parent_obj_type = null)
285 {
286 $res = array();
287
288 if (!$a_parent_obj_type) {
289 $a_parent_obj_type = ilObject::_lookupType($a_parent_obj_id);
290 }
291
292 $badges = ilBadge::getInstancesByParentId($a_parent_obj_id);
293 foreach (ilBadgeHandler::getInstance()->getAvailableTypesForObjType($a_parent_obj_type) as $type_id => $type) {
294 if (!$type instanceof ilBadgeAuto) {
295 foreach ($badges as $badge) {
296 if ($badge->getTypeId() == $type_id &&
297 $badge->isActive()) {
298 $res[$badge->getId()] = $badge->getTitle();
299 }
300 }
301 }
302 }
303
304 asort($res);
305 return $res;
306 }
307
308
309
310 //
311 // service/module definition
312 //
313
319 public static function updateFromXML($a_component_id)
320 {
321 $handler = self::getInstance();
322 $components = $handler->getComponents();
323 $components[] = $a_component_id;
324 $handler->setComponents($components);
325 }
326
332 public static function clearFromXML($a_component_id)
333 {
334 $handler = self::getInstance();
335 $components = $handler->getComponents();
336 foreach ($components as $idx => $component) {
337 if ($component == $a_component_id) {
338 unset($components[$idx]);
339 }
340 }
341 $handler->setComponents($components);
342 }
343
344
345 //
346 // helper
347 //
348
349 public function isObjectActive($a_obj_id, $a_obj_type = null)
350 {
351 if (!$this->isActive()) {
352 return false;
353 }
354
355 if (!$a_obj_type) {
356 $a_obj_type = ilObject::_lookupType($a_obj_id);
357 }
358
359 if ($a_obj_type != "bdga") {
361 $a_obj_id,
363 false
364 )) {
365 return false;
366 }
367 }
368
369 return true;
370 }
371
372 public function triggerEvaluation($a_type_id, $a_user_id, array $a_params = null)
373 {
374 if (!$this->isActive() ||
375 in_array($a_type_id, $this->getInactiveTypes())) {
376 return;
377 }
378
379 $type = $this->getTypeInstanceByUniqueId($a_type_id);
380 if (!$type ||
381 !$type instanceof ilBadgeAuto) {
382 return;
383 }
384
385 $new_badges = array();
386 foreach (ilBadge::getInstancesByType($a_type_id) as $badge) {
387 if ($badge->isActive()) {
388 // already assigned?
389 if (!ilBadgeAssignment::exists($badge->getId(), $a_user_id)) {
390 if ((bool) $type->evaluate($a_user_id, (array) $a_params, (array) $badge->getConfiguration())) {
391 $ass = new ilBadgeAssignment($badge->getId(), $a_user_id);
392 $ass->store();
393
394 $new_badges[$a_user_id][] = $badge->getId();
395 }
396 }
397 }
398 }
399
400 $this->sendNotification($new_badges);
401 }
402
403 public function getUserIds($a_parent_ref_id, $a_parent_obj_id = null, $a_parent_type = null)
404 {
406
407 if (!$a_parent_obj_id) {
408 $a_parent_obj_id = ilObject::_lookupObjectId($a_parent_ref_id);
409 }
410 if (!$a_parent_type) {
411 $a_parent_type = ilObject::_lookupType($a_parent_obj_id);
412 }
413
414 // try to get participants from (parent) course/group
415 switch ($a_parent_type) {
416 case "crs":
417 $member_obj = ilCourseParticipants::_getInstanceByObjId($a_parent_obj_id);
418 return $member_obj->getMembers();
419
420 case "grp":
421 $member_obj = ilGroupParticipants::_getInstanceByObjId($a_parent_obj_id);
422 return $member_obj->getMembers();
423
424 default:
425 // walk path to find course or group object and use members of that object
426 $path = $tree->getPathId($a_parent_ref_id);
427 array_pop($path);
428 foreach (array_reverse($path) as $path_ref_id) {
429 $type = ilObject::_lookupType($path_ref_id, true);
430 if ($type == "crs" || $type == "grp") {
431 return $this->getParticipantsForObject($path_ref_id, null, $type);
432 }
433 }
434 break;
435 }
436 }
437
438
439 //
440 // PATH HANDLING (PUBLISHING)
441 //
442
443 protected function getBasePath()
444 {
445 return ilUtil::getWebspaceDir() . "/pub_badges/";
446 }
447
448 public function getInstancePath(ilBadgeAssignment $a_ass)
449 {
450 $hash = md5($a_ass->getBadgeId() . "_" . $a_ass->getUserId());
451
452 $path = $this->getBasePath() . "instances/" .
453 $a_ass->getBadgeId() . "/" .
454 floor($a_ass->getUserId() / 1000) . "/";
455
457
458 $path .= $hash . ".json";
459
460 return $path;
461 }
462
463 public function countStaticBadgeInstances(ilBadge $a_badge)
464 {
465 $path = $this->getBasePath() . "instances/" . $a_badge->getId();
466 $cnt = 0;
467 if (is_dir($path)) {
468 $this->countStaticBadgeInstancesHelper($cnt, $path);
469 }
470 return $cnt;
471 }
472
473 protected function countStaticBadgeInstancesHelper(&$a_cnt, $a_path)
474 {
475 foreach (glob($a_path . "/*") as $item) {
476 if (is_dir($item)) {
477 $this->countStaticBadgeInstancesHelper($a_cnt, $item);
478 } elseif (substr($item, -5) == ".json") {
479 $a_cnt++;
480 }
481 }
482 }
483
484 public function getBadgePath(ilBadge $a_badge)
485 {
486 $hash = md5($a_badge->getId());
487
488 $path = $this->getBasePath() . "badges/" .
489 floor($a_badge->getId() / 100) . "/" .
490 $hash . "/";
491
493
494 return $path;
495 }
496
497 protected function prepareIssuerJson($a_url)
498 {
499 $json = new stdClass();
500 $json->{"@context"} = "https://w3id.org/openbadges/v1";
501 $json->type = "Issuer";
502 $json->id = $a_url;
503 $json->name = $this->getObiOrganistation();
504 $json->url = ILIAS_HTTP_PATH . "/";
505 $json->email = $this->getObiContact();
506
507 return $json;
508 }
509
510 public function getIssuerStaticUrl()
511 {
512 $path = $this->getBasePath() . "issuer/";
514 $path .= "issuer.json";
515
516 $url = ILIAS_HTTP_PATH . substr($path, 1);
517
518 if (!file_exists($path)) {
519 $json = json_encode($this->prepareIssuerJson($url));
520 file_put_contents($path, $json);
521 }
522
523 return $url;
524 }
525
526 public function rebuildIssuerStaticUrl()
527 {
528 $path = $this->getBasePath() . "issuer/issuer.json";
529 if (file_exists($path)) {
530 unlink($path);
531 }
532 $this->getIssuerStaticUrl();
533 }
534
535
536 //
537 // notification
538 //
539
540 public function sendNotification(array $a_user_map, $a_parent_ref_id = null)
541 {
542 $badges = array();
543
544 foreach ($a_user_map as $user_id => $badge_ids) {
545 $user_badges = array();
546
547 foreach ($badge_ids as $badge_id) {
548 // making extra sure
549 if (!ilBadgeAssignment::exists($badge_id, $user_id)) {
550 continue;
551 }
552
553 if (!array_key_exists($badge_id, $badges)) {
554 $badges[$badge_id] = new ilBadge($badge_id);
555 }
556
557 $badge = $badges[$badge_id];
558
559 $user_badges[] = $badge->getTitle();
560 }
561
562 if (sizeof($user_badges)) {
563 // compose and send mail
564
565 $ntf = new ilSystemNotification(false);
566 $ntf->setLangModules(array("badge"));
567
568 $ntf->setRefId($a_parent_ref_id);
569 $ntf->setGotoLangId("badge_notification_parent_goto");
570
571 // user specific language
572 $lng = $ntf->getUserLanguage($user_id);
573
574 $ntf->setIntroductionLangId("badge_notification_body");
575
576 $ntf->addAdditionalInfo("badge_notification_badges", implode("\n", $user_badges), true);
577
578 $url = ilLink::_getLink($user_id, "usr", array(), "_bdg");
579 $ntf->addAdditionalInfo("badge_notification_badges_goto", $url);
580
581 $ntf->setReasonLangId("badge_notification_reason");
582
583 // force email
584 $mail = new ilMail(ANONYMOUS_USER_ID);
585 $mail->enqueue(
586 ilObjUser::_lookupEmail($user_id),
587 null,
588 null,
589 $lng->txt("badge_notification_subject"),
590 $ntf->composeAndGetMessage($user_id, null, "read", true),
591 []
592 );
593
594
595 // osd
596 // bug #24562
597 if (ilContext::hasHTML()) {
598 $osd_params = array("badge_list" => "<br />" . implode("<br />", $user_badges));
599
600 require_once "Services/Notifications/classes/class.ilNotificationConfig.php";
601 $notification = new ilNotificationConfig("osd_main");
602 $notification->setTitleVar("badge_notification_subject", array(), "badge");
603 $notification->setShortDescriptionVar("badge_notification_osd", $osd_params, "badge");
604 $notification->setLongDescriptionVar("", $osd_params, "");
605 $notification->setAutoDisable(false);
606 $notification->setLink($url);
607 $notification->setIconPath(ilUtil::getImagePath('icon_bdga.svg'));
608 $notification->setValidForSeconds(ilNotificationConfig::TTL_SHORT);
609 $notification->setVisibleForSeconds(ilNotificationConfig::DEFAULT_TTS);
610 $notification->notifyByUsers(array($user_id));
611 }
612 }
613 }
614 }
615}
An exception for terminatinating execution or to throw for unit testing.
Class ilBadgeAssignment.
static exists($a_badge_id, $a_user_id)
Class ilBadgeHandler.
setInactiveTypes(array $a_types=null)
getUniqueTypeId($a_component_id, ilBadgeType $a_badge)
getAvailableTypesForObjType($a_object_type)
Get valid badges types for object type.
__construct()
Constructor.
setComponents(array $a_components=null)
isObjectActive($a_obj_id, $a_obj_type=null)
static updateFromXML($a_component_id)
Import component definition.
triggerEvaluation($a_type_id, $a_user_id, array $a_params=null)
getAvailableTypes()
Get badges types.
setObiOrganisation($a_value)
countStaticBadgeInstancesHelper(&$a_cnt, $a_path)
getProviderInstance($a_component_id)
Get provider instance.
static getInstance()
Constructor.
getComponentCaption($a_component_id)
getInstancePath(ilBadgeAssignment $a_ass)
getBadgePath(ilBadge $a_badge)
getUserIds($a_parent_ref_id, $a_parent_obj_id=null, $a_parent_type=null)
countStaticBadgeInstances(ilBadge $a_badge)
getTypeInstanceByUniqueId($a_id)
Get type instance by unique id (component, type)
sendNotification(array $a_user_map, $a_parent_ref_id=null)
getAvailableManualBadges($a_parent_obj_id, $a_parent_obj_type=null)
Get available manual badges for object id.
static clearFromXML($a_component_id)
Remove component definition.
Class ilBadge.
static getInstancesByParentId($a_parent_id, array $a_filter=null)
static getInstancesByType($a_type_id)
static _lookupContainerSetting($a_id, $a_keyword, $a_default_value=null)
Lookup a container setting.
static hasHTML()
Has HTML output.
static _getInstanceByObjId($a_obj_id)
Get singleton instance.
static _getInstanceByObjId($a_obj_id)
Get singleton instance.
Describes a notification and provides methods for publishing this notification.
static _lookupEmail($a_user_id)
Lookup email.
static _lookupObjectId($a_ref_id)
lookup object id
static _lookupType($a_id, $a_reference=false)
lookup object type
ILIAS Setting Class.
Wrapper classes for system notifications.
static getWebspaceDir($mode="filesystem")
get webspace directory
static makeDirParents($a_dir)
Create a new directory and all parent directories.
static getImagePath($img, $module_path="", $mode="output", $offline=false)
get image path (for images located in a template directory)
const ANONYMOUS_USER_ID
Definition: constants.php:25
global $DIC
Definition: goto.php:24
Manual Badge Auto.
Badge Provider interface.
Badge type interface.
getId()
Get typ id (unique for component)
$type
$url
$lng
foreach($_POST as $key=> $value) $res
settings()
Definition: settings.php:2
global $ilDB