ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.ilBadgeAssignment.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
3
13{
17 protected $db;
18
19 protected $badge_id; // [int]
20 protected $user_id; // [int]
21 protected $tstamp; // [timestamp]
22 protected $awarded_by; // [int]
23 protected $pos; // [int]
24 protected $stored; // [bool]
25
26 public function __construct($a_badge_id = null, $a_user_id = null)
27 {
28 global $DIC;
29
30 $this->db = $DIC->database();
31 if ($a_badge_id &&
32 $a_user_id) {
33 $this->setBadgeId($a_badge_id);
34 $this->setUserId($a_user_id);
35
36 $this->read($a_badge_id, $a_user_id);
37 }
38 }
39
40 public static function getInstancesByUserId($a_user_id)
41 {
42 global $DIC;
43
44 $ilDB = $DIC->database();
45
46 $res = array();
47
48 $set = $ilDB->query("SELECT * FROM badge_user_badge" .
49 " WHERE user_id = " . $ilDB->quote($a_user_id, "integer") .
50 " ORDER BY pos");
51 while ($row = $ilDB->fetchAssoc($set)) {
52 $obj = new self();
53 $obj->importDBRow($row);
54 $res[] = $obj;
55 }
56
57 return $res;
58 }
59
60 public static function getInstancesByBadgeId($a_badge_id)
61 {
62 global $DIC;
63
64 $ilDB = $DIC->database();
65
66 $res = array();
67
68 $set = $ilDB->query("SELECT * FROM badge_user_badge" .
69 " WHERE badge_id = " . $ilDB->quote($a_badge_id, "integer"));
70 while ($row = $ilDB->fetchAssoc($set)) {
71 $obj = new self();
72 $obj->importDBRow($row);
73 $res[] = $obj;
74 }
75
76 return $res;
77 }
78
79 public static function getInstancesByParentId($a_parent_obj_id)
80 {
81 global $DIC;
82
83 $ilDB = $DIC->database();
84
85 $res = array();
86
87 $badge_ids = array();
88 foreach (ilBadge::getInstancesByParentId($a_parent_obj_id) as $badge) {
89 $badge_ids[] = $badge->getId();
90 }
91 if (sizeof($badge_ids)) {
92 $set = $ilDB->query("SELECT * FROM badge_user_badge" .
93 " WHERE " . $ilDB->in("badge_id", $badge_ids, "", "integer"));
94 while ($row = $ilDB->fetchAssoc($set)) {
95 $obj = new self();
96 $obj->importDBRow($row);
97 $res[] = $obj;
98 }
99 }
100
101 return $res;
102 }
103
104 public static function getAssignedUsers($a_badge_id)
105 {
106 $res = array();
107
108 foreach (self::getInstancesByBadgeId($a_badge_id) as $ass) {
109 $res[] = $ass->getUserId();
110 }
111
112 return $res;
113 }
114
115 public static function exists($a_badge_id, $a_user_id)
116 {
117 $obj = new self($a_badge_id, $a_user_id);
118 return $obj->stored;
119 }
120
121
122 //
123 // setter/getter
124 //
125
126 protected function setBadgeId($a_value)
127 {
128 $this->badge_id = (int) $a_value;
129 }
130
131 public function getBadgeId()
132 {
133 return $this->badge_id;
134 }
135
136 protected function setUserId($a_value)
137 {
138 $this->user_id = (int) $a_value;
139 }
140
141 public function getUserId()
142 {
143 return $this->user_id;
144 }
145
146 protected function setTimestamp($a_value)
147 {
148 $this->tstamp = (int) $a_value;
149 }
150
151 public function getTimestamp()
152 {
153 return $this->tstamp;
154 }
155
156 public function setAwardedBy($a_id)
157 {
158 $this->awarded_by = (int) $a_id;
159 }
160
161 public function getAwardedBy()
162 {
163 return $this->awarded_by;
164 }
165
166 public function setPosition($a_value)
167 {
168 if ($a_value !== null) {
169 $a_value = (int) $a_value;
170 }
171 $this->pos = $a_value;
172 }
173
174 public function getPosition()
175 {
176 return $this->pos;
177 }
178
179
180 //
181 // crud
182 //
183
184 protected function importDBRow(array $a_row)
185 {
186 $this->stored = true;
187 $this->setBadgeId($a_row["badge_id"]);
188 $this->setUserId($a_row["user_id"]);
189 $this->setTimestamp($a_row["tstamp"]);
190 $this->setAwardedBy($a_row["awarded_by"]);
191 $this->setPosition($a_row["pos"]);
192 }
193
194 protected function read($a_badge_id, $a_user_id)
195 {
197
198 $set = $ilDB->query("SELECT * FROM badge_user_badge" .
199 " WHERE badge_id = " . $ilDB->quote($a_badge_id, "integer") .
200 " AND user_id = " . $ilDB->quote($a_user_id, "integer"));
201 $row = $ilDB->fetchAssoc($set);
202 if ($row["user_id"]) {
203 $this->importDBRow($row);
204 }
205 }
206
207 protected function getPropertiesForStorage()
208 {
209 return array(
210 "tstamp" => array("integer", (bool) $this->stored ? $this->getTimestamp() : time()),
211 "awarded_by" => array("integer", $this->getAwardedBy()),
212 "pos" => array("integer", $this->getPosition())
213 );
214 }
215
216 public function store()
217 {
219
220 if (!$this->getBadgeId() ||
221 !$this->getUserId()) {
222 return;
223 }
224
225 $keys = array(
226 "badge_id" => array("integer", $this->getBadgeId()),
227 "user_id" => array("integer", $this->getUserId())
228 );
229 $fields = $this->getPropertiesForStorage();
230
231 if (!(bool) $this->stored) {
232 $ilDB->insert("badge_user_badge", $fields + $keys);
233 } else {
234 $ilDB->update("badge_user_badge", $fields, $keys);
235 }
236 }
237
238 public function delete()
239 {
241
242 if (!$this->getBadgeId() ||
243 !$this->getUserId()) {
244 return;
245 }
246
247 $this->deleteStaticFiles();
248
249 $ilDB->manipulate("DELETE FROM badge_user_badge" .
250 " WHERE badge_id = " . $ilDB->quote($this->getBadgeId(), "integer") .
251 " AND user_id = " . $ilDB->quote($this->getUserId(), "integer"));
252 }
253
254 public static function deleteByUserId($a_user_id)
255 {
256 foreach (self::getInstancesByUserId($a_user_id) as $ass) {
257 $ass->delete();
258 }
259 }
260
261 public static function deleteByBadgeId($a_badge_id)
262 {
263 foreach (self::getInstancesByBadgeId($a_badge_id) as $ass) {
264 $ass->delete();
265 }
266 }
267
268 public static function deleteByParentId($a_parent_obj_id)
269 {
270 foreach (self::getInstancesByParentId($a_parent_obj_id) as $ass) {
271 $ass->delete();
272 }
273 }
274
275 public static function updatePositions($a_user_id, array $a_positions)
276 {
277 $existing = array();
278 include_once "Services/Badge/classes/class.ilBadge.php";
279 foreach (self::getInstancesByUserId($a_user_id) as $ass) {
280 $badge = new ilBadge($ass->getBadgeId());
281 $existing[$badge->getId()] = array($badge->getTitle(), $ass);
282 }
283
284 $new_pos = 0;
285 foreach ($a_positions as $title) {
286 foreach ($existing as $id => $item) {
287 if ($title == $item[0]) {
288 $item[1]->setPosition(++$new_pos);
289 $item[1]->store();
290 unset($existing[$id]);
291 }
292 }
293 }
294 }
295
303 public static function getBadgesForUser($a_user_id, $a_ts_from, $a_ts_to)
304 {
305 global $DIC;
306
307 $db = $DIC->database();
308
309 $set = $db->queryF(
310 "SELECT bdg.parent_id, ub.tstamp, bdg.title FROM badge_user_badge ub JOIN badge_badge bdg" .
311 " ON (ub.badge_id = bdg.id) " .
312 " WHERE ub.user_id = %s AND ub.tstamp >= %s AND ub.tstamp <= %s",
313 array("integer","integer","integer"),
314 array($a_user_id, $a_ts_from, $a_ts_to)
315 );
316 $res = [];
317 while ($rec = $db->fetchAssoc($set)) {
318 $res[] = $rec;
319 }
320 return $res;
321 }
322
323
324 //
325 // PUBLISHING
326 //
327
328 protected function prepareJson($a_url)
329 {
330 $verify = new stdClass();
331 $verify->type = "hosted";
332 $verify->url = $a_url;
333
334 $recipient = new stdClass();
335 $recipient->type = "email";
336 $recipient->hashed = true;
337 $recipient->salt = ilBadgeHandler::getInstance()->getObiSalt();
338
339 // https://github.com/mozilla/openbadges-backpack/wiki/How-to-hash-&-salt-in-various-languages.
340 include_once "Services/Badge/classes/class.ilBadgeProfileGUI.php";
341 $user = new ilObjUser($this->getUserId());
343 if (!$mail) {
344 $mail = $user->getEmail();
345 }
346 $recipient->identity = 'sha256$' . hash('sha256', $mail . $recipient->salt);
347
348 // spec: should be locally unique
349 $unique_id = md5($this->getBadgeId() . "-" . $this->getUserId());
350
351 $json = new stdClass();
352 $json->{"@context"} = "https://w3id.org/openbadges/v1";
353 $json->type = "Assertion";
354 $json->id = $a_url;
355 $json->uid = $unique_id;
356 $json->recipient = $recipient;
357
358 include_once "Services/Badge/classes/class.ilBadge.php";
359 $badge = new ilBadge($this->getBadgeId());
360 $badge_url = $badge->getStaticUrl();
361
362 // created baked image
363 $baked_image = $this->getImagePath($badge);
364 if ($this->bakeImage($baked_image, $badge->getImagePath(), $a_url)) {
365 // path to url
366 $parts = explode("/", $a_url);
367 array_pop($parts);
368 $parts[] = basename($baked_image);
369 $json->image = implode("/", $parts);
370 }
371
372 $json->issuedOn = $this->getTimestamp();
373 $json->badge = $badge_url;
374 $json->verify = $verify;
375
376 return $json;
377 }
378
379 public function getImagePath(ilBadge $a_badge)
380 {
381 $json_path = ilBadgeHandler::getInstance()->getInstancePath($this);
382 $baked_path = dirname($json_path);
383 $baked_file = array_shift(explode(".", basename($json_path)));
384
385 // get correct suffix from badge image
386 $suffix = strtolower(array_pop(explode(".", basename($a_badge->getImagePath()))));
387 return $baked_path . "/" . $baked_file . "." . $suffix;
388 }
389
390 protected function bakeImage($a_baked_image_path, $a_badge_image_path, $a_assertion_url)
391 {
392 $suffix = strtolower(array_pop(explode(".", basename($a_badge_image_path))));
393 if ($suffix == "png") {
394 // using chamilo baker lib
395 include_once "Services/Badge/lib/baker.lib.php";
396 $png = new PNGImageBaker(file_get_contents($a_badge_image_path));
397
398 // add payload
399 if ($png->checkChunks("tEXt", "openbadges")) {
400 $baked = $png->addChunk("tEXt", "openbadges", $a_assertion_url);
401 }
402
403 // create baked file
404 if (!file_exists($a_baked_image_path)) {
405 file_put_contents($a_baked_image_path, $baked);
406 }
407
408 // verify file
409 $verify = $png->extractBadgeInfo(file_get_contents($a_baked_image_path));
410 if (is_array($verify)) {
411 return true;
412 }
413 } elseif ($suffix == "svg") {
414 // :TODO: not really sure if this is correct
415 $svg = simplexml_load_file($a_badge_image_path);
416 $ass = $svg->addChild("openbadges:assertion", "", "http://openbadges.org");
417 $ass->addAttribute("verify", $a_assertion_url);
418 $baked = $svg->asXML();
419
420 // create baked file
421 if (!file_exists($a_baked_image_path)) {
422 file_put_contents($a_baked_image_path, $baked);
423 }
424
425 return true;
426 }
427
428 return false;
429 }
430
431 public function getStaticUrl()
432 {
433 include_once("./Services/Badge/classes/class.ilBadgeHandler.php");
434 $path = ilBadgeHandler::getInstance()->getInstancePath($this);
435
436 $url = ILIAS_HTTP_PATH . substr($path, 1);
437
438 if (!file_exists($path)) {
439 $json = json_encode($this->prepareJson($url));
440 file_put_contents($path, $json);
441 }
442
443 return $url;
444 }
445
446 public function deleteStaticFiles()
447 {
448 // remove instance files
449 include_once("./Services/Badge/classes/class.ilBadgeHandler.php");
450 $path = ilBadgeHandler::getInstance()->getInstancePath($this);
451 $path = str_replace(".json", ".*", $path);
452 array_map("unlink", glob($path));
453 }
454
455 public static function clearBadgeCache($a_user_id)
456 {
457 foreach (self::getInstancesByUserId($a_user_id) as $ass) {
458 $ass->deleteStaticFiles();
459 }
460 }
461}
$path
Definition: aliased.php:25
An exception for terminatinating execution or to throw for unit testing.
Php library to Bake the PNG Images.
Definition: baker.lib.php:8
static getInstancesByUserId($a_user_id)
bakeImage($a_baked_image_path, $a_badge_image_path, $a_assertion_url)
static getAssignedUsers($a_badge_id)
static clearBadgeCache($a_user_id)
static deleteByBadgeId($a_badge_id)
static getInstancesByBadgeId($a_badge_id)
read($a_badge_id, $a_user_id)
static getBadgesForUser($a_user_id, $a_ts_from, $a_ts_to)
Get badges for user.
static deleteByUserId($a_user_id)
__construct($a_badge_id=null, $a_user_id=null)
getImagePath(ilBadge $a_badge)
static updatePositions($a_user_id, array $a_positions)
static exists($a_badge_id, $a_user_id)
static getInstancesByParentId($a_parent_obj_id)
static deleteByParentId($a_parent_obj_id)
static getInstance()
Constructor.
static getInstancesByParentId($a_parent_id, array $a_filter=null)
getImagePath($a_full_path=true)
if(!array_key_exists('StateId', $_REQUEST)) $id
$keys
$user
Definition: migrateto20.php:57
$row
hash(StreamInterface $stream, $algo, $rawOutput=false)
Calculate a hash of a Stream.
Definition: functions.php:406
$url
global $DIC
Definition: saml.php:7
foreach($_POST as $key=> $value) $res
global $ilDB