Completed
Push — master ( 03ec64...ee79b5 )
by
unknown
07:25
created

Federation   C

Complexity

Total Complexity 78

Size/Duplication

Total Lines 605
Duplicated Lines 4.13 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 2
Bugs 0 Features 0
Metric Value
dl 25
loc 605
rs 5.4355
c 2
b 0
f 0
wmc 78
lcom 1
cbo 7

8 Methods

Rating   Name   Duplication   Size   Complexity  
F downloadStats() 0 44 21
B __construct() 25 307 5
A newIdP() 0 16 4
B listIdentityProviders() 0 25 3
B listFederationAdmins() 0 11 5
C listExternalEntities() 0 68 17
C getExternalDBEntityDetails() 0 27 8
F listAllIdentityProviders() 0 59 15

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Federation often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Federation, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/* * *********************************************************************************
4
 * (c) 2011-15 GÉANT on behalf of the GN3, GN3plus and GN4 consortia
5
 * License: see the LICENSE file in the root directory
6
 * ********************************************************************************* */
7
?>
8
<?php
9
10
/**
11
 * This file contains the Federation class.
12
 * 
13
 * @author Stefan Winter <[email protected]>
14
 * @author Tomasz Wolniewicz <[email protected]>
15
 * 
16
 * @package Developer
17
 * 
18
 */
19
/**
20
 * necessary includes
21
 */
22
require_once("CAT.php");
23
require_once('IdP.php');
24
require_once('EntityWithDBProperties.php');
25
26
/**
27
 * This class represents an consortium federation.
28
 * It is semantically a country(!). Do not confuse this with a TLD; a federation
29
 * may span more than one TLD, and a TLD may be distributed across multiple federations.
30
 *
31
 * Example: a federation "fr" => "France" may also contain other TLDs which
32
 *              belong to France in spite of their different TLD
33
 * Example 2: Domains ending in .edu are present in multiple different
34
 *              federations
35
 *
36
 * @author Stefan Winter <[email protected]>
37
 * @author Tomasz Wolniewicz <[email protected]>
38
 *
39
 * @license see LICENSE file in root directory
40
 *
41
 * @package Developer
42
 */
43
class Federation extends EntityWithDBProperties {
44
    
45
    /**
46
     * all known federation, in an array with ISO short name as an index, and localised version of the pretty-print name as value.
47
     * The static value is only filled with meaningful content after the first object has been instantiated. That is because it is not
48
     * possible to define static properties with function calls like _().
49
     * 
50
     * @var array of all known federations
51
     */
52
    public static $FederationList = [];
53
54
        public static function downloadStats($federationid = NULL, $astablerows = FALSE) {
55
        $gross_admin = 0;
56
        $gross_user = 0;
57
58
        $timestamp = date("Y-m-d") . "T" . date("H:i:s");
59
        
60
        $retstring = "";
61
        if (!$astablerows)
62
            $retstring .= "<federation id='" . ( $federationid == NULL ? "ALL" : $federationid ) . "' ts='$timestamp'>\n";
63
64
        foreach (Devices::listDevices() as $index => $device_array) {
65
            $query = "SELECT SUM(downloads_admin) AS admin, SUM(downloads_user) AS user FROM downloads, profile, institution WHERE device_id = '$index' AND downloads.profile_id = profile.profile_id AND profile.inst_id = institution.inst_id ";
66
            if ($federationid != NULL) {
67
                $query .= "AND institution.country = '" . $federationid . "'";
68
            }
69
            $retstring .= ($astablerows ? "<tr>" : "  <device name='" . $device_array['display'] . "'>\n");
70
            $admin_query = DBConnection::exec($this->databaseType, $query);
0 ignored issues
show
Bug introduced by
The variable $this does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
71
            while ($a = mysqli_fetch_object($admin_query)) {
72
                if ($astablerows)
73
                    $retstring .= "<td>" . $device_array['display'] . "</td>";
74
                $retstring .= ($astablerows ? "<td>" : "    <downloads group='admin'>");
75
                $retstring .= ( $a->admin === NULL ? "0" : $a->admin);
76
                $retstring .= ($astablerows ? "</td><td>" : "</downloads>\n    <downloads group='user'>");
77
                $retstring .= ( $a->user === NULL ? "0" : $a->user);
78
                $retstring .= ($astablerows ? "</td>" : "</downloads>\n");
79
                $gross_admin = $gross_admin + $a->admin;
80
                $gross_user = $gross_user + $a->user;
81
            }
82
            $retstring .= ($astablerows ? "</tr>" : "  </device>\n");
83
        }
84
        $retstring .= ($astablerows ? "<tr>" : "  <total>\n");
85
        if ($astablerows)
86
            $retstring .= "<td><strong>TOTAL</ts>";
87
        $retstring .= ($astablerows ? "<td><strong>" : "    <downloads group='admin'>");
88
        $retstring .= $gross_admin;
89
        $retstring .= ($astablerows ? "</strong></td><td><strong>" : "</downloads>\n    <downloads group='user'>");
90
        $retstring .= $gross_user;
91
        $retstring .= ($astablerows ? "</strong></td>" : "</downloads>\n");
92
        $retstring .= ($astablerows ? "</tr>" : "  </total>\n");
93
        if (!$astablerows)
94
            $retstring .= "</federation>\n";
95
96
        return $retstring;
97
    }
98
99
    /**
100
     *
101
     * Constructs a Federation object.
102
     *
103
     * @param string $fedname - textual representation of the Federation object
104
     *        Example: "lu" (for Luxembourg)
105
     */
106
    public function __construct($fedname = "") {
107
        
108
        // initialise the superclass variables
109
        
110
        $this->databaseType = "INST";
111
        $this->entityOptionTable = "federation_option";
112
        $this->entityIdColumn = "country";
113
        $this->identifier = $fedname;
114
        $this->name = $fedname;
115
        $this->attributes = [];
116
        
117
        /* Federations are created in DB with bootstrapFederation, and listed via listFederations
118
         */
119
        $oldlocale = CAT::set_locale('core');
120
        
121
        Federation::$FederationList = [
122
            'AD' => _("Andorra"),
123
            'AT' => _("Austria"),
124
            'BE' => _("Belgium"),
125
            'BG' => _("Bulgaria"),
126
            'CY' => _("Cyprus"),
127
            'CZ' => _("Czech Republic"),
128
            'DK' => _("Denmark"),
129
            'EE' => _("Estonia"),
130
            'FI' => _("Finland"),
131
            'FR' => _("France"),
132
            'DE' => _("Germany"),
133
            'GR' => _("Greece"),
134
            'HR' => _("Croatia"),
135
            'IE' => _("Ireland"),
136
            'IS' => _("Iceland"),
137
            'IT' => _("Italy"),
138
            'HU' => _("Hungary"),
139
            'LU' => _("Luxembourg"),
140
            'LV' => _("Latvia"),
141
            'LT' => _("Lithuania"),
142
            'MK' => _("Macedonia"),
143
            'RS' => _("Serbia"),
144
            'NL' => _("Netherlands"),
145
            'NO' => _("Norway"),
146
            'PL' => _("Poland"),
147
            'PT' => _("Portugal"),
148
            'RO' => _("Romania"),
149
            'SI' => _("Slovenia"),
150
            'ES' => _("Spain"),
151
            'SE' => _("Sweden"),
152
            'SK' => _("Slovakia"),
153
            'CH' => _("Switzerland"),
154
            'TR' => _("Turkey"),
155
            'UK' => _("United Kingdom"),
156
            'TEST' => 'TEST Country',
157
            'AU' => _("Australia"),
158
            'CA' => _("Canada"),
159
            'IL' => _("Israel"),
160
            'JP' => _("Japan"),
161
            'NZ' => _("New Zealand"),
162
            'US' => _("U.S.A."),
163
            'BR' => _("Brazil"),
164
            'CL' => _("Chile"),
165
            'PE' => _("Peru"),
166
            'VE' => _("Venezuela"),
167
            'DEFAULT' => _("Default"),
168
            'AM' => _("Armenia"),
169
            'AZ' => _("Azerbaijan"),
170
            'BY' => _("Belarus"),
171
            'EC' => _("Ecuador"),
172
            'HK' => _("Hong Kong"),
173
            'KE' => _("Kenya"),
174
            'KG' => _("Kyrgyzstan"),
175
            'KR' => _("Korea"),
176
            'KZ' => _("Kazakhstan"),
177
            'MA' => _("Morocco"),
178
            'MD' => _("Moldova"),
179
            'ME' => _("Montenegro"),
180
            'MO' => _("Macau"),
181
            'MT' => _("Malta"),
182
            'RU' => _("Russia"),
183
            'SG' => _("Singapore"),
184
            'TH' => _("Thailand"),
185
            'TW' => _("Taiwan"),
186
            'ZA' => _("South Africa"),
187
            'AF' => 'Afghanistan',
188
            'AL' => 'Albania',
189
            'DZ' => 'Algeria',
190
            'AS' => 'American Samoa',
191
            'AO' => 'Angola',
192
            'AI' => 'Anguilla',
193
            'AQ' => 'Antarctica',
194
            'AG' => 'Antigua And Barbuda',
195
            'AR' => 'Argentina',
196
            'AW' => 'Aruba',
197
            'BS' => 'Bahamas, The',
198
            'BH' => 'Bahrain',
199
            'BD' => 'Bangladesh',
200
            'BB' => 'Barbados',
201
            'BZ' => 'Belize',
202
            'BJ' => 'Benin',
203
            'BM' => 'Bermuda',
204
            'BT' => 'Bhutan',
205
            'BO' => 'Bolivia',
206
            'BA' => 'Bosnia And Herzegovina',
207
            'BW' => 'Botswana',
208
            'BV' => 'Bouvet Island',
209
            'IO' => 'British Indian Ocean Territory',
210
            'BN' => 'Brunei',
211
            'BF' => 'Burkina Faso',
212
            'MM' => 'Burma',
213
            'BI' => 'Burundi',
214
            'KH' => 'Cambodia',
215
            'CM' => 'Cameroon',
216
            'CV' => 'Cape Verde',
217
            'KY' => 'Cayman Islands',
218
            'CF' => 'Central African Republic',
219
            'TD' => 'Chad',
220
            'CN' => 'China',
221
            'CX' => 'Christmas Island',
222
            'CC' => 'Cocos (keeling) Islands',
223
            'CO' => 'Colombia',
224
            'KM' => 'Comoros',
225
            'CG' => 'Congo (brazzaville) ',
226
            'CD' => 'Congo (kinshasa)',
227
            'CK' => 'Cook Islands',
228
            'CR' => 'Costa Rica',
229
            'CI' => 'CÔte D’ivoire',
230
            'CU' => 'Cuba',
231
            'CW' => 'CuraÇao',
232
            'DJ' => 'Djibouti',
233
            'DM' => 'Dominica',
234
            'DO' => 'Dominican Republic',
235
            'EG' => 'Egypt',
236
            'SV' => 'El Salvador',
237
            'GQ' => 'Equatorial Guinea',
238
            'ER' => 'Eritrea',
239
            'ET' => 'Ethiopia',
240
            'FK' => 'Falkland Islands (islas Malvinas)',
241
            'FO' => 'Faroe Islands',
242
            'FJ' => 'Fiji',
243
            'GF' => 'French Guiana',
244
            'PF' => 'French Polynesia',
245
            'TF' => 'French Southern And Antarctic Lands',
246
            'GA' => 'Gabon',
247
            'GM' => 'Gambia, The',
248
            'GE' => 'Georgia',
249
            'GH' => 'Ghana',
250
            'GI' => 'Gibraltar',
251
            'GL' => 'Greenland',
252
            'GD' => 'Grenada',
253
            'GP' => 'Guadeloupe',
254
            'GU' => 'Guam',
255
            'GT' => 'Guatemala',
256
            'GG' => 'Guernsey',
257
            'GN' => 'Guinea',
258
            'GW' => 'Guinea-bissau',
259
            'GY' => 'Guyana',
260
            'HT' => 'Haiti',
261
            'HM' => 'Heard Island And Mcdonald Islands',
262
            'HN' => 'Honduras',
263
            'IN' => 'India',
264
            'ID' => 'Indonesia',
265
            'IR' => 'Iran',
266
            'IQ' => 'Iraq',
267
            'IM' => 'Isle Of Man',
268
            'JM' => 'Jamaica',
269
            'JE' => 'Jersey',
270
            'JO' => 'Jordan',
271
            'KI' => 'Kiribati',
272
            'KP' => 'Korea, North',
273
            'KW' => 'Kuwait',
274
            'LA' => 'Laos',
275
            'LB' => 'Lebanon',
276
            'LS' => 'Lesotho',
277
            'LR' => 'Liberia',
278
            'LY' => 'Libya',
279
            'LI' => 'Liechtenstein',
280
            'MG' => 'Madagascar',
281
            'MW' => 'Malawi',
282
            'MY' => 'Malaysia',
283
            'MV' => 'Maldives',
284
            'ML' => 'Mali',
285
            'MH' => 'Marshall Islands',
286
            'MQ' => 'Martinique',
287
            'MR' => 'Mauritania',
288
            'MU' => 'Mauritius',
289
            'YT' => 'Mayotte',
290
            'MX' => 'Mexico',
291
            'FM' => 'Micronesia, Federated States Of',
292
            'MC' => 'Monaco',
293
            'MN' => 'Mongolia',
294
            'MS' => 'Montserrat',
295
            'MZ' => 'Mozambique',
296
            'NA' => 'Namibia',
297
            'NR' => 'Nauru',
298
            'NP' => 'Nepal',
299
            'NC' => 'New Caledonia',
300
            'NI' => 'Nicaragua',
301
            'NE' => 'Niger',
302
            'NG' => 'Nigeria',
303
            'NU' => 'Niue',
304
            'NF' => 'Norfolk Island',
305
            'MP' => 'Northern Mariana Islands',
306
            'OM' => 'Oman',
307
            'PK' => 'Pakistan',
308
            'PW' => 'Palau',
309
            'PA' => 'Panama',
310
            'PG' => 'Papua New Guinea',
311
            'PY' => 'Paraguay',
312
            'PH' => 'Philippines',
313
            'PN' => 'Pitcairn Islands',
314
            'PR' => 'Puerto Rico',
315
            'QA' => 'Qatar',
316
            'RE' => 'Reunion',
317
            'RW' => 'Rwanda',
318
            'BL' => 'Saint Barthelemy',
319
            'SH' => 'Saint Helena, Ascension, And Tristan Da Cunha',
320
            'KN' => 'Saint Kitts And Nevis',
321
            'LC' => 'Saint Lucia',
322
            'MF' => 'Saint Martin',
323
            'PM' => 'Saint Pierre And Miquelon',
324
            'VC' => 'Saint Vincent And The Grenadines',
325
            'WS' => 'Samoa',
326
            'SM' => 'San Marino',
327
            'ST' => 'Sao Tome And Principe',
328
            'SA' => 'Saudi Arabia',
329
            'SN' => 'Senegal',
330
            'SC' => 'Seychelles',
331
            'SL' => 'Sierra Leone',
332
            'SX' => 'Sint Maarten',
333
            'SB' => 'Solomon Islands',
334
            'SO' => 'Somalia',
335
            'GS' => 'South Georgia And South Sandwich Islands',
336
            'SS' => 'South Sudan',
337
            'LK' => 'Sri Lanka',
338
            'SD' => 'Sudan',
339
            'SR' => 'Suriname',
340
            'SZ' => 'Swaziland',
341
            'SY' => 'Syria',
342
            'TJ' => 'Tajikistan',
343
            'TZ' => 'Tanzania',
344
            'TL' => 'Timor-leste',
345
            'TG' => 'Togo',
346
            'TK' => 'Tokelau',
347
            'TO' => 'Tonga',
348
            'TT' => 'Trinidad And Tobago',
349
            'TN' => 'Tunisia',
350
            'TM' => 'Turkmenistan',
351
            'TC' => 'Turks And Caicos Islands',
352
            'TV' => 'Tuvalu',
353
            'UG' => 'Uganda',
354
            'UA' => 'Ukraine',
355
            'AE' => 'United Arab Emirates',
356
            'GB' => 'United Kingdom',
357
            'UY' => 'Uruguay',
358
            'UZ' => 'Uzbekistan',
359
            'VU' => 'Vanuatu',
360
            'VA' => 'Vatican City',
361
            'VN' => 'Vietnam',
362
            'VG' => 'Virgin Islands, British',
363
            'VI' => 'Virgin Islands, United States ',
364
            'WF' => 'Wallis And Futuna',
365
            'EH' => 'Western Sahara',
366
            'YE' => 'Yemen',
367
            'ZM' => 'Zambia',
368
            'ZW' => 'Zimbabwe',
369
        ];
370
371
        CAT::set_locale($oldlocale);
372
        
373
        
374
        $fedAttributes = DBConnection::exec($this->databaseType, "SELECT DISTINCT option_name,option_value, row FROM federation_option
375
              WHERE federation_id = '$this->name'  ORDER BY option_name");
376
377
        
378
379
        $optioninstance = Options::instance();
380
381 View Code Duplication
        while ($a = mysqli_fetch_object($fedAttributes)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
382
            $lang = "";
383
            // decode base64 for files (respecting multi-lang)
384
            $optinfo = $optioninstance->optionType($a->option_name);
385
            $flag = $optinfo['flag'];
386
387
            if ($optinfo['type'] != "file") {
388
                $this->attributes[] = array("name" => $a->option_name, "value" => $a->option_value, "level" => "FED", "row" => $a->row, "flag" => $flag);
389
            } else {
390
                // suppress E_NOTICE on the following... we are testing *if*
391
                // we have a serialized value - so not having one is fine and
392
                // shouldn't throw E_NOTICE
393
                if (@unserialize($a->option_value) !== FALSE) { // multi-lang
394
                    $content = unserialize($a->option_value);
395
                    $lang = $content['lang'];
396
                    $content = $content['content'];
397
                } else { // single lang, direct content
398
                    $content = $a->option_value;
399
                }
400
401
                $content = base64_decode($content);
402
403
                $this->attributes[] = array("name" => $a->option_name, "value" => ($lang == "" ? $content : serialize(Array('lang' => $lang, 'content' => $content))), "level" => "FED", "row" => $a->row, "flag" => $flag);
404
            }
405
        }
406
        $this->attributes[] = array("name" => "internal:country",
407
            "value" => $this->name,
408
            "level" => "FED",
409
            "row" => 0,
410
            "flag" => NULL);
411
412
    }
413
414
    /**
415
     * Creates a new IdP inside the federation.
416
     * 
417
     * @param string $owner_id Persistent identifier of the user for whom this IdP is created (first administrator)
418
     * @param string $level Privilege level of the first administrator (was he blessed by a federation admin or a peer?)
419
     * @param string $mail e-mail address with which the user was invited to administer (useful for later user identification if the user chooses a "funny" real name)
420
     * @return int identifier of the new IdP
421
     */
422
    public function newIdP($owner_id, $level, $mail) {
423
        DBConnection::exec($this->databaseType, "INSERT INTO institution (country) VALUES('$this->name')");
424
        $identifier = DBConnection::lastID($this->databaseType);
425
        if ($identifier == 0 || !CAT::writeAudit($owner_id, "NEW", "IdP $identifier")) {
0 ignored issues
show
Bug Best Practice introduced by
The expression \CAT::writeAudit($owner_...', "IdP {$identifier}") of type boolean|null is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
426
            echo "<p>" . _("Could not create a new Institution!") . "</p>";
427
            exit(1);
428
        }
429
        // escape all strings
430
        $escapedOwnerId = DBConnection::escape_value($this->databaseType, $owner_id);
431
        $escapedLevel = DBConnection::escape_value($this->databaseType, $level);
432
        $escapedMail = DBConnection::escape_value($this->databaseType, $mail);
433
434
        if ($escapedOwnerId != "PENDING")
435
            DBConnection::exec($this->databaseType, "INSERT INTO ownership (user_id,institution_id, blesslevel, orig_mail) VALUES('$escapedOwnerId', $identifier, '$escapedLevel', '$escapedMail')");
436
        return $identifier;
437
    }
438
439
    /**
440
     * Lists all Identity Providers in this federation
441
     *
442
     * @param int $active_only if set to non-zero will list only those institutions which have some valid profiles defined.
443
     * @return array (Array of IdP instances)
444
     *
445
     */
446
    public function listIdentityProviders($active_only = 0) {
447
        if ($active_only) {
448
            $allIDPs = DBConnection::exec($this->databaseType, "SELECT distinct institution.inst_id AS inst_id
449
               FROM institution
450
               JOIN profile ON institution.inst_id = profile.inst_id
451
               WHERE institution.country = '$this->name' 
452
               AND profile.showtime = 1
453
               ORDER BY inst_id");
454
        } else {
455
            $allIDPs = DBConnection::exec($this->databaseType, "SELECT inst_id FROM institution
456
               WHERE country = '$this->name' ORDER BY inst_id");
457
        }
458
459
        $returnarray = [];
460
        while ($a = mysqli_fetch_object($allIDPs)) {
461
            $idp = new IdP($a->inst_id);
462
            $name = $idp->name;
463
            $A = ['entityID' => $idp->identifier,
464
                'title' => $name,
465
                'country' => strtoupper($idp->federation),
466
                'instance' => $idp];
467
            $returnarray[$idp->identifier] = $A;
468
        }
469
        return $returnarray;
470
    }
471
472
    public function listFederationAdmins() {
473
        $returnarray = [];
474
        if (Config::$CONSORTIUM['name'] == "eduroam" && isset(Config::$CONSORTIUM['deployment-voodoo']) && Config::$CONSORTIUM['deployment-voodoo'] == "Operations Team") // SW: APPROVED
475
            $admins = DBConnection::exec("USER", "SELECT eptid as user_id FROM view_admin WHERE role = 'fedadmin' AND realm = '" . strtolower($this->name) . "'");
476
        else
477
            $admins = DBConnection::exec("USER", "SELECT user_id FROM user_options WHERE option_name = 'user:fedadmin' AND option_value = '" . strtoupper($this->name) . "'");
478
479
        while ($a = mysqli_fetch_object($admins))
480
            $returnarray[] = $a->user_id;
481
        return $returnarray;
482
    }
483
484
    public function listExternalEntities($unmapped_only) {
485
        $returnarray = [];
486
        $countrysuffix = "";
0 ignored issues
show
Unused Code introduced by
$countrysuffix is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
487
        
488
        if ($this->name != "")
489
            $countrysuffix = " WHERE country = '" . strtolower($this->name) . "'";
490
        else
491
            $countrysuffix = "";
492
        
493
        if (Config::$CONSORTIUM['name'] == "eduroam" && isset(Config::$CONSORTIUM['deployment-voodoo']) && Config::$CONSORTIUM['deployment-voodoo'] == "Operations Team") { // SW: APPROVED
494
            $usedarray = [];
495
            $externals = DBConnection::exec("EXTERNAL", "SELECT id_institution AS id, country, inst_realm as realmlist, name AS collapsed_name, contact AS collapsed_contact 
496
                                                                                FROM view_active_idp_institution $countrysuffix");
497
            $already_used = DBConnection::exec($this->databaseType, "SELECT DISTINCT external_db_id FROM institution 
498
                                                                                                     WHERE external_db_id IS NOT NULL 
499
                                                                                                     AND external_db_syncstate = " . EXTERNAL_DB_SYNCSTATE_SYNCED);
500
            $pending_invite = DBConnection::exec($this->databaseType, "SELECT DISTINCT external_db_uniquehandle FROM invitations 
501
                                                                                                      WHERE external_db_uniquehandle IS NOT NULL 
502
                                                                                                      AND invite_created >= TIMESTAMPADD(DAY, -1, NOW()) 
503
                                                                                                      AND used = 0");
504
            while ($a = mysqli_fetch_object($already_used))
505
                $usedarray[] = $a->external_db_id;
506
            while ($a = mysqli_fetch_object($pending_invite))
507
                if (!in_array($a->external_db_uniquehandle, $usedarray))
508
                    $usedarray[] = $a->external_db_uniquehandle;
509
            while ($a = mysqli_fetch_object($externals)) {
510
                if ($unmapped_only === TRUE) {
511
                    if (in_array($a->id, $usedarray))
512
                        continue;
513
                }
514
                $names = explode('#', $a->collapsed_name);
515
                // trim name list to current best language match
516
                $available_languages = [];
517
                foreach ($names as $name) {
518
                    $thislang = explode(': ', $name, 2);
519
                    $available_languages[$thislang[0]] = $thislang[1];
520
                }
521
                if (array_key_exists(CAT::get_lang(), $available_languages)) {
522
                    $thelangauge = $available_languages[CAT::get_lang()];
523
                } else if (array_key_exists("en", $available_languages)) {
524
                    $thelangauge = $available_languages["en"];
525
                } else { // whatever. Pick one out of the list
526
                    $thelangauge = array_pop($available_languages);
527
                }
528
                $contacts = explode('#', $a->collapsed_contact);
529
530
531
                $mailnames = "";
532
                foreach ($contacts as $contact) {
533
                    $matches = [];
534
                    preg_match("/^n: (.*), e: (.*), p: .*$/", $contact, $matches);
535
                    if ($matches[2] != "") {
536
                        if ($mailnames != "")
537
                            $mailnames .= ", ";
538
                        // extracting real names is nice, but the <> notation
539
                        // really gets screwed up on POSTs and HTML safety
540
                        // so better not do this; use only mail addresses
541
                        // keeping the old codeline in case we revive this
542
                        // $mailnames .= '"'.$matches[1].'" <'.$matches[2].'>';
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
543
                        $mailnames .= $matches[2];
544
                    }
545
                }
546
                $returnarray[] = ["ID" => $a->id, "name" => $thelangauge, "contactlist" => $mailnames, "country" => $a->country, "realmlist" => $a->realmlist];
547
            }
548
        }
549
550
        return $returnarray;
551
    }
552
553
    public static function getExternalDBEntityDetails($external_id, $realm = NULL) {
554
        $list = [];
555
        if (Config::$CONSORTIUM['name'] == "eduroam" && isset(Config::$CONSORTIUM['deployment-voodoo']) && Config::$CONSORTIUM['deployment-voodoo'] == "Operations Team") { // SW: APPROVED
556
            if ($realm !== NULL)
557
                $scanforrealm = "OR inst_realm LIKE '%$realm%'";
558
            else
559
                $scanforrealm = "";
560
            $info_list = DBConnection::exec("EXTERNAL", "SELECT name AS collapsed_name, inst_realm as realmlist, contact AS collapsed_contact, country FROM view_active_idp_institution WHERE id_institution = $external_id $scanforrealm");
561
            // split names and contacts into proper pairs
562
            while ($a = mysqli_fetch_object($info_list)) {
563
                $names = explode('#', $a->collapsed_name);
564
                foreach ($names as $name) {
565
                    $perlang = explode(': ', $name, 2);
566
                    $list['names'][$perlang[0]] = $perlang[1];
567
                }
568
                $contacts = explode('#', $a->collapsed_contact);
569
                foreach ($contacts as $contact) {
570
                    $email_1 = explode('e: ', $contact);
571
                    $email_2 = explode(',', $email_1[1]);
572
                    $list['admins'][] = ["email" => $email_2[0]];
573
                }
574
                $list['country'] = $a->country;
575
                $list['realmlist'] = $a->realmlist;
576
            }
577
        }
578
        return $list;
579
    }
580
581
    /**
582
     * Lists all identity providers in the database
583
     * adding information required by DiscoJuice.
584
     * @param int $active_only if and set to non-zero will
585
     * cause listing of only those institutions which have some valid profiles defined.
586
     *
587
     */
588
    public static function listAllIdentityProviders($active_only = 0, $country = 0) {
589
        DBConnection::exec($this->databaseType, "SET SESSION group_concat_max_len=10000");
0 ignored issues
show
Bug introduced by
The variable $this does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
590
        $query = "SELECT distinct institution.inst_id AS inst_id, institution.country AS country,
591
                     group_concat(concat_ws('===',institution_option.option_name,LEFT(institution_option.option_value,200)) separator '---') AS options
592
                     FROM institution ";
593
        if ($active_only == 1)
594
            $query .= "JOIN profile ON institution.inst_id = profile.inst_id ";
595
        $query .= "JOIN institution_option ON institution.inst_id = institution_option.institution_id ";
596
        $query .= "WHERE (institution_option.option_name = 'general:instname' 
597
                          OR institution_option.option_name = 'general:geo_coordinates'
598
                          OR institution_option.option_name = 'general:logo_file') ";
599
        if ($active_only == 1)
600
            $query .= "AND profile.showtime = 1 ";
601
602
        if ($country) {
603
            // escape the parameter
604
            $country = DBConnection::escape_value($this->databaseType, $country);
605
            $query .= "AND institution.country = '$country' ";
606
        }
607
        $query .= "GROUP BY institution.inst_id ORDER BY inst_id";
608
        $allIDPs = DBConnection::exec($this->databaseType, $query);
609
        $returnarray = [];
610
        while ($a = mysqli_fetch_object($allIDPs)) {
611
            $O = explode('---', $a->options);
612
            $A = [];
613
            if (isset($geo))
614
                unset($geo);
615
            if (isset($names))
616
                $names = [];
617
            $A['entityID'] = $a->inst_id;
618
            $A['country'] = strtoupper($a->country);
619
            foreach ($O as $o) {
620
                $opt = explode('===', $o);
621
                if ($opt[0] == 'general:logo_file')
622
                    $A['icon'] = $a->inst_id;
623
                if ($opt[0] == 'general:geo_coordinates') {
624
                    $at1 = unserialize($opt[1]);
625
                    if (!isset($geo))
626
                        $geo = [];
627
                    $geo[] = $at1;
628
                }
629
                if ($opt[0] == 'general:instname') {
630
                    if (!isset($names))
631
                        $names = [];
632
                    $names[] = ['value' => $opt[1]];
633
                }
634
            }
635
            
636
            $name = _("Unnamed Entity");
637
            if (count($names) != 0) {
638
                $name = getLocalisedValue($names, CAT::get_lang());
0 ignored issues
show
Bug introduced by
The variable $names does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
It seems like $names can also be of type null; however, getLocalisedValue() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
639
            }
640
            $A['title'] = $name;
641
            if (isset($geo))
642
                $A['geo'] = $geo;
643
            $returnarray[] = $A;
644
        }
645
        return $returnarray;
646
    }
647
    }