ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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
296
297 //
298 // PUBLISHING
299 //
300
301 protected function prepareJson($a_url)
302 {
303 $verify = new stdClass();
304 $verify->type = "hosted";
305 $verify->url = $a_url;
306
307 $recipient = new stdClass();
308 $recipient->type = "email";
309 $recipient->hashed = true;
310 $recipient->salt = ilBadgeHandler::getInstance()->getObiSalt();
311
312 // https://github.com/mozilla/openbadges-backpack/wiki/How-to-hash-&-salt-in-various-languages.
313 include_once "Services/Badge/classes/class.ilBadgeProfileGUI.php";
314 $user = new ilObjUser($this->getUserId());
315 $mail = $user->getPref(ilBadgeProfileGUI::BACKPACK_EMAIL);
316 if (!$mail) {
317 $mail = $user->getEmail();
318 }
319 $recipient->identity = 'sha256$' . hash('sha256', $mail . $recipient->salt);
320
321 // spec: should be locally unique
322 $unique_id = md5($this->getBadgeId() . "-" . $this->getUserId());
323
324 $json = new stdClass();
325 $json->{"@context"} = "https://w3id.org/openbadges/v1";
326 $json->type = "Assertion";
327 $json->id = $a_url;
328 $json->uid = $unique_id;
329 $json->recipient = $recipient;
330
331 include_once "Services/Badge/classes/class.ilBadge.php";
332 $badge = new ilBadge($this->getBadgeId());
333 $badge_url = $badge->getStaticUrl();
334
335 // created baked image
336 $baked_image = $this->getImagePath($badge);
337 if ($this->bakeImage($baked_image, $badge->getImagePath(), $a_url)) {
338 // path to url
339 $parts = explode("/", $a_url);
340 array_pop($parts);
341 $parts[] = basename($baked_image);
342 $json->image = implode("/", $parts);
343 }
344
345 $json->issuedOn = $this->getTimestamp();
346 $json->badge = $badge_url;
347 $json->verify = $verify;
348
349 return $json;
350 }
351
352 public function getImagePath(ilBadge $a_badge)
353 {
354 $json_path = ilBadgeHandler::getInstance()->getInstancePath($this);
355 $baked_path = dirname($json_path);
356 $baked_file = array_shift(explode(".", basename($json_path)));
357
358 // get correct suffix from badge image
359 $suffix = strtolower(array_pop(explode(".", basename($a_badge->getImagePath()))));
360 return $baked_path . "/" . $baked_file . "." . $suffix;
361 }
362
363 protected function bakeImage($a_baked_image_path, $a_badge_image_path, $a_assertion_url)
364 {
365 $suffix = strtolower(array_pop(explode(".", basename($a_badge_image_path))));
366 if ($suffix == "png") {
367 // using chamilo baker lib
368 include_once "Services/Badge/lib/baker.lib.php";
369 $png = new PNGImageBaker(file_get_contents($a_badge_image_path));
370
371 // add payload
372 if ($png->checkChunks("tEXt", "openbadges")) {
373 $baked = $png->addChunk("tEXt", "openbadges", $a_assertion_url);
374 }
375
376 // create baked file
377 if (!file_exists($a_baked_image_path)) {
378 file_put_contents($a_baked_image_path, $baked);
379 }
380
381 // verify file
382 $verify = $png->extractBadgeInfo(file_get_contents($a_baked_image_path));
383 if (is_array($verify)) {
384 return true;
385 }
386 } elseif ($suffix == "svg") {
387 // :TODO: not really sure if this is correct
388 $svg = simplexml_load_file($a_badge_image_path);
389 $ass = $svg->addChild("openbadges:assertion", "", "http://openbadges.org");
390 $ass->addAttribute("verify", $a_assertion_url);
391 $baked = $svg->asXML();
392
393 // create baked file
394 if (!file_exists($a_baked_image_path)) {
395 file_put_contents($a_baked_image_path, $baked);
396 }
397
398 return true;
399 }
400
401 return false;
402 }
403
404 public function getStaticUrl()
405 {
406 include_once("./Services/Badge/classes/class.ilBadgeHandler.php");
407 $path = ilBadgeHandler::getInstance()->getInstancePath($this);
408
409 $url = ILIAS_HTTP_PATH . substr($path, 1);
410
411 if (!file_exists($path)) {
412 $json = json_encode($this->prepareJson($url));
413 file_put_contents($path, $json);
414 }
415
416 return $url;
417 }
418
419 public function deleteStaticFiles()
420 {
421 // remove instance files
422 include_once("./Services/Badge/classes/class.ilBadgeHandler.php");
423 $path = ilBadgeHandler::getInstance()->getInstancePath($this);
424 $path = str_replace(".json", ".*", $path);
425 array_map("unlink", glob($path));
426 }
427
428 public static function clearBadgeCache($a_user_id)
429 {
430 foreach (self::getInstancesByUserId($a_user_id) as $ass) {
431 $ass->deleteStaticFiles();
432 }
433 }
434}
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 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
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