Test Failed
Push — master ( d682dd...1b57e8 )
by Tomasz
09:19
created

CAT::getExternalCountriesList()   A

Complexity

Conditions 6
Paths 2

Size

Total Lines 20
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 15
c 1
b 0
f 0
dl 0
loc 20
rs 9.2222
cc 6
nc 2
nop 0
1
<?php
2
3
/*
4
 * *****************************************************************************
5
 * Contributions to this work were made on behalf of the GÉANT project, a 
6
 * project that has received funding from the European Union’s Framework 
7
 * Programme 7 under Grant Agreements No. 238875 (GN3) and No. 605243 (GN3plus),
8
 * Horizon 2020 research and innovation programme under Grant Agreements No. 
9
 * 691567 (GN4-1) and No. 731122 (GN4-2).
10
 * On behalf of the aforementioned projects, GEANT Association is the sole owner
11
 * of the copyright in all material which was developed by a member of the GÉANT
12
 * project. GÉANT Vereniging (Association) is registered with the Chamber of 
13
 * Commerce in Amsterdam with registration number 40535155 and operates in the 
14
 * UK as a branch of GÉANT Vereniging.
15
 * 
16
 * Registered office: Hoekenrode 3, 1102BR Amsterdam, The Netherlands. 
17
 * UK branch address: City House, 126-130 Hills Road, Cambridge CB2 1PQ, UK
18
 *
19
 * License: see the web/copyright.inc.php file in the file structure or
20
 *          <base_url>/copyright.php after deploying the software
21
 */
22
23
/**
24
 *  This is the definition of the CAT class
25
 * @author Stefan Winter <[email protected]>
26
 * @author Tomasz Wolniewicz <[email protected]>
27
 *
28
 * @package Developer
29
 */
30
/**
31
 * necessary includes
32
 */
33
34
namespace core;
35
36
/**
37
 * Define some variables which need to be globally accessible
38
 * and some general purpose methods
39
 *
40
 * @author Stefan Winter <[email protected]>
41
 * @author Tomasz Wolniewicz <[email protected]>
42
 *
43
 * @package Developer
44
 */
45
class CAT extends \core\common\Entity
46
{
47
48
    /**
49
     * which version is this?
50
     * even if we are unreleased, keep track of internal version-to-be
51
     * developers need to set this in code. The user-displayed string
52
     * is generated into $CAT_VERSION_STRING and $CAT_COPYRIGHT below
53
     */
54
    public const VERSION_MAJOR = 2;
55
    public const VERSION_MINOR = 2;
56
    public const VERSION_PATCH = 1;
57
    public const VERSION_EXTRA = "";
58
    private const RELEASE_VERSION = TRUE;
59
    private const USER_API_VERSION = 2;
60
61
    /**
62
     * trying to keep up with the name changes of copyright holder and consortia
63
     * updating those on *one* place should change display everywhere!
64
     */
65
    private const COPYRIGHT_HOLDER = "G&Eacute;ANT Association";
66
    private const COPYRIGHT_CONSORTIA = "the G&Eacute;ANT Projects funded by EU";
67
    private const COPYRIGHT_MIN_YEAR = 2011;
68
    private const COPYRIGHT_MAX_YEAR = 2025;
69
70
    /**
71
     * This is the user-displayed string; controlled by the four options above
72
     * It is generated in the constructor.
73
     * 
74
     * @var string
75
     */
76
    public $catVersionString;
77
78
    /**
79
     * The entire copyright line, generated in constructor
80
     * 
81
     * @var string
82
     */
83
    public $catCopyright;
84
    
85
    public $catVersion;
86
    
87
    public $catCopyrifhtAndLicense;
88
89
    /**
90
     * all known federation, in an array with ISO short name as an index, and localised version of the pretty-print name as value.
91
     * The static value is only filled with meaningful content after the first object has been instantiated. That is because it is not
92
     * possible to define static properties with function calls like _().
93
     * 
94
     * @var array of all known federations
95
     */
96
    public $knownFederations;
97
98
    /**
99
     * the default database to query in this class.
100
     */
101
    const DB_TYPE = "INST";
102
103
    /**
104
     *  Constructor sets the language by calling set_lang 
105
     *  and stores language settings in object properties
106
     */
107
    public function __construct()
108
    {
109
        parent::__construct();
110
        common\Entity::intoThePotatoes();
111
112
        $this->catVersionString = sprintf("Unreleased %s Git Revision"    , "<a href='https://github.com/GEANT/CAT/tree/master/Changes.md'>") . "</a>";
113
114
        if (CAT::RELEASE_VERSION) {
115
            $major = CAT::VERSION_MAJOR;
116
            $minor = CAT::VERSION_MINOR;
117
            $patch = CAT::VERSION_PATCH;
118
            $extra = CAT::VERSION_EXTRA;
119
            $temp_version = "CAT-$major.$minor.$patch";
120
//            $branch = "release_$major" . "_$minor";
121
            $branch = "v$major.$minor.$patch";
122
//            if (CAT::VERSION_PATCH != 0) {
123
//                $temp_version .= ".$patch";
124
//            }
125
            if (CAT::VERSION_EXTRA != "") {
126
                $temp_version .= "-$extra";
127
            }
128
            $this->catVersionString = sprintf("Release <a href='%s'>%s</a>", "https://github.com/GEANT/CAT/tree/" . $branch . "/Changes.md", $temp_version);
129
130
        }
131
        $product = \config\Master::APPEARANCE['productname'];
132
        $minYear = self::COPYRIGHT_MIN_YEAR;
133
        $maxYear = self::COPYRIGHT_MAX_YEAR;
134
        $holder = self::COPYRIGHT_HOLDER;
135
        $consortia = self::COPYRIGHT_CONSORTIA;
136
        $this->catCopyright = "$product - " . $this->catVersionString . " &copy; $minYear-$maxYear $holder<br/>on behalf of $consortia; and others <a href='copyright.php'>Full Copyright and Licenses</a>";
137
        $this->catCopyrifhtAndLicense = "&copy; $minYear-$maxYear $holder<br/>on behalf of $consortia; and others <a href='copyright.php'>Full Copyright and Licenses</a>";
138
        $this->catVersion = "$product<br>" . $this->catVersionString;
139
140
        /* Federations are created in DB with bootstrapFederation, and listed via listFederations
141
         */
142
143
        $this->knownFederations = [
144
            'AD' => ['name'=>_("Andorra")],
145
            'AT' => ['name'=>_("Austria")],
146
            'BE' => ['name'=>_("Belgium")],
147
            'BG' => ['name'=>_("Bulgaria")],
148
            'CY' => ['name'=>_("Cyprus")],
149
            'CZ' => ['name'=>_("Czech Republic")],
150
            'DK' => ['name'=>_("Denmark")],
151
            'EE' => ['name'=>_("Estonia")],
152
            'FI' => ['name'=>_("Finland")],
153
            'FR' => ['name'=>_("France")],
154
            'DE' => ['name'=>_("Germany")],
155
            'GR' => ['name'=>_("Greece")],
156
            'HR' => ['name'=>_("Croatia")],
157
            'IE' => ['name'=>_("Ireland")],
158
            'IS' => ['name'=>_("Iceland")],
159
            'IT' => ['name'=>_("Italy")],
160
            'HU' => ['name'=>_("Hungary")],
161
            'KS' => ['name'=>_("Kosovo")],
162
            'LU' => ['name'=>_("Luxembourg")],
163
            'LV' => ['name'=>_("Latvia")],
164
            'LT' => ['name'=>_("Lithuania")],
165
            'MK' => ['name'=>_("Macedonia")],
166
            'RS' => ['name'=>_("Serbia")],
167
            'NL' => ['name'=>_("Netherlands")],
168
            'NO' => ['name'=>_("Norway")],
169
            'PL' => ['name'=>_("Poland")],
170
            'PT' => ['name'=>_("Portugal")],
171
            'RO' => ['name'=>_("Romania")],
172
            'SI' => ['name'=>_("Slovenia")],
173
            'ES' => ['name'=>_("Spain")],
174
            'SE' => ['name'=>_("Sweden")],
175
            'SK' => ['name'=>_("Slovakia")],
176
            'CH' => ['name'=>_("Switzerland")],
177
            'TR' => ['name'=>_("Turkey")],
178
            'UK' => ['name'=>_("United Kingdom"), 'code'=>'GB'],
179
            'TEST' => ['name'=>'TEST Country'],
180
            'AU' => ['name'=>_("Australia")],
181
            'CA' => ['name'=>_("Canada")],
182
            'IL' => ['name'=>_("Israel")],
183
            'JP' => ['name'=>_("Japan")],
184
            'NZ' => ['name'=>_("New Zealand")],
185
            'US' => ['name'=>_("U.S.A.")],
186
            'BR' => ['name'=>_("Brazil")],
187
            'CL' => ['name'=>_("Chile")],
188
            'PE' => ['name'=>_("Peru")],
189
            'VE' => ['name'=>_("Venezuela")],
190
            'DEFAULT' => ['name'=>_("Default")],
191
            'AM' => ['name'=>_("Armenia")],
192
            'AZ' => ['name'=>_("Azerbaijan")],
193
//            'BY' => ['name'=>_("Belarus")],
194
            'EC' => ['name'=>_("Ecuador")],
195
            'HK' => ['name'=>_("Hong Kong")],
196
            'KE' => ['name'=>_("Kenya")],
197
            'KG' => ['name'=>_("Kyrgyzstan")],
198
            'KR' => ['name'=>_("Korea")],
199
            'KZ' => ['name'=>_("Kazakhstan")],
200
            'MA' => ['name'=>_("Morocco")],
201
            'MD' => ['name'=>_("Moldova")],
202
            'ME' => ['name'=>_("Montenegro")],
203
            'MO' => ['name'=>_("Macau")],
204
            'MT' => ['name'=>_("Malta")],
205
//            'RU' => ['name'=>_("Russia")],
206
            'SG' => ['name'=>_("Singapore")],
207
            'TH' => ['name'=>_("Thailand")],
208
            'TW' => ['name'=>_("Taiwan")],
209
            'ZA' => ['name'=>_("South Africa")],
210
            'AF' => ['name'=>'Afghanistan'],
211
            'AL' => ['name'=>'Albania'],
212
            'DZ' => ['name'=>'Algeria'],
213
            'AS' => ['name'=>'American Samoa'],
214
            'AO' => ['name'=>'Angola'],
215
            'AI' => ['name'=>'Anguilla'],
216
            'AQ' => ['name'=>'Antarctica'],
217
            'AG' => ['name'=>'Antigua And Barbuda'],
218
            'AR' => ['name'=>'Argentina'],
219
            'AW' => ['name'=>'Aruba'],
220
            'BS' => ['name'=>'Bahamas], The'],
221
            'BH' => ['name'=>'Bahrain'],
222
            'BD' => ['name'=>'Bangladesh'],
223
            'BB' => ['name'=>'Barbados'],
224
            'BZ' => ['name'=>'Belize'],
225
            'BJ' => ['name'=>'Benin'],
226
            'BM' => ['name'=>'Bermuda'],
227
            'BT' => ['name'=>'Bhutan'],
228
            'BO' => ['name'=>'Bolivia'],
229
            'BA' => ['name'=>'Bosnia And Herzegovina'],
230
            'BW' => ['name'=>'Botswana'],
231
            'BV' => ['name'=>'Bouvet Island'],
232
            'IO' => ['name'=>'British Indian Ocean Territory'],
233
            'BN' => ['name'=>'Brunei'],
234
            'BF' => ['name'=>'Burkina Faso'],
235
            'MM' => ['name'=>'Burma'],
236
            'BI' => ['name'=>'Burundi'],
237
            'KH' => ['name'=>'Cambodia'],
238
            'CM' => ['name'=>'Cameroon'],
239
            'CV' => ['name'=>'Cape Verde'],
240
            'KY' => ['name'=>'Cayman Islands'],
241
            'CF' => ['name'=>'Central African Republic'],
242
            'TD' => ['name'=>'Chad'],
243
            'CN' => ['name'=>'China'],
244
            'CX' => ['name'=>'Christmas Island'],
245
            'CC' => ['name'=>'Cocos (keeling) Islands'],
246
            'CO' => ['name'=>'Colombia'],
247
            'KM' => ['name'=>'Comoros'],
248
            'CG' => ['name'=>'Congo (brazzaville) '],
249
            'CD' => ['name'=>'Congo (kinshasa)'],
250
            'CK' => ['name'=>'Cook Islands'],
251
            'CR' => ['name'=>'Costa Rica'],
252
            'CI' => ['name'=>'CÔte D’ivoire'],
253
            'CU' => ['name'=>'Cuba'],
254
            'CW' => ['name'=>'CuraÇao'],
255
            'DJ' => ['name'=>'Djibouti'],
256
            'DM' => ['name'=>'Dominica'],
257
            'DO' => ['name'=>'Dominican Republic'],
258
            'EG' => ['name'=>'Egypt'],
259
            'SV' => ['name'=>'El Salvador'],
260
            'GQ' => ['name'=>'Equatorial Guinea'],
261
            'ER' => ['name'=>'Eritrea'],
262
            'ET' => ['name'=>'Ethiopia'],
263
            'FK' => ['name'=>'Falkland Islands (islas Malvinas)'],
264
            'FO' => ['name'=>'Faroe Islands'],
265
            'FJ' => ['name'=>'Fiji'],
266
            'GF' => ['name'=>'French Guiana'],
267
            'PF' => ['name'=>'French Polynesia'],
268
            'TF' => ['name'=>'French Southern And Antarctic Lands'],
269
            'GA' => ['name'=>'Gabon'],
270
            'GM' => ['name'=>'Gambia], The'],
271
            'GE' => ['name'=>'Georgia'],
272
            'GEANT' => ['name'=>'The GEANT country'],
273
            'GH' => ['name'=>'Ghana'],
274
            'GI' => ['name'=>'Gibraltar'],
275
            'GL' => ['name'=>'Greenland'],
276
            'GD' => ['name'=>'Grenada'],
277
            'GP' => ['name'=>'Guadeloupe'],
278
            'GU' => ['name'=>'Guam'],
279
            'GT' => ['name'=>'Guatemala'],
280
            'GG' => ['name'=>'Guernsey'],
281
            'GN' => ['name'=>'Guinea'],
282
            'GW' => ['name'=>'Guinea-bissau'],
283
            'GY' => ['name'=>'Guyana'],
284
            'HT' => ['name'=>'Haiti'],
285
            'HM' => ['name'=>'Heard Island And Mcdonald Islands'],
286
            'HN' => ['name'=>'Honduras'],
287
            'IN' => ['name'=>'India'],
288
            'ID' => ['name'=>'Indonesia'],
289
            'IR' => ['name'=>'Iran'],
290
            'IQ' => ['name'=>'Iraq'],
291
            'IM' => ['name'=>'Isle Of Man'],
292
            'JM' => ['name'=>'Jamaica'],
293
            'JE' => ['name'=>'Jersey'],
294
            'JO' => ['name'=>'Jordan'],
295
            'KI' => ['name'=>'Kiribati'],
296
            'KP' => ['name'=>'Korea], North'],
297
            'KW' => ['name'=>'Kuwait'],
298
            'LA' => ['name'=>'Laos'],
299
            'LB' => ['name'=>'Lebanon'],
300
            'LS' => ['name'=>'Lesotho'],
301
            'LR' => ['name'=>'Liberia'],
302
            'LY' => ['name'=>'Libya'],
303
            'LI' => ['name'=>'Liechtenstein'],
304
            'MG' => ['name'=>'Madagascar'],
305
            'MW' => ['name'=>'Malawi'],
306
            'MY' => ['name'=>'Malaysia'],
307
            'MV' => ['name'=>'Maldives'],
308
            'ML' => ['name'=>'Mali'],
309
            'MH' => ['name'=>'Marshall Islands'],
310
            'MQ' => ['name'=>'Martinique'],
311
            'MR' => ['name'=>'Mauritania'],
312
            'MU' => ['name'=>'Mauritius'],
313
            'YT' => ['name'=>'Mayotte'],
314
            'MX' => ['name'=>'Mexico'],
315
            'FM' => ['name'=>'Micronesia, Federated States Of'],
316
            'MC' => ['name'=>'Monaco'],
317
            'MN' => ['name'=>'Mongolia'],
318
            'MS' => ['name'=>'Montserrat'],
319
            'MZ' => ['name'=>'Mozambique'],
320
            'NA' => ['name'=>'Namibia'],
321
            'NR' => ['name'=>'Nauru'],
322
            'NP' => ['name'=>'Nepal'],
323
            'NC' => ['name'=>'New Caledonia'],
324
            'NI' => ['name'=>'Nicaragua'],
325
            'NE' => ['name'=>'Niger'],
326
            'NG' => ['name'=>'Nigeria'],
327
            'NU' => ['name'=>'Niue'],
328
            'NF' => ['name'=>'Norfolk Island'],
329
            'MP' => ['name'=>'Northern Mariana Islands'],
330
            'OM' => ['name'=>'Oman'],
331
            'PK' => ['name'=>'Pakistan'],
332
            'PW' => ['name'=>'Palau'],
333
            'PA' => ['name'=>'Panama'],
334
            'PG' => ['name'=>'Papua New Guinea'],
335
            'PY' => ['name'=>'Paraguay'],
336
            'PH' => ['name'=>'Philippines'],
337
            'PN' => ['name'=>'Pitcairn Islands'],
338
            'PR' => ['name'=>'Puerto Rico'],
339
            'QA' => ['name'=>'Qatar'],
340
            'RE' => ['name'=>'Reunion'],
341
            'RW' => ['name'=>'Rwanda'],
342
            'BL' => ['name'=>'Saint Barthelemy'],
343
            'SH' => ['name'=>'Saint Helena, Ascension, And Tristan Da Cunha'],
344
            'KN' => ['name'=>'Saint Kitts And Nevis'],
345
            'LC' => ['name'=>'Saint Lucia'],
346
            'MF' => ['name'=>'Saint Martin'],
347
            'PM' => ['name'=>'Saint Pierre And Miquelon'],
348
            'VC' => ['name'=>'Saint Vincent And The Grenadines'],
349
            'WS' => ['name'=>'Samoa'],
350
            'SM' => ['name'=>'San Marino'],
351
            'ST' => ['name'=>'Sao Tome And Principe'],
352
            'SA' => ['name'=>'Saudi Arabia'],
353
            'SN' => ['name'=>'Senegal'],
354
            'SC' => ['name'=>'Seychelles'],
355
            'SL' => ['name'=>'Sierra Leone'],
356
            'SX' => ['name'=>'Sint Maarten'],
357
            'SB' => ['name'=>'Solomon Islands'],
358
            'SO' => ['name'=>'Somalia'],
359
            'GS' => ['name'=>'South Georgia And South Sandwich Islands'],
360
            'SS' => ['name'=>'South Sudan'],
361
            'LK' => ['name'=>'Sri Lanka'],
362
            'SD' => ['name'=>'Sudan'],
363
            'SR' => ['name'=>'Suriname'],
364
            'SZ' => ['name'=>'Swaziland'],
365
            'SY' => ['name'=>'Syria'],
366
            'TJ' => ['name'=>'Tajikistan'],
367
            'TZ' => ['name'=>'Tanzania'],
368
            'TL' => ['name'=>'Timor-leste'],
369
            'TG' => ['name'=>'Togo'],
370
            'TK' => ['name'=>'Tokelau'],
371
            'TO' => ['name'=>'Tonga'],
372
            'TT' => ['name'=>'Trinidad And Tobago'],
373
            'TN' => ['name'=>'Tunisia'],
374
            'TM' => ['name'=>'Turkmenistan'],
375
            'TC' => ['name'=>'Turks And Caicos Islands'],
376
            'TV' => ['name'=>'Tuvalu'],
377
            'UG' => ['name'=>'Uganda'],
378
            'UA' => ['name'=>'Ukraine'],
379
            'AE' => ['name'=>'United Arab Emirates'],
380
            'GB' => ['name'=>_('United Kingdom')],
381
            'UY' => ['name'=>'Uruguay'],
382
            'UZ' => ['name'=>'Uzbekistan'],
383
            'VU' => ['name'=>'Vanuatu'],
384
            'VA' => ['name'=>'Vatican City'],
385
            'VN' => ['name'=>'Vietnam'],
386
            'VG' => ['name'=>'Virgin Islands, British'],
387
            'VI' => ['name'=>'Virgin Islands, United States '],
388
            'WF' => ['name'=>'Wallis And Futuna'],
389
            'EH' => ['name'=>'Western Sahara'],
390
            'YE' => ['name'=>'Yemen'],
391
            'ZM' => ['name'=>'Zambia'],
392
            'ZW' => ['name'=>'Zimbabwe'],
393
        ];
394
395
        common\Entity::outOfThePotatoes();
396
    }
397
398
    /**
399
     * Calculates the number of IdPs overall in the system
400
     * 
401
     * @param string $level completeness level of IdPs that are to be taken into consideration for counting
402
     * @return int
403
     */
404
    public function totalIdPs($level)
405
    {
406
        $handle = DBConnection::handle(CAT::DB_TYPE);
407
        switch ($level) {
408
            case "ALL":
409
                $idpcount = $handle->exec("SELECT COUNT(inst_id) AS instcount FROM institution");
410
                break;
411
            case "VALIDPROFILE":
412
                $idpcount = $handle->exec("SELECT COUNT(DISTINCT institution.inst_id) AS instcount FROM institution,profile WHERE institution.inst_id = profile.inst_id AND profile.sufficient_config = 1");
413
                break;
414
            case "PUBLICPROFILE":
415
                $idpcount = $handle->exec("SELECT COUNT(DISTINCT institution.inst_id) AS instcount FROM institution,profile WHERE institution.inst_id = profile.inst_id AND profile.showtime = 1");
416
                break;
417
            default:
418
                return -1;
419
        }
420
        // SELECTs never return a booleans, always an object
421
        $dbresult = mysqli_fetch_object(/** @scrutinizer ignore-type */ $idpcount);
422
        return $dbresult->instcount;
423
    }
424
425
    /**
426
     * Lists all identity providers in the database
427
     * adding information required by DiscoJuice.
428
     * 
429
     * @param int    $activeOnly if set to non-zero will cause listing of only those institutions which have some valid profiles defined.
430
     * @param string $country    if set, only list IdPs in a specific country
431
     * @return array the list of identity providers
432
     *
433
     */
434
    public function listAllIdentityProviders($activeOnly = 0, $country = "")
435
    {
436
        common\Entity::intoThePotatoes();
437
        $handle = DBConnection::handle("INST");
438
        $handle->exec("SET SESSION group_concat_max_len=10000");
439
        $query = "SELECT distinct institution.inst_id AS inst_id, institution.country AS country,
440
                     group_concat(concat_ws('===',institution_option.option_name,LEFT(institution_option.option_value,200), institution_option.option_lang) separator '---') AS options
441
                     FROM institution ";
442
        if ($activeOnly == 1) {
443
            $query .= "JOIN v_active_inst ON institution.inst_id = v_active_inst.inst_id ";
444
        }
445
        $query .= "JOIN institution_option ON institution.inst_id = institution_option.institution_id ";
446
        $query .= "WHERE (institution_option.option_name = 'general:instname' 
447
                          OR institution_option.option_name = 'general:geo_coordinates'
448
                          OR institution_option.option_name = 'general:logo_file') ";
449
450
        $query .= ($country != "" ? "AND institution.country = ? " : "");
451
452
        $query .= "GROUP BY institution.inst_id ORDER BY inst_id";
453
454
        $allIDPs = ($country != "" ? $handle->exec($query, "s", $country) : $handle->exec($query));
455
        $returnarray = [];
456
        // SELECTs never return a booleans, always an object
457
        while ($queryResult = mysqli_fetch_object(/** @scrutinizer ignore-type */ $allIDPs)) {
458
            $institutionOptions = explode('---', $queryResult->options);
459
            $oneInstitutionResult = [];
460
            $geo = [];
461
            $names = [];
462
463
            $oneInstitutionResult['entityID'] = $queryResult->inst_id;
464
            $oneInstitutionResult['country'] = strtoupper($queryResult->country);
465
            foreach ($institutionOptions as $institutionOption) {
466
                $opt = explode('===', $institutionOption);
467
                switch ($opt[0]) {
468
                    case 'general:logo_file':
469
                        $oneInstitutionResult['icon'] = $queryResult->inst_id;
470
                        break;
471
                    case 'general:geo_coordinates':
472
                        $at1 = json_decode($opt[1], true);
473
                        $geo[] = $at1;
474
                        break;
475
                    case 'general:instname':
476
                        $names[] = [
477
                            'lang' => $opt[2],
478
                            'value' => $opt[1]
479
                        ];
480
                        break;
481
                    default:
482
                        break;
483
                }
484
            }
485
486
            $name = _("Unnamed Entity");
487
            if (count($names) != 0) {
488
                $langObject = new \core\common\Language();
489
                $name = $langObject->getLocalisedValue($names);
490
            }
491
            $oneInstitutionResult['title'] = $name;
492
            if (count($geo) > 0) {
493
                $oneInstitutionResult['geo'] = $geo;
494
            }
495
            $returnarray[] = $oneInstitutionResult;
496
        }
497
        common\Entity::outOfThePotatoes();
498
        return $returnarray;
499
    }
500
501
    /**
502
     * Prepares a list of countries known to the CAT.
503
     * 
504
     * @param int $activeOnly is set and nonzero will cause that only countries with some institutions underneath will be listed
505
     * @return array Array indexed by (uppercase) lang codes and sorted according to the current locale
506
     */
507
    public function printCountryList($activeOnly = 0)
508
    {
509
        $olddomain = $this->languageInstance->setTextDomain("core");
510
        $handle = DBConnection::handle(CAT::DB_TYPE);
511
        $returnArray = []; // in if -> the while might never be executed, so initialise
512
        if ($activeOnly) {
513
            $federations = $handle->exec("SELECT DISTINCT UPPER(institution.country) AS country FROM institution JOIN profile
514
                          ON institution.inst_id = profile.inst_id WHERE profile.showtime = 1 ORDER BY country");
515
            // SELECT never returns a boolean, always a mysqli_object
516
            while ($activeFederations = mysqli_fetch_object(/** @scrutinizer ignore-type */ $federations)) {
517
                $fedIdentifier = $activeFederations->country; // UPPER() has capitalised this for us
518
                $returnArray[$fedIdentifier] = isset($this->knownFederations[$fedIdentifier]) ? $this->knownFederations[$fedIdentifier]['name'] : $fedIdentifier;
519
            }
520
        } else {
521
            foreach ($this->knownFederations as $fedIdentifier => $value) {
522
                $returnArray[$fedIdentifier] = $value['name'];
523
            }
524
        }
525
        asort($returnArray, SORT_LOCALE_STRING);
526
        $this->languageInstance->setTextDomain($olddomain);
527
        return($returnArray);
528
    }
529
530
    /**
531
     * get additional details about an institution from the EXTERNAL customer DB
532
     * (if any; for eduroam, this would be the official eduroam database)
533
     * 
534
     * @param string $externalId the ID of the institution in the external DB
535
     * @param string $ROid - the ID of the federation in the external DB - we assume that it is always of the form strtoupper($country_code).'01'
536
     * @param string $realm      the function can also try to find an inst by its realm in the external DB
537
     * @return array a list of institutions, ideally with only one member
538
     * @throws \Exception
539
     */
540
    public function getExternalDBEntityDetails($externalId, $ROid, $realm = NULL)
541
    {
542
        $list = [];
543
        if (\config\ConfAssistant::CONSORTIUM['name'] == "eduroam" && isset(\config\ConfAssistant::CONSORTIUM['deployment-voodoo']) && \config\ConfAssistant::CONSORTIUM['deployment-voodoo'] == "Operations Team") { // SW: APPROVED
544
            $scanforrealm = "";
545
            if ($realm !== NULL) {
546
                $scanforrealm = "OR inst_realm LIKE '%$realm%'";
547
            }
548
            $externalHandle = DBConnection::handle("EXTERNAL");
549
            $infoList = $externalHandle->exec("SELECT name AS collapsed_name, inst_realm as realmlist, contact AS collapsed_contact, country, type FROM view_active_institution WHERE instid = '$externalId' AND ROid = '$ROid' $scanforrealm");
550
            // split names and contacts into proper pairs
551
            // SELECT never returns a boolean, always a mysqli_object
552
            while ($externalEntityQuery = mysqli_fetch_object(/** @scrutinizer ignore-type */ $infoList)) {
553
                $list['names'] = \core\ExternalEduroamDBData::dissectCollapsedInstitutionNames($externalEntityQuery->collapsed_name)['perlang'];
554
                $contacts = \core\ExternalEduroamDBData::dissectCollapsedContacts($externalEntityQuery->collapsed_contact);
555
                foreach ($contacts as $contact) {
556
                    $list['admins'][] = ["email" => $contact['mail']];
557
                }
558
                $list['country'] = strtoupper($externalEntityQuery->country);
559
                $list['realmlist'] = $externalEntityQuery->realmlist;
560
                switch ($externalEntityQuery->type) {
561
                    case ExternalEduroamDBData::TYPE_IDP:
562
                        $list['type'] = IdP::TYPE_IDP;
563
                        break;
564
                    case ExternalEduroamDBData::TYPE_SP:
565
                        $list['type'] = IdP::TYPE_SP;
566
                        break;
567
                    case ExternalEduroamDBData::TYPE_IDPSP:
568
                        $list['type'] = IdP::TYPE_IDPSP;
569
                        break;
570
                    default:
571
                        throw new \Exception("Eduroam DB returned a participant type we do not know.");
572
                }
573
            }
574
        }
575
        return $list;
576
    }
577
578
    /**
579
     * the list of countries as per external DB
580
     * @return array the list
581
     */
582
    public function getExternalCountriesList()
583
    {
584
        $olddomain = $this->languageInstance->setTextDomain("core");
585
        $returnArray = []; // in if -> the while might never be executed, so initialise
586
        if (\config\ConfAssistant::CONSORTIUM['name'] == "eduroam" && isset(\config\ConfAssistant::CONSORTIUM['deployment-voodoo']) && \config\ConfAssistant::CONSORTIUM['deployment-voodoo'] == "Operations Team") { // SW: APPROVED
587
            $handle = DBConnection::handle("EXTERNAL");
588
            $timeStart = microtime(true);
589
            $federations = $handle->exec("SELECT DISTINCT UPPER(country) AS country FROM view_active_institution ORDER BY country");
590
            $timeEnd = microtime(true);
591
            $timeElapsed = $timeEnd - $timeStart;
592
            // the query yielded a mysqli_result because it's a SELECT, this never gives back a boolean
593
            while ($eduroamFederations = mysqli_fetch_object(/** @scrutinizer ignore-type */ $federations)) {
594
                $fedIdentifier = $eduroamFederations->country;
595
                $returnArray[$fedIdentifier] = isset($this->knownFederations[$fedIdentifier]) ? $this->knownFederations[$fedIdentifier]['name'] : $fedIdentifier;
596
            }
597
            asort($returnArray, SORT_LOCALE_STRING);
598
            $returnArray['time'] = $timeElapsed;
599
        }
600
        $this->languageInstance->setTextDomain($olddomain);
601
        return($returnArray);
602
    }
603
604
    /**
605
     * the (HTML) root path of the CAT deployment
606
     * 
607
     * @return string
608
     */
609
    public static function getRootUrlPath()
610
    {
611
        return substr(\config\Master::PATHS['cat_base_url'], -1) === '/' ? substr(\config\Master::PATHS['cat_base_url'], 0, -1) : \config\Master::PATHS['cat_base_url'];
612
    }
613
614
    /**
615
     * takes care of starting our session
616
     * 
617
     * @return void
618
     */
619
    public static function sessionStart()
620
    {
621
        $loggerInstance = new \core\common\Logging();
622
        if (session_status() != PHP_SESSION_ACTIVE) {
623
            $loggerInstance->debug(4, "Session start\n");
624
            session_name("CAT");
625
            session_set_cookie_params([
626
                'lifetime' => 0,
627
                'path' => "/",
628
                'domain' => $_SERVER['HTTP_HOST'],
629
                'secure' => (isset($_SERVER['HTTPS']) ? TRUE : FALSE),
630
                'httponly' => false,
631
                'samesite' => 'strict'
632
        ]);               
633
            session_start();
634
        }
635
    }
636
637
    /**
638
     * determines which external DB to use, and returns an object instance
639
     * 
640
     * @return \core\ExternalEduroamDBData|\core\ExternalNothing
641
     */
642
    public static function determineExternalConnection()
643
    {
644
        if (\config\ConfAssistant::CONSORTIUM['name'] == "eduroam" && isset(\config\ConfAssistant::CONSORTIUM['deployment-voodoo']) && \config\ConfAssistant::CONSORTIUM['deployment-voodoo'] == "Operations Team") {
645
            return new ExternalEduroamDBData();
646
        }
647
        return new ExternalNothing();
648
    }
649
650
    public function getSuperglueZone()
651
    {
652
        $externalDB = CAT::determineExternalConnection();
653
        return $externalDB->listExternalRealms();
654
    }
655
656
    public static function hostedSPEnabled() {
657
        return \config\Master::FUNCTIONALITY_LOCATIONS['CONFASSISTANT_MSP'] === 'LOCAL';    
658
    }
659
    
660
    public static function hostedIDPEnabled() {
661
        return \config\Master::FUNCTIONALITY_LOCATIONS['CONFASSISTANT_MIDP'] === 'LOCAL';
662
    }
663
    
664
    public static function radiusProfilesEnabled() {
665
        return \config\Master::FUNCTIONALITY_LOCATIONS['CONFASSISTANT_RADIUS'] === 'LOCAL';        
666
    }
667
    
668
    public static function hostedServicesEnabled() {
669
        return \core\CAT::hostedIDPEnabled() || \core\CAT::hostedSPEnabled();
670
    }
671
}
672