Test Setup Failed
Push — master ( 20ee25...592796 )
by Tomasz
08:23
created

IdPlist::setKeywords()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 20
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 14
c 1
b 0
f 0
dl 0
loc 20
rs 9.4888
cc 5
nc 5
nop 1
1
<?php
2
3
/*
4
 * *****************************************************************************
5
 * Contributions to this work were made on behalf of the GÉANT project, a 
6
 * project that has received funding from the European Union’s Framework 
7
 * Programme 7 under Grant Agreements No. 238875 (GN3) and No. 605243 (GN3plus),
8
 * Horizon 2020 research and innovation programme under Grant Agreements No. 
9
 * 691567 (GN4-1) and No. 731122 (GN4-2).
10
 * On behalf of the aforementioned projects, GEANT Association is the sole owner
11
 * of the copyright in all material which was developed by a member of the GÉANT
12
 * project. GÉANT Vereniging (Association) is registered with the Chamber of 
13
 * Commerce in Amsterdam with registration number 40535155 and operates in the 
14
 * UK as a branch of GÉANT Vereniging.
15
 * 
16
 * Registered office: Hoekenrode 3, 1102BR Amsterdam, The Netherlands. 
17
 * UK branch address: City House, 126-130 Hills Road, Cambridge CB2 1PQ, UK
18
 *
19
 * License: see the web/copyright.inc.php file in the file structure or
20
 *          <base_url>/copyright.php after deploying the software
21
 */
22
23
namespace core;
24
25
class IdPlist extends common\Entity
26
{
27
28
    /**
29
     * Order active identity providers according to their distance and name
30
     * @param string $country         the country from which to list IdPs
31
     * @param array  $currentLocation current location
32
     * @return array $IdPs -  list of arrays ('id', 'name');
33
     */
34
    public static function orderIdentityProviders($country, $currentLocation)
35
    {
36
        $idps = self::listAllIdentityProviders(1, $country);
37
        $here = self::setCurrentLocation($currentLocation);
38
        $idpTitle = [];
39
        $resultSet = [];
40
        foreach ($idps as $idp) {
41
            $idpTitle[$idp['entityID']] = $idp['title'];
42
            $d = self::getIdpDistance($idp, $here);
43
            $resultSet[$idp['entityID']] = $d." ".$idp['title'];
44
        }
45
        asort($resultSet);
46
        $outarray = [];
47
        foreach (array_keys($resultSet) as $r) {
48
            $outarray[] = ['idp' => $r, 'title' => $idpTitle[$r]];
49
        }
50
        return($outarray);
51
    }
52
53
    /**
54
     * Lists all identity providers in the database
55
     * adding information required by DiscoJuice.
56
     * 
57
     * @param int    $activeOnly if set to non-zero will cause listing of only those institutions which have some valid profiles defined.
58
     * @param string $country    if set, only list IdPs in a specific country
59
     * @return array the list of identity providers
60
     *
61
     */
62
    public static function listAllIdentityProviders($activeOnly = 0, $country = "")
63
    {
64
        common\Entity::intoThePotatoes();
65
        $handle = DBConnection::handle("INST");
66
        $handle->exec("SET SESSION group_concat_max_len=10000");
67
        $query = IdPlist::setAllIdentyProvidersQuery($activeOnly, $country);
68
        $allIDPs = ($country != "" ? $handle->exec($query, "s", $country) : $handle->exec($query));
69
        $returnarray = [];
70
        while ($queryResult = mysqli_fetch_object(/** @scrutinizer ignore-type */ $allIDPs)) {
71
            $options = IdPlist::setIdentityProviderAttributes($queryResult);
72
            $oneInstitutionResult = [];
73
            $oneInstitutionResult['entityID'] = $queryResult->inst_id;
74
            $oneInstitutionResult['country'] = strtoupper($queryResult->country);
75
            $name = _("Unnamed Entity");
76
            if (count($options['names']) != 0) {
77
                $langObject = new \core\common\Language();
78
                $name = $langObject->getLocalisedValue($options['names']);
79
            }          
80
            $oneInstitutionResult['title'] = $name;
81
            $keywords = IdPlist::setKeywords($options['names']);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $keywords is correct as core\IdPlist::setKeywords($options['names']) targeting core\IdPlist::setKeywords() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
82
            if (!empty($keywords)) {
83
                $oneInstitutionResult['keywords'] = $keywords;
84
            }        
85
            if (count($options['geo']) > 0) {
86
                $oneInstitutionResult['geo'] = $options['geo'];
87
            }            
88
            if ($options['icon'] > 0) {
89
                $oneInstitutionResult['icon'] = $options['icon'];
90
            }
91
            $returnarray[] = $oneInstitutionResult;
92
        }
93
        common\Entity::outOfThePotatoes();
94
        return $returnarray;
95
    }
96
    
97
    /**
98
     * outputs a full list of IdPs containing the fllowing data:
99
     * institution_is, institution name in all available languages,
100
     * list of production profiles.
101
     * For eache profile the profile identifier, profile name in all languages
102
     * and redirect values (empty rediret value means that no redirect has been
103
     * set).
104
     * 
105
     * @return array of identity providers with attributes
106
     */
107
    public static function listIdentityProvidersWithProfiles() {
108
        $handle = DBConnection::handle("INST");
109
        $handle->exec("SET SESSION group_concat_max_len=10000");
110
        $idpQuery = IdPlist::setAllIdentyProvidersQuery(1);
111
        $allIDPs = $handle->exec($idpQuery);
112
        $idpArray = [];
113
        while ($queryResult = mysqli_fetch_object(/** @scrutinizer ignore-type */ $allIDPs)) {
114
            $options = IdPlist::setIdentityProviderAttributes($queryResult);
115
            $oneInstitutionResult = [];
116
            $oneInstitutionResult['country'] = strtoupper($queryResult->country);
117
            $oneInstitutionResult['entityID'] = (int) $queryResult->inst_id; 
118
            $oneInstitutionResult['names'] = $options['names'];
119
            if (count($options['geo']) > 0) {
120
                $geoArray = [];
121
                foreach ($options['geo'] as $coords) {
122
                    $geoArray[] = ['lon' => (float) $coords['lon'],
123
                        'lat' => (float) $coords['lat']];
124
                }
125
                $oneInstitutionResult['geo'] = $geoArray;
126
            }
127
            if ($options['icon'] > 0) {
128
                $oneInstitutionResult['icon'] = $options['icon'];
129
            }
130
            $idpArray[$queryResult->inst_id] = $oneInstitutionResult;
131
        }
132
        
133
        $profileQuery = IdPlist::setAllProfileQuery();
134
        $allProfiles = $handle->exec($profileQuery);
135
        while ($queryResult = mysqli_fetch_object(/** @scrutinizer ignore-type */ $allProfiles)) {
136
            $profileOptions = IdPlist::setProfileAttribtes($queryResult);
137
            $idpId = $queryResult->inst_id;
138
            if (empty($idpArray[$idpId])) {
139
                continue;
140
            }
141
            if (empty($idpArray[$idpId]['profiles'])) {
142
                $idpArray[$idpId]['profiles'] = [];
143
            }
144
            if (!$profileOptions['production']) {
145
                continue;
146
            }
147
            $idpArray[$idpId]['profiles'][] = [
148
                'id'=> (int) $queryResult->profile_id,
149
                'names'=> $profileOptions['profileNames'],
150
                'redirect'=>$profileOptions['redirect']
151
                ];
152
        }       
153
        return $idpArray;
154
    }
155
156
    /**
157
     * sets the current location
158
     * 
159
     * @param array $currentLocation the location to set
160
     * @return array
161
     */
162
    private static function setCurrentLocation($currentLocation)
163
    {
164
        if (is_null($currentLocation)) {
165
            $currentLocation = ['lat' => "90", 'lon' => "0"];
166
            $userLocation = DeviceLocation::locateDevice();
167
            if ($userLocation['status'] == 'ok') {
168
                $currentLocation = $userLocation['geo'];
169
            }
170
        }
171
        return $currentLocation;
172
    }
173
174
    /**
175
     * calculate surface distance from user location to IdP location
176
     * @param array $idp      the IdP in question
177
     * @param array $location user location
178
     * @return string
179
     */
180
    private static function getIdpDistance($idp, $location)
181
    {
182
        $dist = 10000;
183
        if (isset($idp['geo'])) {
184
            $G = $idp['geo'];
185
            if (isset($G['lon'])) {
186
                $d1 = self::geoDistance($location, $G);
187
                if ($d1 < $dist) {
188
                    $dist = $d1;
189
                }
190
            } else {
191
                foreach ($G as $g) {
192
                    $d1 = self::geoDistance($location, $g);
193
                    if ($d1 < $dist) {
194
                        $dist = $d1;
195
                    }
196
                }
197
            }
198
        }
199
        if ($dist > 100) {
200
            $dist = 10000;
201
        }
202
        return(sprintf("%06d", $dist));
203
    }
204
    
205
    /**
206
     * set the IdP query string for listAllIdentityProviders and 
207
     * listIdentityProvidersWithProfiles
208
     * @param int    $activeOnly if set to non-zero will cause listing of only those institutions which have some valid profiles defined.
209
     * @param string $country    if set, only list IdPs in a specific country
210
     * 
211
     * @return string the query
212
     */
213
    private static function setAllIdentyProvidersQuery($activeOnly = 0, $country = "")
214
    {
215
        $query = "SELECT distinct institution.inst_id AS inst_id,
216
            institution.country AS country,
217
            group_concat(concat_ws('===',institution_option.option_name,
218
                LEFT(institution_option.option_value,200),
219
                institution_option.option_lang) separator '---') AS options
220
            FROM institution ";
221
        if ($activeOnly == 1) {
222
            $query .= "JOIN v_active_inst ON institution.inst_id = v_active_inst.inst_id ";
223
        }
224
        $query .= 
225
           "JOIN institution_option ON institution.inst_id = institution_option.institution_id
226
            WHERE (institution_option.option_name = 'general:instname' 
227
                OR institution_option.option_name = 'general:geo_coordinates'
228
                OR institution_option.option_name = 'general:logo_file') ";
229
230
        $query .= ($country != "" ? "AND institution.country = ? " : "");
231
232
        $query .= "GROUP BY institution.inst_id ORDER BY inst_id";
233
        return $query;
234
    }
235
236
    /**
237
     * set the Profile query string for listIdentityProvidersWithProfiles
238
     * 
239
     * @return string query
240
     */
241
    private static function setAllProfileQuery() {
242
        $query = "SELECT profile.inst_id AS inst_id,
243
            profile.profile_id,
244
            group_concat(concat_ws('===',profile_option.option_name, 
245
                LEFT(profile_option.option_value, 200),
246
                profile_option.option_lang) separator '---') AS profile_options
247
            FROM profile
248
            JOIN profile_option ON profile.profile_id = profile_option.profile_id
249
            WHERE profile.sufficient_config = 1
250
                AND profile_option.eap_method_id = 0
251
                AND (profile_option.option_name = 'profile:name'
252
                OR (profile_option.option_name = 'device-specific:redirect'
253
                    AND isnull(profile_option.device_id))
254
                OR profile_option.option_name = 'profile:production')        
255
            GROUP BY profile.profile_id ORDER BY inst_id";
256
        return $query;
257
    }
258
    
259
    /**
260
     * Extract IdP attributes for listAllIdentityProviders and 
261
     * listIdentityProvidersWithProfiles
262
     * @param  $idp object - the row object returned by the IdP search
263
     * @return array the IdP attributes
264
     */
265
    private static function setIdentityProviderAttributes($idp) {
266
        $options = explode('---', $idp->options);
267
        $names = [];
268
        $geo = [];
269
        $icon = 0;
270
        foreach ($options as $option) {
271
            $opt = explode('===', $option);
272
            switch ($opt[0]) {
273
                case 'general:logo_file':
274
                    $icon = $idp->inst_id;
275
                    break;
276
                case 'general:geo_coordinates':
277
                    $at1 = json_decode($opt[1], true);
278
                    $geo[] = $at1;
279
                    break;
280
                case 'general:instname':
281
                    $names[] = [
282
                        'lang' => $opt[2],
283
                        'value' => $opt[1]
284
                    ];
285
                    break;
286
                default:
287
                    break;
288
            }
289
        }
290
        return ['names' => $names, 'geo' => $geo, 'icon' => $icon];
291
        
292
    }
293
    
294
    /**
295
     * Extract Profie attributes for listIdentityProvidersWithProfiles
296
     * 
297
     * @param object $profile - the row object returned by the profile search
298
     * @return array the profile attributes
299
     */
300
    private static function setProfileAttribtes($profile)
301
    {
302
        $profileOptions = explode('---', $profile->profile_options);
303
        $productionProfile = false;
304
        $profileNames = [];
305
        $redirect = '';
306
307
        foreach ($profileOptions as $profileOption) {
308
            $opt = explode('===', $profileOption);
309
            switch ($opt[0]) {
310
                case 'profile:production':
311
                    if ($opt[1] = 'on') {
312
                        $productionProfile = true;
313
                    }
314
                    break;
315
                case 'device-specific:redirect':
316
                        $redirect = $opt[1].':'.$profile->device_id;
317
                    break;
318
                case 'profile:name': 
319
                    $profileNames[] = [
320
                        'lang' => $opt[2],
321
                        'value' => $opt[1]
322
                    ];
323
                    break;
324
                default:
325
                    break; 
326
            }
327
        }
328
        return ['production' => $productionProfile,
329
            'profileNames' => $profileNames,
330
            'redirect' => $redirect];
331
    }
332
    
333
    private static function setKeywords($names)
334
    {
335
        if (!\config\ConfAssistant::USE_KEYWORDS) {
0 ignored issues
show
Bug introduced by
The constant config\ConfAssistant::USE_KEYWORDS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
336
            return null;
337
        }
338
        $keywords = [];
339
        foreach ($names as $keyword) {
340
            $value = $keyword['value'];
341
            $keywords[$keyword['lang']] = $keyword['value'];
342
            $keywords[$keyword['lang'].'_7'] =
343
                    iconv('UTF-8', 'ASCII//TRANSLIT', $value);
344
        }
345
        $keywords_final = array_unique($keywords);
346
        if (!empty($keywords_final)) {
347
            $returnArray = [];
348
            foreach (array_keys($keywords_final) as $key) {
349
            $returnArray[] = [$keywords_final[$key]];
350
            }
351
        }
352
        return $returnArray;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $returnArray does not seem to be defined for all execution paths leading up to this point.
Loading history...
353
    }
354
355
    /**
356
     * Calculate the distance in km between two points given their
357
     * geo coordinates.
358
     * @param array $point1   first point as an 'lat', 'lon' array 
359
     * @param array $profile1 second point as an 'lat', 'lon' array 
360
     * @return float distance in km
361
     */
362
    public static function geoDistance($point1, $profile1)
363
    {
364
365
        $distIntermediate = sin(deg2rad($point1['lat'])) * sin(deg2rad($profile1['lat'])) +
366
                cos(deg2rad($point1['lat'])) * cos(deg2rad($profile1['lat'])) * cos(deg2rad($point1['lon'] - $profile1['lon']));
367
        $dist = rad2deg(acos($distIntermediate)) * 60 * 1.1852;
368
        return(round($dist));
369
    }
370
}