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  {
196  $ilDB = $this->db;
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  {
218  $ilDB = $this->db;
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  {
240  $ilDB = $this->db;
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());
342  $mail = $user->getPref(ilBadgeProfileGUI::BACKPACK_EMAIL);
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
getImagePath($a_full_path=true)
static exists($a_badge_id, $a_user_id)
static getAssignedUsers($a_badge_id)
global $DIC
Definition: saml.php:7
__construct($a_badge_id=null, $a_user_id=null)
if(!array_key_exists('StateId', $_REQUEST)) $id
static deleteByParentId($a_parent_obj_id)
Php library to Bake the PNG Images.
Definition: baker.lib.php:7
$keys
getImagePath(ilBadge $a_badge)
static getInstancesByParentId($a_parent_id, array $a_filter=null)
foreach($_POST as $key=> $value) $res
static deleteByBadgeId($a_badge_id)
$user
Definition: migrateto20.php:57
$row
global $ilDB
static updatePositions($a_user_id, array $a_positions)
$url
bakeImage($a_baked_image_path, $a_badge_image_path, $a_assertion_url)
read($a_badge_id, $a_user_id)
static deleteByUserId($a_user_id)
hash(StreamInterface $stream, $algo, $rawOutput=false)
Calculate a hash of a Stream.
Definition: functions.php:406
static getInstancesByBadgeId($a_badge_id)
static clearBadgeCache($a_user_id)
static getInstancesByUserId($a_user_id)
static getBadgesForUser($a_user_id, $a_ts_from, $a_ts_to)
Get badges for user.
static getInstance()
Constructor.
static getInstancesByParentId($a_parent_obj_id)