Completed
Push — master ( af3ce8...b4d558 )
by Stefan
12:25
created

Profile::getCollapsedAttributes()   C

Complexity

Conditions 18
Paths 80

Size

Total Lines 54
Code Lines 37

Duplication

Lines 10
Ratio 18.52 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 18
eloc 37
c 1
b 1
f 0
nc 80
nop 1
dl 10
loc 54
rs 6.6386

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 Profile 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('Helper.php');
23
require_once('IdP.php');
24
require_once('EAP.php');
25
require_once('X509.php');
26
require_once('EntityWithDBProperties.php');
27
require_once('devices/devices.php');
28
29
define("HIDDEN", -1);
30
define("AVAILABLE", 0);
31
define("UNAVAILABLE", 1);
32
define("INCOMPLETE", 2);
33
define("NOTCONFIGURED", 3);
34
35
/**
36
 * This class represents an EAP Profile.
37
 * Profiles can inherit attributes from their IdP, if the IdP has some. Otherwise,
38
 * one can set attribute in the Profile directly. If there is a conflict between
39
 * IdP-wide and Profile-wide attributes, the more specific ones (i.e. Profile) win.
40
 *
41
 * @author Stefan Winter <[email protected]>
42
 * @author Tomasz Wolniewicz <[email protected]>
43
 *
44
 * @license see LICENSE file in root directory
45
 *
46
 * @package Developer
47
 */
48
class Profile extends EntityWithDBProperties {
49
50
    /**
51
     * This array holds the supported EAP types (in "array" OUTER/INNER representation). They are not synced against the DB after instantiation.
52
     * 
53
     * @var array
54
     */
55
    private $priv_eaptypes;
56
57
    /**
58
     * Class constructor for existing profiles (use IdP::newProfile() to actually create one). Retrieves all attributes and 
59
     * supported EAP types from the DB and stores them in the priv_ arrays.
60
     * 
61
     * @param int $p_id identifier of the profile in the DB
62
     * @param IdP $idp_object optionally, the institution to which this Profile belongs. Saves the construction of the IdP instance. If omitted, an extra query and instantiation is executed to find out.
63
     */
64
    public function __construct($p_id, $idp_object = 0) {
65
        debug(3, "--- BEGIN Constructing new Profile object ... ---\n");
66
67
        $this->databaseType = "INST";
68
        $this->entityOptionTable = "profile_option";
69
        $this->entityIdColumn = "profile_id";
70
        $this->identifier = $p_id;
71
        $this->attributes = [];
72
73
        $profile = DBConnection::exec($this->databaseType, "SELECT inst_id, realm, use_anon_outer, checkuser_outer, checkuser_value, verify_userinput_suffix as verify, hint_userinput_suffix as hint FROM profile WHERE profile_id = $p_id");
74
        debug(4, $profile);
75
        if (!$profile || $profile->num_rows == 0) {
76
            debug(2, "Profile $p_id not found in database!\n");
77
            throw new Exception("Profile $p_id not found in database!");
78
        }
79
        $profileQuery = mysqli_fetch_object($profile);
80
        if (!($idp_object instanceof IdP)) {
81
            $this->institution = $profileQuery->inst_id;
82
            $idp = new IdP($this->institution);
83
        } else {
84
            $idp = $idp_object;
85
            $this->institution = $idp->name;
86
        }
87
        $temparray = [];
88
        $optioninstance = Options::instance();
89
90
        $this->realm = $profileQuery->realm;
91
        $this->use_anon_outer = $profileQuery->use_anon_outer;
92
        $this->langIndex = CAT::get_lang();
93
        $this->inst_name = $idp->name;
94
95
        $this->checkuser_outer = $profileQuery->checkuser_outer;
0 ignored issues
show
Bug introduced by
The property checkuser_outer does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
96
        $this->checkuser_value = $profileQuery->checkuser_value;
0 ignored issues
show
Bug introduced by
The property checkuser_value does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
97
        $this->verify = $profileQuery->verify;
0 ignored issues
show
Bug introduced by
The property verify does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
98
        $this->hint = $profileQuery->hint;
0 ignored issues
show
Bug introduced by
The property hint does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
99
100
        // fetch all atributes from this profile from DB
101
102
        $AllAttributes = DBConnection::exec($this->databaseType, "SELECT option_name, option_value, device_id, eap_method_id as method, row 
103
                FROM $this->entityOptionTable
104
                WHERE $this->entityIdColumn = $this->identifier");
105
106
        while ($attributeQuery = mysqli_fetch_object($AllAttributes)) {
107
108
            $optinfo = $optioninstance->optionType($attributeQuery->option_name);
109
            if ($optinfo['type'] != "file") {
110
                $temparray[] = [
111
                    "name" => $attributeQuery->option_name,
112
                    "value" => $attributeQuery->option_value,
113
                    "level" => ($attributeQuery->device_id == NULL && $attributeQuery->method == 0 ? "Profile" : "Method" ),
114
                    "row" => $attributeQuery->row,
115
                    "device" => $attributeQuery->device_id,
116
                    "flag" => $optinfo['flag'],
117
                    "eapmethod" => EAP::EAPMethodArrayFromId($attributeQuery->method)];
118
            } else {
119
                $decodedAttribute = $this->decodeFileAttribute($attributeQuery->option_value);
120
121
                $temparray[] = [
122
                    "name" => $attributeQuery->option_name,
123
                    "value" => ( $decodedAttribute['lang'] == "" ? $decodedAttribute['content'] : serialize($decodedAttribute)),
124
                    "level" => ($attributeQuery->device_id == NULL && $attributeQuery->method == 0 ? "Profile" : "Method" ),
125
                    "row" => $attributeQuery->row,
126
                    "flag" => $optinfo['flag'],
127
                    "device" => $attributeQuery->device_id,
128
                    "eapmethod" => EAP::EAPMethodArrayFromId($attributeQuery->method)];
129
            }
130
        }
131
        // add internal attributes
132
133
        $temparray[] = ["name" => "internal:profile_count",
134
            "value" => $idp->profileCount(),
135
            "level" => "Profile",
136
            "row" => 0,
137
            "flag" => NULL,
138
            "device" => NULL,
139
            "eapmethod" => NULL];
140
141
        $temparray[] = ["name" => "internal:checkuser_outer",
142
            "value" => $this->checkuser_outer,
143
            "level" => "Profile",
144
            "row" => 0,
145
            "flag" => NULL,
146
            "device" => NULL,
147
            "eapmethod" => NULL];
148
149
        $temparray[] = ["name" => "internal:checkuser_value",
150
            "value" => $this->checkuser_value,
151
            "level" => "Profile",
152
            "row" => 0,
153
            "flag" => NULL,
154
            "device" => NULL,
155
            "eapmethod" => NULL];
156
157
        $temparray[] = ["name" => "internal:verify_userinput_suffix",
158
            "value" => $this->verify,
159
            "level" => "Profile",
160
            "row" => 0,
161
            "flag" => NULL,
162
            "device" => NULL,
163
            "eapmethod" => NULL];
164
165
        $temparray[] = ["name" => "internal:hint_userinput_suffix",
166
            "value" => $this->hint,
167
            "level" => "Profile",
168
            "row" => 0,
169
            "flag" => NULL,
170
            "device" => NULL,
171
            "eapmethod" => NULL];
172
173
        // strip local@ off of the realm value
174
        $strippedrealm = preg_replace('/^.*@/', '', $this->realm);
175
        $temparray[] = ["name" => "internal:realm",
176
            "value" => $strippedrealm,
177
            "level" => "Profile",
178
            "row" => 0,
179
            "flag" => NULL,
180
            "device" => NULL,
181
            "eapmethod" => NULL];
182
        // FALSE or TRUE
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% 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...
183
        $temparray[] = ["name" => "internal:use_anon_outer",
184
            "value" => $this->use_anon_outer,
185
            "level" => "Profile",
186
            "row" => 0,
187
            "flag" => NULL,
188
            "device" => NULL,
189
            "eapmethod" => NULL];
190
        // the local part, if set (otherwise use default value)
191
        if (preg_match('/@/', $this->realm)) {
192
            $temparray[] = ["name" => "internal:anon_local_value",
193
                "value" => substr($this->realm, 0, strpos($this->realm, '@')),
194
                "level" => "Profile",
195
                "row" => 0,
196
                "flag" => NULL,
197
                "device" => NULL,
198
                "eapmethod" => NULL];
199
        } else {
200
            $temparray[] = ["name" => "internal:anon_local_value",
201
                "value" => "anonymous",
202
                "level" => "Profile",
203
                "row" => 0,
204
                "flag" => NULL,
205
                "device" => NULL,
206
                "eapmethod" => NULL];
207
        }
208
209
        // now, fetch IdP-wide attributes
210
211
        $idpoptions = $idp->getAttributes();
212
213
        foreach ($idpoptions as $the_attr) {
214
            $temparray[] = [
215
                "name" => $the_attr["name"],
216
                "value" => $the_attr["value"],
217
                "level" => $the_attr["level"],
218
                "row" => $the_attr["row"],
219
                "flag" => $the_attr["flag"],
220
                "device" => NULL,
221
                "eapmethod" => NULL,
222
            ];
223
        }
224
225
        // check sanity (device and eapmethod are mutually exclusive) and first batch of adding (method level)
226
227
        foreach ($temparray as $attrib) {
228
            if ($attrib["device"] != NULL && $attrib["eapmethod"] != NULL) {
229
                debug(2, "Sanity check failed - device and eapmethod are set!\n");
230
            }
231
        }
232
233
        foreach ($temparray as $attrib) {
234
            if ($attrib["device"] != NULL || $attrib["eapmethod"] != NULL) {
235
                $this->attributes[] = $attrib;
236
            }
237
        }
238
        // pick all attributes which are profile specific and place into final array if no eap/device-specific exists
239
240 View Code Duplication
        foreach ($temparray as $attrib) {
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...
241
            if ($attrib["level"] == "Profile") {
242
                $ignore = "";
243
                foreach ($this->attributes as $approved_attrib) {
244
                    if ($attrib["name"] == $approved_attrib["name"] && $approved_attrib["level"] != "IdP" && $approved_attrib["level"] != "Profile") {
245
                        $ignore = "YES";
246
                    }
247
                }
248
                if ($ignore != "YES") {
249
                    $this->attributes[] = $attrib;
250
                }
251
            }
252
        }
253
254
        // now, add IdP-wide attribs
255
256 View Code Duplication
        foreach ($temparray as $attrib) {
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...
257
            if ($attrib["level"] == "IdP") {
258
                $ignore = "";
259
                foreach ($this->attributes as $approved_attrib) {
260
                    if ($attrib["name"] == $approved_attrib["name"] && $approved_attrib["level"] != "IdP") {
261
                        $ignore = "YES";
262
                    }
263
                }
264
                if ($ignore != "YES") {
265
                    $this->attributes[] = $attrib;
266
                }
267
            }
268
        }
269
270
        $this->name = getLocalisedValue($this->getAttributes('profile:name', 0, 0), $this->langIndex);
271
272
        $eap_m = DBConnection::exec($this->databaseType, "SELECT eap_method_id 
273
                                                        FROM supported_eap supp 
274
                                                        WHERE supp.profile_id = $this->identifier 
275
                                                        ORDER by preference");
276
        $returnarray = [];
277
        while ($eapQuery = (mysqli_fetch_object($eap_m))) {
278
            $eaptype = EAP::EAPMethodArrayFromId($eapQuery->eap_method_id);
279
            $returnarray[] = $eaptype;
280
        }
281
        debug(4, "Looks like this profile supports the following EAP types: ");
282
        debug(4, $returnarray);
283
        $this->priv_eaptypes = $returnarray;
284
285
        debug(3, "--- END Constructing new Profile object ... ---\n");
286
    }
287
288
    /**
289
     * find a profile, given its realm
290
     */
291
    public static function profileFromRealm($realm) {
292
        $exec_query = DBConnection::exec($this->databaseType, "SELECT profile_id FROM profile WHERE realm LIKE '%@$realm'");
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...
293
        if ($profileIdQuery = mysqli_fetch_object($exec_query)) {
294
            return $profileIdQuery->profile_id;
295
        }
296
        return FALSE;
297
    }
298
299
    /**
300
     * update the last_changed timestamp for this profile
301
     */
302
    public function updateFreshness() {
303
        DBConnection::exec($this->databaseType, "UPDATE profile SET last_change = CURRENT_TIMESTAMP WHERE profile_id = $this->identifier");
304
    }
305
306
    /**
307
     * gets the last-modified timestamp (useful for caching "dirty" check)
308
     */
309
    public function getFreshness() {
310
        $exec_update = DBConnection::exec($this->databaseType, "SELECT last_change FROM profile WHERE profile_id = $this->identifier");
311
        if ($freshnessQuery = mysqli_fetch_object($exec_update)) {
312
            return $freshnessQuery->last_change;
313
        }
314
    }
315
316
    /**
317
     * tests if the configurator needs to be regenerated
318
     * returns the configurator path or NULL if regeneration is required
319
     */
320
321
    /**
322
     * This function tests if the configurator needs to be regenerated (properties of the Profile may have changed since the last configurator generation).
323
     * 
324
     * @param string $device device ID to check
325
     * @return mixed a string with the path to the configurator download, or NULL if it needs to be regenerated
326
     */
327
    public function testCache($device) {
328
        $returnValue = NULL;
329
        $escapedDevice = DBConnection::escape_value($this->databaseType, $device);
330
        $result = DBConnection::exec($this->databaseType, "SELECT download_path, mime, UNIX_TIMESTAMP(installer_time) AS tm FROM downloads WHERE profile_id = $this->identifier AND device_id = '$escapedDevice' AND lang = '$this->langIndex'");
331
        if ($result && $cache = mysqli_fetch_object($result)) {
332
            $exec_update = DBConnection::exec($this->databaseType, "SELECT UNIX_TIMESTAMP(last_change) AS last_change FROM profile WHERE profile_id = $this->identifier");
333
            if ($lastChange = mysqli_fetch_object($exec_update)->last_change) {
334
                if ($lastChange < $cache->tm) {
335
                    debug(4, "Installer cached:$cache->download_path\n");
336
                    $returnValue = ['cache' => $cache->download_path, 'mime' => $cache->mime];
337
                }
338
            }
339
        }
340
        return $returnValue;
341
    }
342
343
    /**
344
     * Updates database with new installler location
345
     * 
346
     * @param string device the device identifier string
347
     * @param string path the path where the new installer can be found
348
     */
349
    public function updateCache($device, $path, $mime) {
350
        $escapedDevice = DBConnection::escape_value($this->databaseType, $device);
351
        $escapedPath = DBConnection::escape_value($this->databaseType, $path);
352
        DBConnection::exec($this->databaseType, "INSERT INTO downloads (profile_id,device_id,download_path,mime,lang,installer_time) 
353
                                        VALUES ($this->identifier, '$escapedDevice', '$escapedPath', '$mime', '$this->langIndex', CURRENT_TIMESTAMP ) 
354
                                        ON DUPLICATE KEY UPDATE download_path = '$escapedPath', mime = '$mime', installer_time = CURRENT_TIMESTAMP");
355
    }
356
357
    /**
358
     * Log a new download for our stats
359
     * 
360
     * @param device the device id string
361
     * @param area either admin or user
362
     * @return TRUE if incrementing worked, FALSE if not
363
     */
364
    public function incrementDownloadStats($device, $area) {
365
        $escapedDevice = DBConnection::escape_value($this->databaseType, $device);
366
        if ($area == "admin" || $area == "user") {
367
            DBConnection::exec($this->databaseType, "INSERT INTO downloads (profile_id, device_id, lang, downloads_$area) VALUES ($this->identifier, '$escapedDevice','$this->langIndex', 1) ON DUPLICATE KEY UPDATE downloads_$area = downloads_$area + 1");
368
            return TRUE;
369
        }
370
        return FALSE;
371
    }
372
373
    /**
374
     * Retrieve current download stats from database, either for one specific device or for all devices
375
     * @param string $device the device id string
376
     * @return mixed user downloads of this profile; if device is given, returns the counter as int, otherwise an array with devicename => counter
377
     */
378
    public function getUserDownloadStats($device = 0) {
379
        $returnarray = [];
380
        $numbers_q = DBConnection::exec($this->databaseType, "SELECT device_id, SUM(downloads_user) AS downloads_user FROM downloads WHERE profile_id = $this->identifier GROUP BY device_id");
381
        while ($a = mysqli_fetch_object($numbers_q)) {
382
            $returnarray[$a->device_id] = $a->downloads_user;
383
        }
384
        if ($device !== 0) {
385
            if (isset($returnarray[$device])) {
386
                return $returnarray[$device];
387
            }
388
            return 0;
389
        }
390
        // we should pretty-print the device names
391
        $finalarray = [];
392
        $devlist = Devices::listDevices();
393
        foreach ($returnarray as $devId => $count) {
394
            if (isset($devlist[$devId])) {
395
                $finalarray[$devlist[$devId]['display']] = $count;
396
            }
397
        }
398
        return $finalarray;
399
    }
400
401
    /**
402
     * adds an attribute to this profile; not the usual function from EntityWithDBProperties
403
     * because this class also has per-EAP-type and per-device sub-settings
404
     *
405
     * @param string $attrName name of the attribute to set
406
     * @param string $attrValue value of the attribute to set
407
     * @param int $eapType identifier of the EAP type in the database. 0 if the attribute is valid for all EAP types.
408
     * @param string $device identifier of the device in the databse. Omit the argument if attribute is valid for all devices.
409
     */
410
    public function addAttribute($attrName, $attrValue, $eapType, $device = 0) {
411
        $escapedAttrName = DBConnection::escape_value($this->databaseType, $attrName);
412
        $escapedAttrValue = DBConnection::escape_value($this->databaseType, $attrValue);
413
414
        DBConnection::exec($this->databaseType, "INSERT INTO $this->entityOptionTable ($this->entityIdColumn, option_name, option_value, eap_method_id" . ($device !== 0 ? ",device_id" : "") . ") 
415
                          VALUES(" . $this->identifier . ", '$escapedAttrName', '$escapedAttrValue', $eapType" . ($device !== 0 ? ",'" . DBConnection::escape_value($this->databaseType, $device) . "'" : "" ) . ")");
416
        $this->updateFreshness();
417
    }
418
419
    /**
420
     * register new supported EAP method for this profile
421
     *
422
     * @param array $type The EAP Type, as defined in class EAP
423
     * @param int $preference preference of this EAP Type. If a preference value is re-used, the order of EAP types of the same preference level is undefined.
424
     *
425
     */
426
    public function addSupportedEapMethod($type, $preference) {
427
        DBConnection::exec($this->databaseType, "INSERT INTO supported_eap (profile_id, eap_method_id, preference) VALUES ("
428
                . $this->identifier . ", "
429
                . EAP::EAPMethodIdFromArray($type) . ", "
430
                . $preference . ")");
431
        $this->updateFreshness();
432
    }
433
434
    /**
435
     * Deletes the profile from database and uninstantiates itself.
436
     *
437
     */
438
    public function destroy() {
439
        DBConnection::exec($this->databaseType, "DELETE FROM profile_option WHERE profile_id = $this->identifier");
440
        DBConnection::exec($this->databaseType, "DELETE FROM supported_eap WHERE profile_id = $this->identifier");
441
        DBConnection::exec($this->databaseType, "DELETE FROM profile WHERE profile_id = $this->identifier");
442
        unset($this);
443
    }
444
445
    /**
446
     * Removes all supported EAP methods
447
     */
448
    public function flushSupportedEapMethods() {
449
        DBConnection::exec($this->databaseType, "DELETE FROM supported_eap WHERE profile_id = $this->identifier");
450
        $this->updateFreshness();
451
    }
452
453
    /** Toggle anonymous outer ID support.
454
     *
455
     * @param boolean $shallwe TRUE to enable outer identities (needs valid $realm), FALSE to disable
456
     *
457
     */
458
    public function setAnonymousIDSupport($shallwe) {
459
        DBConnection::exec($this->databaseType, "UPDATE profile SET use_anon_outer = " . ($shallwe == true ? "1" : "0") . " WHERE profile_id = $this->identifier");
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
460
    }
461
462
    /** Toggle special username for realm checks
463
     *
464
     * @param boolean $shallwe TRUE to enable outer identities (needs valid $realm), FALSE to disable
465
     * @param string $localpart the username
466
     *
467
     */
468
    public function setRealmCheckUser($shallwe, $localpart = NULL) {
469
        DBConnection::exec($this->databaseType, "UPDATE profile SET checkuser_outer = " . ($shallwe == true ? "1" : "0") .
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
470
                ( $localpart !== NULL ? ", checkuser_value = '$localpart' " : "") .
471
                " WHERE profile_id = $this->identifier");
472
    }
473
474
    /** should username be verified or even prefilled?
475
     * 
476
     */
477
    public function setInputVerificationPreference($verify, $hint) {
478
        DBConnection::exec($this->databaseType, "UPDATE profile SET verify_userinput_suffix = " . ($verify == true ? "1" : "0") .
479
                ", hint_userinput_suffix = " . ($hint == true ? "1" : "0") .
480
                " WHERE profile_id = $this->identifier");
481
    }
482
483
    /**
484
     * Specifies the realm of this profile.
485
     * 
486
     * @param string $realm the realm (potentially with the local@ part that should be used for anonymous identities)
487
     */
488
    public function setRealm($realm) {
489
        $escapedRealm = DBConnection::escape_value($this->databaseType, $realm);
490
        DBConnection::exec($this->databaseType, "UPDATE profile SET realm = '$escapedRealm' WHERE profile_id = $this->identifier");
491
        $this->realm = $escapedRealm;
492
    }
493
494
    /**
495
     * Produces an array of EAP methods supported by this profile, ordered by preference
496
     * 
497
     * @param int $complete_only if set and non-zero limits the output to methods with complete information
498
     * @return array list of EAP methods, (in "array" OUTER/INNER representation)
499
     */
500
    public function getEapMethodsinOrderOfPreference($complete_only = 0) {
501
        $temparray = [];
502
503
        if ($complete_only == 0) {
504
            return $this->priv_eaptypes;
505
        } else {
506
            foreach ($this->priv_eaptypes as $type) {
507
                if ($this->isEapTypeDefinitionComplete($type) === true) {
508
                    $temparray[] = $type;
509
                }
510
            }
511
            return($temparray);
512
        }
513
    }
514
515
    /** Returns an array of the profile's attributes.
516
     * 
517
     * @param string option_name the name of a specific option. If set, only returns option values for this option name
518
     * @param eapmethod the EAP type, in array ("OUTER/INNER") notation. If set, returns only attributes which are specific to that EAP type
519
     * @param string device the device ID string. If set, returns only attributes which are specific to that device
520
     * @return array attributes of the profile
521
     */
522
    public function getAttributes($optionName = 0, $eapmethod = 0, $device = 0) {
523
524
        $outarray = [];
525
        $temparray = [];
526
        if ($eapmethod) {
527
            foreach ($this->attributes as $theAttr) {
528
                if ($theAttr["eapmethod"] == $eapmethod) {
529
                    $temparray[] = $theAttr;
530
                }
531
            }
532
        } else
533
        if ($device) {
534
            foreach ($this->attributes as $theAttr) {
535
                if ($theAttr["device"] == $device) {
536
                    $temparray[] = $theAttr;
537
                }
538
            }
539
        }
540
541
        foreach ($this->attributes as $theAttr) {
542
            if ($theAttr["device"] == NULL && $theAttr["eapmethod"] == NULL) {
543
                $temparray[] = $theAttr;
544
            }
545
        }
546
547
        // return only options by one name, if asked for
548
549
        if ($optionName) {
550
            foreach ($temparray as $theAttr) {
551
                if ($theAttr["name"] == $optionName) {
552
                    $outarray[] = $theAttr;
553
                }
554
            }
555
        } else {
556
            $outarray = $temparray;
557
        }
558
        
559
        return $outarray;
560
    }
561
562
    /**
563
     * Performs a sanity check for a given EAP type - did the admin submit enough information to create installers for him?
564
     * 
565
     * @param array $eaptype the EAP type in "array" OUTER/INNER representation
566
     * @return mixed TRUE if the EAP type is complete; an array of missing attribues if it's incomplete; FALSE if it's incomplete for other reasons
567
     */
568
    public function isEapTypeDefinitionComplete($eaptype) {
569
        $missing = [];
570
        // TLS, TTLS, PEAP outer phase need a CA certficate and a Server Name
571
        if ($eaptype["OUTER"] == PEAP || $eaptype["OUTER"] == TLS || $eaptype["OUTER"] == TTLS || $eaptype["OUTER"] == FAST) {
572
573
            $cnOption = $this->getAttributes("eap:server_name", $eaptype);
0 ignored issues
show
Documentation introduced by
$eaptype is of type array<string,?,{"OUTER":"?"}>, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
574
            $caOption = $this->getAttributes("eap:ca_file", $eaptype);
0 ignored issues
show
Documentation introduced by
$eaptype is of type array<string,?,{"OUTER":"?"}>, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
575
            /* echo "<pre>";
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% 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...
576
              print_r($options);
577
              echo "</pre>"; */
578
            if (count($caOption) > 0 && count($cnOption) > 0) {// see if we have at least one root CA cert
579
                foreach ($caOption as $one_ca) {
580
                    $x509 = new X509();
581
                    $ca_parsed = $x509->processCertificate($one_ca['value']);
582
                    if ($ca_parsed['root'] == 1) {
583
                        return true;
584
                    }
585
                }
586
                $missing[] = "eap:ca_file";
587
            }
588
            if (count($caOption) == 0) {
589
                $missing[] = "eap:ca_file";
590
            }
591
            if (count($cnOption) == 0) {
592
                $missing[] = "eap:server_name";
593
            }
594
            return $missing;
595
        } elseif ($eaptype["OUTER"] == PWD || $eaptype["INNER"] == NE_SILVERBULLET) {
596
            /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% 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...
597
              $cn_option = $this->getAttributes("eap:server_name", $eaptype);
598
              if (count($cn_option) > 0) */
599
            return true;
600
            /* $missing[] = "eap:server_name";
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% 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...
601
              return $missing; */
602
        }
603
604
        // we have no idea; let's say false
605
606
        return false;
607
    }
608
609
    /**
610
     * list all devices marking their availabiblity and possible redirects
611
     *
612
     * @param string $locale for text-based attributes, either returns values for the default value, or if specified here, in the locale specified
613
     * @return array of device ids display names and their status
614
     */
615
    public function listDevices($locale = 0) {
616
        if ($locale == 0) {
617
            $locale = $this->langIndex;
618
        }
619
        $redirectUrl = 0;
0 ignored issues
show
Unused Code introduced by
$redirectUrl 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...
620
        $returnarray = [];
621
        $redirect = $this->getAttributes("device-specific:redirect", 0, 0);
622
        if ($redirect) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $redirect of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
623
            $v = unserialize($redirect[0]['value']);
624
            return [['id' => '0', 'redirect' => $v['content']]];
625
        }
626
        $preferred_eap = $this->getEapMethodsinOrderOfPreference(1);
627
        $eAPOptions = [];
628
        foreach (Devices::listDevices() as $d => $D) {
629
            $factory = new DeviceFactory($d);
630
            $dev = $factory->device;
631
            $redirectUrl = getLocalisedValue($this->getAttributes("device-specific:redirect", 0, $d), $locale);
632
            $devStatus = AVAILABLE;
633
            $message = 0;
634 View Code Duplication
            if (isset($D['options']) && isset($D['options']['message']) && $D['options']['message']) {
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...
635
                $message = $D['options']['message'];
636
            }
637
638
            if ($redirectUrl === 0) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of $redirectUrl (string) and 0 (integer) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
639
                if (isset($D['options']) && isset($D['options']['redirect']) && $D['options']['redirect']) {
640
                    $devStatus = HIDDEN;
641
                } else {
642
                    $eap = $dev->getPreferredEapType($preferred_eap);
643
                    if ($eap) {
644
                        if (isset($eAPOptions["eap-specific:customtext"][serialize($eap)])) {
645
                            $eap_customtext = $eAPOptions["eap-specific:customtext"][serialize($eap)];
646
                        }
647
                        else {
648
                            $eap_customtext = getLocalisedValue($this->getAttributes("eap-specific:customtext", $eap, 0), $locale);
649
                            $eAPOptions["eap-specific:customtext"][serialize($eap)] = $eap_customtext;
650
                        }
651
                        $device_customtext = getLocalisedValue($this->getAttributes("device-specific:customtext", 0, $d), $locale);
652
                    } else {
653
                        $devStatus = UNAVAILABLE;
654
                    }
655
                }
656
            }
657
            $returnarray[] = ['id' => $d, 'display' => $D['display'], 'status' => $devStatus, 'redirect' => $redirectUrl, 'eap_customtext' => $eap_customtext, 'device_customtext' => $device_customtext, 'message' => $message, 'options' => $D['options']];
0 ignored issues
show
Bug introduced by
The variable $eap_customtext 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
The variable $device_customtext 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...
658
        }
659
        return $returnarray;
660
    }
661
662
    /**
663
     * prepare profile attributes for device modules
664
     * Gets profile attributes taking into account the most specific level on which they may be defined
665
     * as wel as the chosen language.
666
     * can be called with an optional $eap argument
667
     * 
668
     * @param array $eap if specified, retrieves attributes specific to the given EAP type
669
     * @return array list of attributes in collapsed style (index is the attrib name, value is an array of different values)
670
     */
671
    public function getCollapsedAttributes($eap = 0) {
672
        $attr = $this->getAttributes(0, $eap);
673
        $temp1 = [];
674
        foreach ($attr as $b) {
675
            $name = $b['name'];
676
            $temp1[] = $name;
677
            $level = $b['level'];
678
//            $S[$l] = $z[$l];
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% 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...
679
            $value = $b['value'];
680
            if (!isset($temp[$name][$level])) {
681
                $temp[$name][$level] = [];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$temp was never initialized. Although not strictly required by PHP, it is generally a good practice to add $temp = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
682
            }
683
            if ($b['flag'] == 'ML') {
684
                $v = unserialize($value);
685
                $value = [$v['lang'] => $v['content']];
686
            }
687
            $temp[$name][$level][] = $value;
0 ignored issues
show
Bug introduced by
The variable $temp 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...
688
            $flags[$name] = $b['flag'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$flags was never initialized. Although not strictly required by PHP, it is generally a good practice to add $flags = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
689
        }
690
        foreach ($temp1 as $name) {
691
            if ($flags[$name] == 'ML') {
0 ignored issues
show
Bug introduced by
The variable $flags 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...
692
                $S = [];
693 View Code Duplication
                if (isset($temp[$name]['Profile'])) {
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...
694
                    foreach ($temp[$name]['Profile'] as $z) {
695
                        foreach ($z as $l => $w) {
696
                            $S[$l] = $w;
697
                        }
698
                    }
699
                }
700 View Code Duplication
                if (!$S && isset($temp[$name]['IdP'])) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $S of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
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...
701
                    foreach ($temp[$name]['IdP'] as $z) {
702
                        foreach ($z as $l => $w) {
703
                            $S[$l] = $w;
704
                        }
705
                    }
706
                }
707
                $out[$name]['langs'] = $S;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$out was never initialized. Although not strictly required by PHP, it is generally a good practice to add $out = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
708
                if (isset($S[$this->langIndex]) || isset($S['C'])) {
709
                    $out[$name][0] = (isset($S[$this->langIndex])) ? $S[$this->langIndex] : $S['C'];
0 ignored issues
show
Bug introduced by
The variable $out 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...
710
                }
711
            } else {
712
                if (isset($temp[$name]['Method'])) {
713
                    $out[$name] = $temp[$name]['Method'];
714
                }
715
                elseif (isset($temp[$name]['Profile'])) {
716
                    $out[$name] = $temp[$name]['Profile'];
717
                }
718
                else {
719
                    $out[$name] = $temp[$name]['IdP'];
720
                }
721
            }
722
        }
723
        return($out);
724
    }
725
726
    /**
727
     * 
728
     */
729 View Code Duplication
    public function getSufficientConfig() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
730
        $result = DBConnection::exec($this->databaseType, "SELECT sufficient_config FROM profile WHERE profile_id = " . $this->identifier);
731
        $configQuery = mysqli_fetch_row($result);
732
        if ($configQuery[0] == "0") {
733
            return FALSE;
734
        }
735
        return TRUE;
736
    }
737
738
    /**
739
     * Checks if the profile has enough information to have something to show to end users. This does not necessarily mean
740
     * that there's a fully configured EAP type - it is sufficient if a redirect has been set for at least one device.
741
     * 
742
     * @return boolean TRUE if enough information for showtime is set; FALSE if not
743
     */
744
    public function readyForShowtime() {
745
        $properConfig = FALSE;
746
        $attribs = $this->getCollapsedAttributes();
747
        // do we have enough to go live? Check if any of the configured EAP methods is completely configured ...
748
        if (sizeof($this->getEapMethodsinOrderOfPreference(1)) > 0) {
749
            $properConfig = TRUE;
750
        }
751
        // if not, it could still be that general redirect has been set
752
        if (!$properConfig) {
753
            if (isset($attribs['device-specific:redirect'])) {
754
                $properConfig = TRUE;
755
            }
756
            // TODO: or maybe just a per-device redirect? would be good enough...
757
        }
758
        // do we know at least one SSID to configure, or work with wired? If not, it's not ready...
759
        if (!isset($attribs['media:SSID']) &&
760
                !isset($attribs['media:SSID_with_legacy']) &&
761
                (!isset(Config::$CONSORTIUM['ssid']) || count(Config::$CONSORTIUM['ssid']) == 0) &&
762
                !isset($attribs['media:wired'])) {
763
            $properConfig = FALSE;
764
                }
765
        return $properConfig;
766
    }
767
768
    /**
769
     * set the showtime and QR-user attributes if prepShowTime says that there is enough info *and* the admin flagged the profile for showing
770
     */
771
    public function prepShowtime() {
772
        $properConfig = $this->readyForShowtime();
773
        if ($properConfig) {
774
            DBConnection::exec($this->databaseType, "UPDATE profile SET sufficient_config = TRUE WHERE profile_id = " . $this->identifier);
775
        }
776
        else {
777
            DBConnection::exec($this->databaseType, "UPDATE profile SET sufficient_config = FALSE WHERE profile_id = " . $this->identifier);
778
        }
779
        $attribs = $this->getCollapsedAttributes();
780
        // if not enough info to go live, set FALSE
781
        // even if enough info is there, admin has the ultimate say: 
782
        //   if he doesn't want to go live, no further checks are needed, set FALSE as well
783
        if (!$properConfig || !isset($attribs['profile:production']) || (isset($attribs['profile:production']) && $attribs['profile:production'][0] != "on")) {
784
            DBConnection::exec($this->databaseType, "UPDATE profile SET showtime = FALSE WHERE profile_id = " . $this->identifier);
785
            return;
786
        } else {
787
            DBConnection::exec($this->databaseType, "UPDATE profile SET showtime = TRUE WHERE profile_id = " . $this->identifier);
788
            return;
789
        }
790
    }
791
792
    /**
793
     * Checks if the profile is shown (showable) to end users
794
     * @return boolean TRUE if profile is shown; FALSE if not
795
     */
796 View Code Duplication
    public function getShowtime() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
797
        $result = DBConnection::exec($this->databaseType, "SELECT showtime FROM profile WHERE profile_id = " . $this->identifier);
798
        $r = mysqli_fetch_row($result);
799
        /* echo "<pre>";
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% 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...
800
          print_r($r);
801
          echo "</pre>"; */
802
        if ($r[0] == "0") {
803
            return FALSE;
804
        }
805
        return TRUE;
806
    }
807
808
    /**
809
     * current language
810
     * @var string
811
     */
812
    private $langIndex;
813
814
    /**
815
     * DB identifier of the parent institution of this profile
816
     * @var int
817
     */
818
    public $institution;
819
820
    /**
821
     * name of the parent institution of this profile in the current language
822
     * @var string
823
     */
824
    public $inst_name;
825
826
    /**
827
     * realm of this profile (empty string if unset)
828
     * @var string
829
     */
830
    public $realm;
831
832
    /**
833
     * boolean value: should anonymous outer IDs be used or not?
834
     * @var boolean
835
     */
836
    public $use_anon_outer;
837
838
}
839