displayRadiusPropertyWidget()   F
last analyzed

Complexity

Conditions 31
Paths > 20000

Size

Total Lines 189
Code Lines 153

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 153
c 2
b 0
f 0
dl 0
loc 189
rs 0
cc 31
nc 622080
nop 4

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
 * Contributions to this work were made on behalf of the GÉANT project, a 
5
 * project that has received funding from the European Union’s Framework 
6
 * Programme 7 under Grant Agreements No. 238875 (GN3) and No. 605243 (GN3plus),
7
 * Horizon 2020 research and innovation programme under Grant Agreements No. 
8
 * 691567 (GN4-1) and No. 731122 (GN4-2).
9
 * On behalf of the aforementioned projects, GEANT Association is the sole owner
10
 * of the copyright in all material which was developed by a member of the GÉANT
11
 * project. GÉANT Vereniging (Association) is registered with the Chamber of 
12
 * Commerce in Amsterdam with registration number 40535155 and operates in the 
13
 * UK as a branch of GÉANT Vereniging.
14
 * 
15
 * Registered office: Hoekenrode 3, 1102BR Amsterdam, The Netherlands. 
16
 * UK branch address: City House, 126-130 Hills Road, Cambridge CB2 1PQ, UK
17
 *
18
 * License: see the web/copyright.inc.php file in the file structure or
19
 *          <base_url>/copyright.php after deploying the software
20
 */
21
22
/**
23
 * This page displays the dashboard overview of an entire IdP.
24
 * 
25
 * @author Stefan Winter <[email protected]>
26
 * @author Maja Górecka-Wolniewicz <[email protected]>
27
 * @author Tomasz Wolniewicz <[email protected]>
28
 */
29
?>
30
<?php
31
require_once dirname(dirname(dirname(__FILE__))) . "/config/_config.php";
32
33
function displaySilverbulletPropertyWidget(&$theProfile, $readonly, &$uiElements) {
34
    ?>
35
    <div style='padding-bottom:20px;'>
36
        <h2><?php echo $theProfile->name; ?></h2>
37
        <?php
38
        $maxusers = $theProfile->getAttributes("internal:silverbullet_maxusers");
39
        $completeness = $theProfile->isEapTypeDefinitionComplete(new core\common\EAP(core\common\EAP::INTEGER_SILVERBULLET));
40
        // do we have all info needed for showtime? particularly: support email
41
        if (is_array($completeness)) {
42
            ?>
43
            <div class='notacceptable'>
44
                <?php echo _("Information needed!"); ?>
45
                <ul style='margin:1px'>
46
                    <?php
47
                    foreach ($completeness as $missing_attrib) {
48
                        echo "<li>" . $uiElements->displayName($missing_attrib) . "</li>";
49
                    }
50
                    ?>
51
                </ul>
52
            </div>
53
            <?php
54
        } else {
55
            echo sprintf(_("You can create up to %d users."), $maxusers[0]['value']) . "<br/>" . sprintf(_("Their credentials will carry the name <strong>%s</strong>."), $theProfile->realm);
56
        }
57
        ?>
58
        <br/>
59
        <br/>
60
        <?php
61
        if ($readonly === FALSE) {
62
            ?>
63
            <form action='edit_silverbullet.php?inst_id=<?php echo $theProfile->institution; ?>&amp;profile_id=<?php echo $theProfile->identifier; ?>' method='POST'>
64
                <button <?php echo ( is_array($completeness) ? "disabled" : "" ); ?> type='submit' name='sb_action' value='sb_edit'><?php echo _("Manage User Base"); ?></button>
65
            </form>
66
            <?php
67
        }
68
        ?>
69
    </div>
70
    <?php
71
}
72
73
/**
74
 * display an infocard with overview data of a RADIUS profile
75
 * 
76
 * @param \core\Profile             $theProfile the profile we display
77
 * @param boolean                   $readonly     are we in readonly mode? No edit buttons then...
78
 * @param \web\lib\admin\UIElements $uiElements   some UI elements
79
 * @param string                    $editMode 'fullaccess', 'readonly'
80
 * @throws Exception
81
 */
82
function displayRadiusPropertyWidget(&$theProfile, $readonly, &$uiElements, $editMode) {
83
    ?>
84
    <div style='padding-bottom:20px;'>
85
        <?php $profile_name = $theProfile->name; ?>
86
        <div style='margin-bottom:10px; display:block;'>
87
            <h2 style='overflow:auto; display:inline; padding-bottom: 10px;'><?php printf(_("Profile: %s"), $profile_name); ?></h2>
88
        </div>
89
        <?php
90
        // see if there are any profile-level overrides
91
        $attribs = $theProfile->getAttributes();
92
        // write things into a buffer; we need some function calls to determine
93
        // readiness - but want to display it before!
94
        $has_overrides = FALSE;
95
        foreach ($attribs as $attrib) {
96
            if ($attrib['level'] == \core\Options::LEVEL_PROFILE && !preg_match("/^(internal:|profile:name|profile:description|profile:production|eap:)/", $attrib['name'])) {
97
                $has_overrides = TRUE;
98
            }
99
        }
100
        $buffer_eaptypediv = "<div style='margin-bottom:40px; float:left;'>" . _("<strong>EAP Types</strong> (in order of preference):") . "<br/>";
101
        $typelist = $theProfile->getEapMethodsinOrderOfPreference();
102
        $allcomplete = TRUE;
103
        foreach ($typelist as $eaptype) {
104
            $buffer_eaptypediv .= $eaptype->getPrintableRep();
105
            $completeness = $theProfile->isEapTypeDefinitionComplete($eaptype);
106
            if ($completeness === true) {
107
                $buffer_eaptypediv .= " <div class='acceptable'>" . _("OK") . "</div>";
108
            } else {
109
                $buffer_eaptypediv .= " <div class='notacceptable'>";
110
                $buffer_eaptypediv .= _("Information needed!");
111
                if (is_array($completeness)) {
112
                    $buffer_eaptypediv .= "<ul style='margin:1px'>";
113
                    foreach ($completeness as $missing_attrib) {
114
                        $buffer_eaptypediv .= "<li>" . $uiElements->displayName($missing_attrib) . "</li>";
115
                    }
116
                    $buffer_eaptypediv .= "</ul>";
117
                }
118
                $buffer_eaptypediv .= "</div>";
119
                $allcomplete = FALSE;
120
            }
121
            $attribs = $theProfile->getAttributes();
122
            $justOnce = FALSE;
123
            foreach ($attribs as $attrib) {
124
                if ($attrib['level'] == \core\Options::LEVEL_METHOD && !preg_match("/^internal:/", $attrib['name']) && !$justOnce) {
125
                    $justOnce = TRUE;
126
                    $buffer_eaptypediv .= "<img src='../resources/images/icons/Tabler/square-rounded-letter-e-blue.svg' alt='" . _("Options on EAP Method/Device level are in effect.") . "'>";
127
                }
128
            }
129
            $buffer_eaptypediv .= "<br/>";
130
        }
131
        $buffer_eaptypediv .= "</div>";
132
133
        $buffer_headline = "<div style='float:right;padding-left:10px'>";
134
        $readiness = $theProfile->readinessLevel();
135
        if ($has_overrides) {
136
            $buffer_headline .= $uiElements->boxRemark("", _("Option override on profile level is in effect."), TRUE);
137
        }
138
        $buffer_headline .= "<br/>";
139
        if (!$allcomplete) {
140
            $buffer_headline .= $uiElements->boxError("", _("The information in this profile is incomplete."), TRUE);
141
        }
142
        switch ($readiness) {
143
            case core\AbstractProfile::READINESS_LEVEL_SHOWTIME:
144
                $buffer_headline .= $uiElements->boxOkay("", _("This profile is shown on the user download interface."), TRUE);
145
                break;
146
            case core\AbstractProfile::READINESS_LEVEL_SUFFICIENTCONFIG:
147
                $buffer_headline .= $uiElements->boxWarning("", sprintf(_("This profile is NOT shown on the user download interface, even though we have enough information to show. To enable the profile, add the attribute \"%s\" and tick the corresponding box."), $uiElements->displayName("profile:production")), TRUE);
148
        }
149
        if ($theProfile->isRedirected()) {
150
            $iconData = $uiElements->iconData('PROFILES_REDIRECTED');
151
            $iconData['text'] = _("Profile redirected");
152
            $buffer_headline .= "<br/>" . $uiElements->catIcon(($iconData));
153
            
154
        } 
155
        
156
        $certStatus = $theProfile->certificateStatus();
157
        switch ($certStatus) {
158
            case core\AbstractProfile::CERT_STATUS_OK:
159
                $iconData = $uiElements->iconData('CERT_STATUS_OK');
160
                $buffer_headline .= "<br/>" . $uiElements->catIcon(($iconData));
161
                break;
162
            case core\AbstractProfile::CERT_STATUS_WARN:
163
                $iconData = $uiElements->iconData('CERT_STATUS_WARN');
164
                $buffer_headline .= "<br/>" . $uiElements->catIcon(($iconData));                
165
                break;
166
            case core\AbstractProfile::CERT_STATUS_ERROR:
167
                $iconData = $uiElements->iconData('CERT_STATUS_ERROR');
168
                $buffer_headline .= "<br/>" . $uiElements->catIcon(($iconData));
169
                break;            
170
        }
171
        $buffer_headline .= "</div>";
172
173
        echo $buffer_headline;
174
        echo $buffer_eaptypediv;
175
176
        $has_eaptypes = count($theProfile->getEapMethodsInOrderOfPreference(1));
177
        $hasRealmArray = $theProfile->getAttributes("internal:realm");
178
        $has_realm = $hasRealmArray[0]['value'];
179
180
        // our own base location, to give to diag URLs
181
        if (isset($_SERVER['HTTPS'])) {
182
            $link = 'https://';
183
        } else {
184
            $link = 'http://';
185
        }
186
        $link .= $_SERVER['SERVER_NAME'];
187
        ?>
188
        <div class='profilemodulebuttons' style='float:right;'>
189
            <?php
190
            if (\config\Master::FUNCTIONALITY_LOCATIONS['DIAGNOSTICS'] !== NULL) {
191
                if (\config\Master::FUNCTIONALITY_LOCATIONS['DIAGNOSTICS'] == "LOCAL") {
192
                    $diagUrl = "../diag/";
193
                } else {
194
                    $diagUrl = \config\Master::FUNCTIONALITY_LOCATIONS['DIAGNOSTICS'] . "/diag/";
195
                }
196
                ?>
197
                <form action='<?php echo $diagUrl . "action_realmcheck.php?inst_id=" . $theProfile->institution . "&profile_id=" . $theProfile->identifier ?>' method='post' accept-charset='UTF-8'>
198
                    <input type='hidden' name='comefrom' value='<?php echo htmlspecialchars($link . $_SERVER['SCRIPT_NAME']); ?>'/>
199
                    <button type='submit' name='profile_action' value='check' <?php echo ($has_realm ? "" : "disabled='disabled'"); ?> title='<?php echo _("The realm can only be checked if you configure the realm!"); ?>'>
200
                        <?php echo _("Check realm reachability"); ?>
201
                    </button>
202
                </form>
203
                <?php
204
            }
205
            ?>
206
            <form action='overview_installers.php?inst_id=<?php echo $theProfile->institution; ?>&amp;profile_id=<?php echo $theProfile->identifier; ?>' method='post' accept-charset='UTF-8'>
207
                <button type='submit' name='profile_action' value='check' <?php echo ($has_eaptypes ? "" : "disabled='disabled'"); ?> title='<?php echo _("You have not fully configured any supported EAP types!"); ?>'>
208
                    <?php echo _("Installer Fine-Tuning and Download"); ?>
209
                </button>
210
            </form>
211
        </div>
212
        <div class='buttongroupprofilebox' style='clear:both; display: flex;'>
213
            <?php 
214
                if ($editMode == 'readonly') {
215
                    $editLabel = _("View");
216
                }
217
                if ($editMode == 'fullaccess') {
218
                    $editLabel = _("Edit");
219
                }
220
            if ($readonly === FALSE) { ?>
221
                <div style='margin-right: 200px; display: ruby'>
222
                    <form action='edit_profile.php?inst_id=<?php echo $theProfile->institution; ?>&amp;profile_id=<?php echo $theProfile->identifier; ?>' method='post' accept-charset='UTF-8'>
223
                        <hr/>
224
                        <button type='submit' name='profile_action' value='edit'><?php echo $editLabel; ?></button>
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $editLabel does not seem to be defined for all execution paths leading up to this point.
Loading history...
225
                    </form>
226
                    <?php if ($editMode == 'fullaccess') { ?>
227
                    <form action='edit_profile_result.php?inst_id=<?php echo $theProfile->institution; ?>&amp;profile_id=<?php echo $theProfile->identifier; ?>' method='post' accept-charset='UTF-8'>
228
                        <button class='delete' type='submit' name='submitbutton' value='<?php echo web\lib\common\FormElements::BUTTON_DELETE; ?>' onclick="return confirm('<?php echo sprintf(_("Do you really want to delete the profile %s?"), $profile_name); ?>')">
229
                            <?php echo _("Delete") ?>
230
                        </button>
231
                    </form>
232
                    <form action='duplicate_profile.php?inst_id=<?php echo $theProfile->institution; ?>&amp;profile_id=<?php echo $theProfile->identifier; ?>' method='post' accept-charset='UTF-8'>
233
                        <button type='submit' name='profile_duplicate'>
234
                            <?php echo _("Duplicate this profile"); ?>
235
                        </button>
236
                    </form>
237
                    <?php } ?>
238
                </div>
239
                <?php
240
            }
241
            if ($readiness == core\AbstractProfile::READINESS_LEVEL_SHOWTIME) {
242
                ?>
243
                <div style='display: flex;'>
244
                    <?php
245
                    $idpLevelUrl = $link . dirname(dirname($_SERVER['SCRIPT_NAME'])) . "?idp=" . $theProfile->institution;
246
                    $displayurl = $idpLevelUrl . "&amp;profile=" . $theProfile->identifier;
247
                    $QRurl = $idpLevelUrl . "&profile=" . $theProfile->identifier;
248
                    $qrCode = new \chillerlan\QRCode\QRCode(new \chillerlan\QRCode\QROptions([
249
                                'outputType' => \chillerlan\QRCode\QRCode::OUTPUT_IMAGE_PNG,
250
                                'eccLevel' => \chillerlan\QRCode\QRCode::ECC_H,
251
                                'scale' => web\lib\admin\UIElements::QRCODE_PIXELS_PER_SYMBOL,
252
                                'imageBase64' => false,
253
                    ]));
254
                    echo "<a href='$displayurl' style='white-space: nowrap; text-align: center;'>";
255
                    $rawQr = $qrCode->render($QRurl);
256
                    if (empty($rawQr)) {
257
                        throw new Exception("Something went seriously wrong during QR code generation!");
258
                    }
259
                    $uri = "data:image/png;base64," . base64_encode($uiElements->pngInjectConsortiumLogo($rawQr, web\lib\admin\UIElements::QRCODE_PIXELS_PER_SYMBOL));
260
                    $size = getimagesize($uri);
261
                    echo "<img width='" . ($size[0] / 4) . "' height='" . ($size[1] / 4) . "' src='$uri' alt='QR-code'/>";
262
263
                    //echo "<nobr>$displayurl</nobr></a>";
264
                    echo "<p>$displayurl</p></a>";
265
                    ?>
266
                </div>
267
                <?php
268
            }
269
            ?>
270
        </div>
271
    </div>
272
    <?php
273
}
274
275
276
$deco = new \web\lib\admin\PageDecoration();
277
$validator = new \web\lib\common\InputValidation();
278
$uiElements = new web\lib\admin\UIElements();
279
echo $deco->defaultPagePrelude(sprintf(_("%s: %s Dashboard"), \config\Master::APPEARANCE['productname'], $uiElements->nomenclatureParticipant));
280
281
// let's check if the inst handle actually exists in the DB
282
[$my_inst, $editMode] = $validator->existingIdPInt($_GET['inst_id'], $_SESSION['user']);
283
284
$myfed = new \core\Federation($my_inst->federation);
285
286
// delete stored realm
287
288
if (isset($_SESSION['check_realm'])) {
289
    unset($_SESSION['check_realm']);
290
}
291
$mapCode = web\lib\admin\AbstractMap::instance($my_inst, TRUE);
292
echo $mapCode->htmlHeadCode();
293
?>
294
<script src="js/XHR.js"></script>
295
<script src="js/popup_redirect.js"></script>
296
<script src="../external/jquery/jquery-ui.js"></script>
297
<link rel="stylesheet" type="text/css" href="../external/jquery/jquery-ui.css" />
298
<style>
299
    #yourBtn {
300
  width: 150px;
301
  padding: 10px;
302
  -webkit-border-radius: 0px;
303
  -moz-border-radius: 0px;
304
  border: 1px  solid #000;
305
  font-family: Arial;
306
  font-size: 13px;
307
  text-align: center;
308
  background-color: yellow;
309
}
310
</style>
311
<script src="../external/jquery/DataTables/datatables.js"></script>
312
<link type="text/css"  rel="stylesheet" href="../external/jquery/DataTables/datatables.css"  media="all" />
313
<script>
314
$(document).ready(function() {    
315
    $("img.cat-icon").tooltip();
316
    $("table.downloads").DataTable({
317
          "dom": 't',
318
          "pageLength": 100,
319
          "columnDefs": [
320
        { orderSequence: ['asc'], targets: [0] },
321
        { orderSequence: ['desc', 'asc'], targets: [1] },
322
        { orderSequence: ['desc', 'asc'], targets: [2] }
323
        ]
324
    });
325
});
326
327
</script>
328
329
<body <?php echo $mapCode->bodyTagCode(); ?>>
330
    <?php
331
    echo $deco->productheader("ADMIN-PARTICIPANT");
332
333
// Sanity check complete. Show what we know about this IdP.
334
    $idpoptions = $my_inst->getAttributes();
335
    if ($editMode == 'readonly') {
336
        $editLabel = _("View ...");
337
    }
338
    if ($editMode == 'fullaccess') {
339
        $editLabel = _("Edit ...");
340
    }
341
    ?>
342
    <h1><?php echo sprintf(_("%s Overview"), $uiElements->nomenclatureParticipant); ?></h1>
343
    <hr/>
344
    <div>
345
        <h2 style='display: flex;'><?php echo sprintf(_("%s general settings"), $uiElements->nomenclatureParticipant); ?>&nbsp;
346
            <form action='edit_participant.php?inst_id=<?php echo $my_inst->identifier; ?>' method='post' accept-charset='UTF-8'>
347
                <button type='submit' name='submitbutton' value='<?php echo \web\lib\common\FormElements::BUTTON_EDIT; ?>'><?php echo $editLabel; ?></button>
348
            </form>
349
        </h2>
350
        <?php
351
        echo $uiElements->instLevelInfoBoxes($my_inst);
352
        ?>
353
        <?php
354
        foreach ($idpoptions as $optionname => $optionvalue) {
355
            if ($optionvalue['name'] == "general:geo_coordinates") {
356
                echo '<div class="infobox">';
357
                echo $mapCode->htmlShowtime();
358
                echo '</div>';
359
                break;
360
            }
361
        }
362
        ?>
363
364
    </div>
365
    <hr/>
366
    <?php
367
    $readonly = \config\Master::DB['INST']['readonly'];
368
    if (preg_match("/IdP/", $my_inst->type)) {
369
        ?>
370
        <h2 style='display: flex;'><?php printf(_("%s: %s Deployment Details"), $uiElements->nomenclatureParticipant, $uiElements->nomenclatureIdP); ?>&nbsp;
371
            <?php
372
            $profiles_for_this_idp = $my_inst->listProfiles();
373
            if ($readonly === FALSE) {
374
375
                // the opportunity to add a new silverbullet profile is only shown if
376
                // a) there is no SB profile yet
377
                // b) federation wants this to happen
378
                // first find out if we already have SB profiles
379
                $sbProfileExists = FALSE;
380
                foreach ($profiles_for_this_idp as $profilecount => $profile_list) {
381
                    switch (get_class($profile_list)) {
382
                        case "core\ProfileSilverbullet":
383
                            $sbProfileExists = TRUE;
384
                            break;
385
                        default:
386
                    }
387
                }
388
                if (\config\Master::FUNCTIONALITY_LOCATIONS['CONFASSISTANT_SILVERBULLET'] == "LOCAL" && count($myfed->getAttributes("fed:silverbullet")) > 0 && $sbProfileExists === FALSE) {
389
                    // the button is greyed out if there's no support email address configured...
390
                    $hasMail = count($my_inst->getAttributes("support:email"));
391
                    ?>
392
                    <form action='edit_silverbullet.php?inst_id=<?php echo $my_inst->identifier; ?>' method='post' accept-charset='UTF-8'>
393
                        <div>
394
                            <button type='submit' <?php echo ($hasMail > 0 ? "" : "disabled"); ?> name='profile_action' value='new'>
395
                                <?php echo sprintf(_("Add %s profile ..."), \core\ProfileSilverbullet::PRODUCTNAME); ?>
396
                            </button>
397
                        </div>
398
                    </form>&nbsp;
399
                    <?php
400
                }
401
                ?>
402
403
                <?php
404
                // adding a normal profile is always possible if we're configured for it
405
                if (\config\Master::FUNCTIONALITY_LOCATIONS['CONFASSISTANT_RADIUS'] == "LOCAL" && $editMode === 'fullaccess') {
406
                    ?>
407
                    <form action='edit_profile.php?inst_id=<?php echo $my_inst->identifier; ?>' method='post' accept-charset='UTF-8'>
408
                        <div>
409
                            <button type='submit' name='profile_action' value='new'>
410
                                <?php echo _("New RADIUS/EAP profile (manual setup) ..."); ?>
411
                            </button>
412
                        </div>
413
                    </form>&nbsp;
414
                    <form method='post' action='inc/profileAutodetectCA.inc.php?inst_id=<?php echo $my_inst->identifier; ?>' onsubmit='popupRedirectWindow(this); return false;' accept-charset='UTF-8'>
415
                        <div>
416
                            <button type='submit' name='profile_action' value='new'>
417
                                <?php echo _("New RADIUS/EAP profile (autodetect server details) ..."); ?>
418
                            </button>
419
                        </div>
420
                    </form>
421
                    <?php
422
                }
423
            }
424
            ?>
425
        </h2>
426
        <?php if(count($profiles_for_this_idp) > 1 && $readonly === FALSE && $editMode === 'fullaccess') { ?>
427
                    <form method='post' action='sort_profiles.php?inst_id=<?php echo $my_inst->identifier; ?>' accept-charset='UTF-8'>
428
                        <div>
429
                            <button type='submit' name='profile_sorting'>
430
                                <?php echo _("Change the order of profiles"); ?>
431
                            </button>
432
                        </div>
433
                    </form>  <p>
434
        <?php }
435
        if (count($profiles_for_this_idp) == 0) { // no profiles yet.
436
            printf(_("There are not yet any profiles for your %s."), $uiElements->nomenclatureIdP);
437
        }
438
        //print '<pre>'; print_r($profiles_for_this_idp); print '</pre>';
439
// if there is one profile and it is of type Silver Bullet, display a very
440
// simple widget with just a "Manage" button
441
        foreach ($profiles_for_this_idp as $profilecount => $profile_list) {
442
            ?>
443
            <div style='display: table-row_id; margin-bottom: 20px;'>
444
                <div class='profilebox' style='display: table-cell; min-width: 650px;'>
445
                    <?php
446
                    switch (get_class($profile_list)) {
447
                        case "core\ProfileSilverbullet":
448
                            displaySilverbulletPropertyWidget($profile_list, $readonly, $uiElements);
449
                            break;
450
                        case "core\ProfileRADIUS":
451
                            displayRadiusPropertyWidget($profile_list, $readonly, $uiElements, $editMode);
452
                            break;
453
                        default:
454
                            throw new Exception("We were asked to operate on something that is neither a RADIUS nor Silverbullet profile!");
455
                    }
456
                    ?>
457
                </div>
458
                <!-- dummy width to keep a little distance -->
459
                <div style='width:20px;'></div>
460
                <div style='display: table-cell; min-width:200px;'>
461
                    <p>
462
                        <strong><?php echo _("User Downloads"); ?></strong>
463
                    </p>
464
                    <table class="downloads" id="downloads_<?php echo $profilecount ?>">
465
                        <thead><tr>
466
                        <?php
467
                        echo "<th>"._("Device")."</th><th>"._("global")."</th><th>"._("this month")."</th></tr></thead><tbody>";
468
                        $stats = $profile_list->getUserDownloadStats();
469
                        foreach ($stats as $dev => $count) {
470
                            if (isset($count['monthly'])) {
471
                                echo "<tr><td><strong>$dev</strong></td><td>".$count['current']."</td><td>".$count['monthly']."</td></tr>";
472
                            }
473
                        }
474
                        ?>
475
                        </tbody>
476
                    </table>
477
                </div>
478
            </div>
479
            <!-- dummy div to keep a little distance-->
480
            <div style='height:20px'></div>
481
            <?php
482
        }
483
        ?>
484
        <hr/>
485
        <?php
486
    }
487
    if (\config\Master::FUNCTIONALITY_LOCATIONS['CONFASSISTANT_SILVERBULLET'] == "LOCAL" && count($myfed->getAttributes("fed:silverbullet")) > 0 && preg_match("/SP/", $my_inst->type)) {
488
        include "overview_sp.php";
489
    }
490
    echo $deco->footer();
491
    
492