Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
/**
18
 * Communicate with backpacks.
19
 *
20
 * @copyright  2012 onwards Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
21
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22
 * @author     Yuliya Bozhko <yuliya.bozhko@totaralms.com>
23
 */
24
 
25
namespace core_badges;
26
 
27
defined('MOODLE_INTERNAL') || die();
28
 
29
require_once($CFG->libdir . '/filelib.php');
30
 
31
use cache;
32
use coding_exception;
33
use core_badges\external\assertion_exporter;
34
use core_badges\external\collection_exporter;
35
use core_badges\external\issuer_exporter;
36
use core_badges\external\badgeclass_exporter;
37
use curl;
38
use stdClass;
39
use context_system;
40
 
41
define('BADGE_ACCESS_TOKEN', 'access');
42
define('BADGE_USER_ID_TOKEN', 'user_id');
43
define('BADGE_BACKPACK_ID_TOKEN', 'backpack_id');
44
define('BADGE_REFRESH_TOKEN', 'refresh');
45
define('BADGE_EXPIRES_TOKEN', 'expires');
46
 
47
/**
48
 * Class for communicating with backpacks.
49
 *
50
 * @package   core_badges
51
 * @copyright  2012 onwards Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
52
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
53
 */
54
class backpack_api {
55
 
56
    /** @var string The email address of the issuer or the backpack owner. */
57
    private $email;
58
 
59
    /** @var string The base url used for api requests to this backpack. */
60
    private $backpackapiurl;
61
 
62
    /** @var integer The backpack api version to use. */
63
    private $backpackapiversion;
64
 
65
    /** @var string The password to authenticate requests. */
66
    private $password;
67
 
68
    /** @var boolean User or site api requests. */
69
    private $isuserbackpack;
70
 
71
    /** @var integer The id of the backpack we are talking to. */
72
    private $backpackid;
73
 
74
    /** @var \backpack_api_mapping[] List of apis for the user or site using api version 1 or 2. */
75
    private $mappings = [];
76
 
77
    /**
78
     * Create a wrapper to communicate with the backpack.
79
     *
80
     * The resulting class can only do either site backpack communication or
81
     * user backpack communication.
82
     *
83
     * @param stdClass $sitebackpack The site backpack record
84
     * @param mixed $userbackpack Optional - if passed it represents the users backpack.
85
     */
86
    public function __construct($sitebackpack, $userbackpack = false) {
87
        global $CFG;
88
        $admin = get_admin();
89
 
90
        $this->backpackapiurl = $sitebackpack->backpackapiurl;
91
        $this->backpackapiversion = $sitebackpack->apiversion;
92
        $this->password = $sitebackpack->password;
93
        $this->email = $sitebackpack->backpackemail;
94
        $this->isuserbackpack = false;
95
        $this->backpackid = $sitebackpack->id;
96
        if (!empty($userbackpack)) {
97
            $this->isuserbackpack = true;
98
            $this->password = $userbackpack->password;
99
            $this->email = $userbackpack->email;
100
        }
101
 
102
        $this->define_mappings();
103
        // Clear the last authentication error.
104
        backpack_api_mapping::set_authentication_error('');
105
    }
106
 
107
    /**
108
     * Define the mappings supported by this usage and api version.
109
     */
110
    private function define_mappings() {
111
        if ($this->backpackapiversion == OPEN_BADGES_V2) {
112
            if ($this->isuserbackpack) {
113
                $mapping = [];
114
                $mapping[] = [
115
                    'collections',                              // Action.
116
                    '[URL]/backpack/collections',               // URL
117
                    [],                                         // Post params.
118
                    '',                                         // Request exporter.
119
                    'core_badges\external\collection_exporter', // Response exporter.
120
                    true,                                       // Multiple.
121
                    'get',                                      // Method.
122
                    true,                                       // JSON Encoded.
123
                    true                                        // Auth required.
124
                ];
125
                $mapping[] = [
126
                    'user',                                     // Action.
127
                    '[SCHEME]://[HOST]/o/token',                // URL
128
                    ['username' => '[EMAIL]', 'password' => '[PASSWORD]'], // Post params.
129
                    '',                                         // Request exporter.
130
                    'oauth_token_response',                     // Response exporter.
131
                    false,                                      // Multiple.
132
                    'post',                                     // Method.
133
                    false,                                      // JSON Encoded.
134
                    false,                                      // Auth required.
135
                ];
136
                $mapping[] = [
137
                    'assertion',                                // Action.
138
                    // Badgr.io does not return the public information about a badge
139
                    // if the issuer is associated with another user. We need to pass
140
                    // the expand parameters which are not in any specification to get
141
                    // additional information about the assertion in a single request.
142
                    '[URL]/backpack/assertions/[PARAM2]?expand=badgeclass&expand=issuer',
143
                    [],                                         // Post params.
144
                    '',                                         // Request exporter.
145
                    'core_badges\external\assertion_exporter',  // Response exporter.
146
                    false,                                      // Multiple.
147
                    'get',                                      // Method.
148
                    true,                                       // JSON Encoded.
149
                    true                                        // Auth required.
150
                ];
151
                $mapping[] = [
152
                    'importbadge',                                // Action.
153
                    // Badgr.io does not return the public information about a badge
154
                    // if the issuer is associated with another user. We need to pass
155
                    // the expand parameters which are not in any specification to get
156
                    // additional information about the assertion in a single request.
157
                    '[URL]/backpack/import',
158
                    ['url' => '[PARAM]'],  // Post params.
159
                    '',                                             // Request exporter.
160
                    'core_badges\external\assertion_exporter',      // Response exporter.
161
                    false,                                          // Multiple.
162
                    'post',                                         // Method.
163
                    true,                                           // JSON Encoded.
164
                    true                                            // Auth required.
165
                ];
166
                $mapping[] = [
167
                    'badges',                                   // Action.
168
                    '[URL]/backpack/collections/[PARAM1]',      // URL
169
                    [],                                         // Post params.
170
                    '',                                         // Request exporter.
171
                    'core_badges\external\collection_exporter', // Response exporter.
172
                    true,                                       // Multiple.
173
                    'get',                                      // Method.
174
                    true,                                       // JSON Encoded.
175
                    true                                        // Auth required.
176
                ];
177
                foreach ($mapping as $map) {
178
                    $map[] = true; // User api function.
179
                    $map[] = OPEN_BADGES_V2; // V2 function.
180
                    $this->mappings[] = new backpack_api_mapping(...$map);
181
                }
182
            } else {
183
                $mapping = [];
184
                $mapping[] = [
185
                    'user',                                     // Action.
186
                    '[SCHEME]://[HOST]/o/token',                // URL
187
                    ['username' => '[EMAIL]', 'password' => '[PASSWORD]'], // Post params.
188
                    '',                                         // Request exporter.
189
                    'oauth_token_response',                     // Response exporter.
190
                    false,                                      // Multiple.
191
                    'post',                                     // Method.
192
                    false,                                      // JSON Encoded.
193
                    false                                       // Auth required.
194
                ];
195
                $mapping[] = [
196
                    'issuers',                                  // Action.
197
                    '[URL]/issuers',                            // URL
198
                    '[PARAM]',                                  // Post params.
199
                    'core_badges\external\issuer_exporter',     // Request exporter.
200
                    'core_badges\external\issuer_exporter',     // Response exporter.
201
                    false,                                      // Multiple.
202
                    'post',                                     // Method.
203
                    true,                                       // JSON Encoded.
204
                    true                                        // Auth required.
205
                ];
206
                $mapping[] = [
207
                    'badgeclasses',                             // Action.
208
                    '[URL]/issuers/[PARAM2]/badgeclasses',      // URL
209
                    '[PARAM]',                                  // Post params.
210
                    'core_badges\external\badgeclass_exporter', // Request exporter.
211
                    'core_badges\external\badgeclass_exporter', // Response exporter.
212
                    false,                                      // Multiple.
213
                    'post',                                     // Method.
214
                    true,                                       // JSON Encoded.
215
                    true                                        // Auth required.
216
                ];
217
                $mapping[] = [
218
                    'assertions',                               // Action.
219
                    '[URL]/badgeclasses/[PARAM2]/assertions',   // URL
220
                    '[PARAM]',                                  // Post params.
221
                    'core_badges\external\assertion_exporter', // Request exporter.
222
                    'core_badges\external\assertion_exporter', // Response exporter.
223
                    false,                                      // Multiple.
224
                    'post',                                     // Method.
225
                    true,                                       // JSON Encoded.
226
                    true                                        // Auth required.
227
                ];
228
                $mapping[] = [
229
                    'updateassertion',                                // Action.
230
                    '[URL]/assertions/[PARAM2]?expand=badgeclass&expand=issuer',
231
                    '[PARAM]',                                  // Post params.
232
                    'core_badges\external\assertion_exporter', // Request exporter.
233
                    'core_badges\external\assertion_exporter', // Response exporter.
234
                    false,                                      // Multiple.
235
                    'put',                                     // Method.
236
                    true,                                       // JSON Encoded.
237
                    true                                        // Auth required.
238
                ];
239
                foreach ($mapping as $map) {
240
                    $map[] = false; // Site api function.
241
                    $map[] = OPEN_BADGES_V2; // V2 function.
242
                    $this->mappings[] = new backpack_api_mapping(...$map);
243
                }
244
            }
245
        } else {
246
            if ($this->isuserbackpack) {
247
                $mapping = [];
248
                $mapping[] = [
249
                    'user',                                     // Action.
250
                    '[URL]/displayer/convert/email',            // URL
251
                    ['email' => '[EMAIL]'],                     // Post params.
252
                    '',                                         // Request exporter.
253
                    'convert_email_response',                   // Response exporter.
254
                    false,                                      // Multiple.
255
                    'post',                                     // Method.
256
                    false,                                      // JSON Encoded.
257
                    false                                       // Auth required.
258
                ];
259
                $mapping[] = [
260
                    'groups',                                   // Action.
261
                    '[URL]/displayer/[PARAM1]/groups.json',     // URL
262
                    [],                                         // Post params.
263
                    '',                                         // Request exporter.
264
                    '',                                         // Response exporter.
265
                    false,                                      // Multiple.
266
                    'get',                                      // Method.
267
                    true,                                       // JSON Encoded.
268
                    true                                        // Auth required.
269
                ];
270
                $mapping[] = [
271
                    'badges',                                   // Action.
272
                    '[URL]/displayer/[PARAM2]/group/[PARAM1].json',     // URL
273
                    [],                                         // Post params.
274
                    '',                                         // Request exporter.
275
                    '',                                         // Response exporter.
276
                    false,                                      // Multiple.
277
                    'get',                                      // Method.
278
                    true,                                       // JSON Encoded.
279
                    true                                        // Auth required.
280
                ];
281
                foreach ($mapping as $map) {
282
                    $map[] = true; // User api function.
283
                    $map[] = OPEN_BADGES_V1; // V1 function.
284
                    $this->mappings[] = new backpack_api_mapping(...$map);
285
                }
286
            } else {
287
                $mapping = [];
288
                $mapping[] = [
289
                    'user',                                     // Action.
290
                    '[URL]/displayer/convert/email',            // URL
291
                    ['email' => '[EMAIL]'],                     // Post params.
292
                    '',                                         // Request exporter.
293
                    'convert_email_response',                   // Response exporter.
294
                    false,                                      // Multiple.
295
                    'post',                                     // Method.
296
                    false,                                      // JSON Encoded.
297
                    false                                       // Auth required.
298
                ];
299
                foreach ($mapping as $map) {
300
                    $map[] = false; // Site api function.
301
                    $map[] = OPEN_BADGES_V1; // V1 function.
302
                    $this->mappings[] = new backpack_api_mapping(...$map);
303
                }
304
            }
305
        }
306
    }
307
 
308
    /**
309
     * Make an api request
310
     *
311
     * @param string $action The api function.
312
     * @param string $collection An api parameter
313
     * @param string $entityid An api parameter
314
     * @param string $postdata The body of the api request.
315
     * @return mixed
316
     */
317
    private function curl_request($action, $collection = null, $entityid = null, $postdata = null) {
318
        global $CFG, $SESSION;
319
 
320
        $curl = new curl();
321
        $authrequired = false;
322
        if ($this->backpackapiversion == OPEN_BADGES_V1) {
323
            $useridkey = $this->get_token_key(BADGE_USER_ID_TOKEN);
324
            if (isset($SESSION->$useridkey)) {
325
                if ($collection == null) {
326
                    $collection = $SESSION->$useridkey;
327
                } else {
328
                    $entityid = $SESSION->$useridkey;
329
                }
330
            }
331
        }
332
        foreach ($this->mappings as $mapping) {
333
            if ($mapping->is_match($action)) {
334
                return $mapping->request(
335
                    $this->backpackapiurl,
336
                    $collection,
337
                    $entityid,
338
                    $this->email,
339
                    $this->password,
340
                    $postdata,
341
                    $this->backpackid
342
                );
343
            }
344
        }
345
 
346
        throw new coding_exception('Unknown request');
347
    }
348
 
349
    /**
350
     * Get the id to use for requests with this api.
351
     *
352
     * @return integer
353
     */
354
    private function get_auth_user_id() {
355
        global $USER;
356
 
357
        if ($this->isuserbackpack) {
358
            return $USER->id;
359
        } else {
360
            // The access tokens for the system backpack are shared.
361
            return -1;
362
        }
363
    }
364
 
365
    /**
366
     * Get the name of the key to store this access token type.
367
     *
368
     * @param string $type
369
     * @return string
370
     */
371
    private function get_token_key($type) {
372
        // This should be removed when everything has a mapping.
373
        $prefix = 'badges_';
374
        if ($this->isuserbackpack) {
375
            $prefix .= 'user_backpack_';
376
        } else {
377
            $prefix .= 'site_backpack_';
378
        }
379
        $prefix .= $type . '_token';
380
        return $prefix;
381
    }
382
 
383
    /**
384
     * Normalise the return from a missing user request.
385
     *
386
     * @param string $status
387
     * @return mixed
388
     */
389
    private function check_status($status) {
390
        // V1 ONLY.
391
        switch($status) {
392
            case "missing":
393
                $response = array(
394
                    'status'  => $status,
395
                    'message' => get_string('error:nosuchuser', 'badges')
396
                );
397
                return $response;
398
        }
399
        return false;
400
    }
401
 
402
    /**
403
     * Make an api request to get an assertion
404
     *
405
     * @param string $entityid The id of the assertion.
406
     * @return mixed
407
     */
408
    public function get_assertion($entityid) {
409
        // V2 Only.
410
        if ($this->backpackapiversion == OPEN_BADGES_V1) {
411
            throw new coding_exception('Not supported in this backpack API');
412
        }
413
 
414
        return $this->curl_request('assertion', null, $entityid);
415
    }
416
 
417
    /**
418
     * Create a badgeclass assertion.
419
     *
420
     * @param string $entityid The id of the badge class.
421
     * @param string $data The structure of the badge class assertion.
422
     * @return mixed
423
     */
424
    public function put_badgeclass_assertion($entityid, $data) {
425
        // V2 Only.
426
        if ($this->backpackapiversion == OPEN_BADGES_V1) {
427
            throw new coding_exception('Not supported in this backpack API');
428
        }
429
 
430
        return $this->curl_request('assertions', null, $entityid, $data);
431
    }
432
 
433
    /**
434
     * Update a badgeclass assertion.
435
     *
436
     * @param string $entityid The id of the badge class.
437
     * @param array $data The structure of the badge class assertion.
438
     * @return mixed
439
     */
440
    public function update_assertion(string $entityid, array $data) {
441
        // V2 Only.
442
        if ($this->backpackapiversion == OPEN_BADGES_V1) {
443
            throw new coding_exception('Not supported in this backpack API');
444
        }
445
 
446
        return $this->curl_request('updateassertion', null, $entityid, $data);
447
    }
448
 
449
    /**
450
     * Import a badge assertion into a backpack. This is used to handle cross domain backpacks.
451
     *
452
     * @param string $data The structure of the badge class assertion.
453
     * @return mixed
454
     * @throws coding_exception
455
     */
456
    public function import_badge_assertion(string $data) {
457
        // V2 Only.
458
        if ($this->backpackapiversion == OPEN_BADGES_V1) {
459
            throw new coding_exception('Not supported in this backpack API');
460
        }
461
 
462
        return $this->curl_request('importbadge', null, null, $data);
463
    }
464
 
465
    /**
466
     * Select collections from a backpack.
467
     *
468
     * @param string $backpackid The id of the backpack
469
     * @param stdClass[] $collections List of collections with collectionid or entityid.
470
     * @return boolean
471
     */
472
    public function set_backpack_collections($backpackid, $collections) {
473
        global $DB, $USER;
474
 
475
        // Delete any previously selected collections.
476
        $sqlparams = array('backpack' => $backpackid);
477
        $select = 'backpackid = :backpack ';
478
        $DB->delete_records_select('badge_external', $select, $sqlparams);
479
        $badgescache = cache::make('core', 'externalbadges');
480
 
481
        // Insert selected collections if they are not in database yet.
482
        foreach ($collections as $collection) {
483
            $obj = new stdClass();
484
            $obj->backpackid = $backpackid;
485
            if ($this->backpackapiversion == OPEN_BADGES_V1) {
486
                $obj->collectionid = (int) $collection;
487
            } else {
488
                $obj->entityid = $collection;
489
                $obj->collectionid = -1;
490
            }
491
            if (!$DB->record_exists('badge_external', (array) $obj)) {
492
                $DB->insert_record('badge_external', $obj);
493
            }
494
        }
495
        $badgescache->delete($USER->id);
496
        return true;
497
    }
498
 
499
    /**
500
     * Create a badgeclass
501
     *
502
     * @param string $entityid The id of the entity.
503
     * @param string $data The structure of the badge class.
504
     * @return mixed
505
     */
506
    public function put_badgeclass($entityid, $data) {
507
        // V2 Only.
508
        if ($this->backpackapiversion == OPEN_BADGES_V1) {
509
            throw new coding_exception('Not supported in this backpack API');
510
        }
511
 
512
        return $this->curl_request('badgeclasses', null, $entityid, $data);
513
    }
514
 
515
    /**
516
     * Create an issuer
517
     *
518
     * @param string $data The structure of the issuer.
519
     * @return mixed
520
     */
521
    public function put_issuer($data) {
522
        // V2 Only.
523
        if ($this->backpackapiversion == OPEN_BADGES_V1) {
524
            throw new coding_exception('Not supported in this backpack API');
525
        }
526
 
527
        return $this->curl_request('issuers', null, null, $data);
528
    }
529
 
530
    /**
531
     * Delete any user access tokens in the session so we will attempt to get new ones.
532
     *
533
     * @return void
534
     */
535
    public function clear_system_user_session() {
536
        global $SESSION;
537
 
538
        $useridkey = $this->get_token_key(BADGE_USER_ID_TOKEN);
539
        unset($SESSION->$useridkey);
540
 
541
        $expireskey = $this->get_token_key(BADGE_EXPIRES_TOKEN);
542
        unset($SESSION->$expireskey);
543
    }
544
 
545
    /**
546
     * Authenticate using the stored email and password and save the valid access tokens.
547
     *
548
     * @return mixed The id of the authenticated user as returned by the backpack. Can have
549
     *    different formats - numeric, empty, object with 'error' property, etc.
550
     */
551
    public function authenticate() {
552
        global $SESSION;
553
 
554
        $backpackidkey = $this->get_token_key(BADGE_BACKPACK_ID_TOKEN);
555
        $backpackid = isset($SESSION->$backpackidkey) ? $SESSION->$backpackidkey : 0;
556
        // If the backpack is changed we need to expire sessions.
557
        if ($backpackid == $this->backpackid) {
558
            if ($this->backpackapiversion == OPEN_BADGES_V2) {
559
                $useridkey = $this->get_token_key(BADGE_USER_ID_TOKEN);
560
                $authuserid = isset($SESSION->$useridkey) ? $SESSION->$useridkey : 0;
561
                if ($authuserid == $this->get_auth_user_id()) {
562
                    $expireskey = $this->get_token_key(BADGE_EXPIRES_TOKEN);
563
                    if (isset($SESSION->$expireskey)) {
564
                        $expires = $SESSION->$expireskey;
565
                        if ($expires > time()) {
566
                            // We have a current access token for this user
567
                            // that has not expired.
568
                            return -1;
569
                        }
570
                    }
571
                }
572
            } else {
573
                $useridkey = $this->get_token_key(BADGE_USER_ID_TOKEN);
574
                $authuserid = isset($SESSION->$useridkey) ? $SESSION->$useridkey : 0;
575
                if (!empty($authuserid)) {
576
                    return $authuserid;
577
                }
578
            }
579
        }
580
        return $this->curl_request('user', $this->email);
581
    }
582
 
583
    /**
584
     * Get all collections in this backpack.
585
     *
586
     * @return stdClass[] The collections.
587
     */
588
    public function get_collections() {
589
        global $PAGE;
590
 
591
        if ($this->authenticate()) {
592
            if ($this->backpackapiversion == OPEN_BADGES_V1) {
593
                $result = $this->curl_request('groups');
594
                if (isset($result->groups)) {
595
                    $result = $result->groups;
596
                }
597
            } else {
598
                $result = $this->curl_request('collections');
599
            }
600
            if ($result) {
601
                return $result;
602
            }
603
        }
604
        return [];
605
    }
606
 
607
    /**
608
     * Get one collection by id.
609
     *
610
     * @param integer $collectionid
611
     * @return stdClass The collection.
612
     */
613
    public function get_collection_record($collectionid) {
614
        global $DB;
615
 
616
        if ($this->backpackapiversion == OPEN_BADGES_V1) {
617
            return $DB->get_fieldset_select('badge_external', 'collectionid', 'backpackid = :bid', array('bid' => $collectionid));
618
        } else {
619
            return $DB->get_fieldset_select('badge_external', 'entityid', 'backpackid = :bid', array('bid' => $collectionid));
620
        }
621
    }
622
 
623
    /**
624
     * Disconnect the backpack from this user.
625
     *
626
     * @param integer $userid The user in Moodle
627
     * @param integer $backpackid The backpack to disconnect
628
     * @return boolean
629
     */
630
    public function disconnect_backpack($userid, $backpackid) {
631
        global $DB, $USER;
632
 
633
        if (\core\session\manager::is_loggedinas() || $userid != $USER->id) {
634
            // Can't change someone elses backpack settings.
635
            return false;
636
        }
637
 
638
        $badgescache = cache::make('core', 'externalbadges');
639
 
640
        $DB->delete_records('badge_external', array('backpackid' => $backpackid));
641
        $DB->delete_records('badge_backpack', array('userid' => $userid));
642
        $badgescache->delete($userid);
643
        $this->clear_system_user_session();
644
 
645
        return true;
646
    }
647
 
648
    /**
649
     * Handle the response from getting a collection to map to an id.
650
     *
651
     * @param stdClass $data The response data.
652
     * @return string The collection id.
653
     */
654
    public function get_collection_id_from_response($data) {
655
        if ($this->backpackapiversion == OPEN_BADGES_V1) {
656
            return $data->groupId;
657
        } else {
658
            return $data->entityId;
659
        }
660
    }
661
 
662
    /**
663
     * Get the last error message returned during an authentication request.
664
     *
665
     * @return string
666
     */
667
    public function get_authentication_error() {
668
        return backpack_api_mapping::get_authentication_error();
669
    }
670
 
671
    /**
672
     * Get the list of badges in a collection.
673
     *
674
     * @param stdClass $collection The collection to deal with.
675
     * @param boolean $expanded Fetch all the sub entities.
676
     * @return stdClass[]
677
     */
678
    public function get_badges($collection, $expanded = false) {
679
        global $PAGE;
680
 
681
        if ($this->authenticate()) {
682
            if ($this->backpackapiversion == OPEN_BADGES_V1) {
683
                if (empty($collection->collectionid)) {
684
                    return [];
685
                }
686
                $result = $this->curl_request('badges', $collection->collectionid);
687
                return $result->badges;
688
            } else {
689
                if (empty($collection->entityid)) {
690
                    return [];
691
                }
692
                // Now we can make requests.
693
                $badges = $this->curl_request('badges', $collection->entityid);
694
                if (count($badges) == 0) {
695
                    return [];
696
                }
697
                $badges = $badges[0];
698
                if ($expanded) {
699
                    $publicassertions = [];
700
                    $context = context_system::instance();
701
                    $output = $PAGE->get_renderer('core', 'badges');
702
                    foreach ($badges->assertions as $assertion) {
703
                        $remoteassertion = $this->get_assertion($assertion);
704
                        // Remote badge was fetched nested in the assertion.
705
                        $remotebadge = $remoteassertion->badgeclass;
706
                        if (!$remotebadge) {
707
                            continue;
708
                        }
709
                        $apidata = badgeclass_exporter::map_external_data($remotebadge, $this->backpackapiversion);
710
                        $exporterinstance = new badgeclass_exporter($apidata, ['context' => $context]);
711
                        $remotebadge = $exporterinstance->export($output);
712
 
713
                        $remoteissuer = $remotebadge->issuer;
714
                        $apidata = issuer_exporter::map_external_data($remoteissuer, $this->backpackapiversion);
715
                        $exporterinstance = new issuer_exporter($apidata, ['context' => $context]);
716
                        $remoteissuer = $exporterinstance->export($output);
717
 
718
                        $badgeclone = clone $remotebadge;
719
                        $badgeclone->issuer = $remoteissuer;
720
                        $remoteassertion->badge = $badgeclone;
721
                        $remotebadge->assertion = $remoteassertion;
722
                        $publicassertions[] = $remotebadge;
723
                    }
724
                    $badges = $publicassertions;
725
                }
726
                return $badges;
727
            }
728
        }
729
    }
730
}