diff --git a/modules/discopower/lib/PowerIdPDisco.php b/modules/discopower/lib/PowerIdPDisco.php index d7f0e7f6496f6b099247d279ec5658008439dcea..e70bc83d6c90b182140a27729d145ee6ccc43809 100644 --- a/modules/discopower/lib/PowerIdPDisco.php +++ b/modules/discopower/lib/PowerIdPDisco.php @@ -12,8 +12,6 @@ */ class sspmod_discopower_PowerIdPDisco extends SimpleSAML_XHTML_IdPDisco { - - /** * The configuration for this instance. * @@ -127,7 +125,7 @@ class sspmod_discopower_PowerIdPDisco extends SimpleSAML_XHTML_IdPDisco $tags = $val['tags']; } foreach ($tags as $tag) { - if (!empty($enableTabs) && !in_array($tag, $enableTabs, true)) { + if (!empty($enableTabs) && !in_array($tag, $enableTabs)) { continue; } $slist[$tag][$key] = $val; @@ -153,21 +151,21 @@ class sspmod_discopower_PowerIdPDisco extends SimpleSAML_XHTML_IdPDisco */ private function processFilter($filter, $entry, $default = true) { - if (in_array($entry['entityid'], $filter['entities.include'], true)) { + if (in_array($entry['entityid'], $filter['entities.include'])) { return true; } - if (in_array($entry['entityid'], $filter['entities.exclude'], true)) { + if (in_array($entry['entityid'], $filter['entities.exclude'])) { return false; } if (array_key_exists('tags', $entry)) { foreach ($filter['tags.include'] as $fe) { - if (in_array($fe, $entry['tags'], true)) { + if (in_array($fe, $entry['tags'])) { return true; } } foreach ($filter['tags.exclude'] as $fe) { - if (in_array($fe, $entry['tags'], true)) { + if (in_array($fe, $entry['tags'])) { return false; } } @@ -246,12 +244,6 @@ class sspmod_discopower_PowerIdPDisco extends SimpleSAML_XHTML_IdPDisco $idpList = $this->getIdPList(); $idpList = $this->idplistStructured($this->filterList($idpList)); $preferredIdP = $this->getRecommendedIdP(); - $faventry = NULL; - foreach ($idpList AS $tab => $slist) { - if (!empty($preferredIdP) && array_key_exists($preferredIdP, $slist)) { - $faventry = $slist[$preferredIdP]; - } - } $t = new SimpleSAML_XHTML_Template($this->config, 'discopower:disco.tpl.php', 'disco'); $discoPowerTabs = array( @@ -269,21 +261,104 @@ class sspmod_discopower_PowerIdPDisco extends SimpleSAML_XHTML_IdPDisco 'switzerland' => $t->noop('{discopower:tabs:switzerland}'), 'ukacessfederation' => $t->noop('{discopower:tabs:ukacessfederation}'), ); - $t->data['faventry'] = $faventry; - $t->data['tabNames'] = $discoPowerTabs; - $t->data['idplist'] = $idpList; - $t->data['preferredidp'] = $preferredIdP; + $t->data['return'] = $this->returnURL; $t->data['returnIDParam'] = $this->returnIdParam; $t->data['entityID'] = $this->spEntityId; + $t->data['defaulttab'] = $this->discoconfig->getValue('defaulttab', 0); + + $idpList = $this->processMetadata($t, $idpList, $preferredIdP); + + $t->data['idplist'] = $idpList; + $faventry = null; + foreach ($idpList as $tab => $slist) { + if (!empty($preferredIdP) && array_key_exists($preferredIdP, $slist)) { + $t->data['faventry'] = $slist[$preferredIdP]; + break; + } + } + + if (!empty($this->data['faventry'])) { + $this->data['autofocus'] = 'favouritesubmit'; + } + + $search = '<script type="text/javascript"> + $(document).ready(function() { + $("#tabdiv").tabs({ selected: ' . $t->data['defaulttab'] . ' });'; + $i = 0; + foreach ($idpList as $tab => $slist) { + $search .= "\n" . '$("#query_' . $tab . '").liveUpdate("#list_' . $tab . '")' . + (($i++ == 0) && (empty($this->data['faventry'])) ? '.focus()' : '') . ';'; + } + $search .= "});\n</script>"; + + $t->data['search'] = $search; + $t->data['score'] = $this->discoconfig->getValue('score', 'quicksilver'); + $t->data['tabNames'] = $discoPowerTabs; + $t->data['preferredidp'] = $preferredIdP; $t->data['urlpattern'] = htmlspecialchars(\SimpleSAML\Utils\HTTP::getSelfURLNoQuery()); $t->data['rememberenabled'] = $this->config->getBoolean('idpdisco.enableremember', false); $t->data['rememberchecked'] = $this->config->getBoolean('idpdisco.rememberchecked', false); - $t->data['defaulttab'] = $this->discoconfig->getValue('defaulttab', 0); - $t->data['score'] = $this->discoconfig->getValue('score', 'quicksilver'); + $t->data['jquery'] = array('core' => true, 'ui' => true); $t->show(); } + private function processMetadata($t, $metadata, $favourite) + { + $basequerystring = '?' . + 'entityID=' . urlencode($t->data['entityID']) . '&' . + 'return=' . urlencode($t->data['return']) . '&' . + 'returnIDParam=' . urlencode($t->data['returnIDParam']) . '&idpentityid='; + + foreach ($metadata as $tab => $idps) { + foreach ($idps as $entityid => $entity) { + $translation = false; + + // Translate name + if (isset($entity['UIInfo']['DisplayName'])) { + $displayName = $entity['UIInfo']['DisplayName']; + + // Should always be an array of language code -> translation + assert(is_array($displayName)); + + if (!empty($displayName)) { + $translation = $t->getTranslator()->getPreferredTranslation($displayName); + } + } + + if ((translation === false) && array_key_exists('name', $entity)) { + if (is_array($entity['name'])) { + $translation = $t->getTranslator()->getPreferredTranslation($entity['name']); + } else { + $translation = $entity['name']; + } + } + + if ($translation === false) { + $translation = $entity['entityid']; + } + $entity['translated'] = $translation; + + // HTML output + if ($entity['entityid'] === $favourite) { + $html = '<a class="metaentry favourite" href="' . $basequerystring . urlencode($entity['entityid']) . '">'; + } else { + $html = '<a class="metaentry" href="' . $basequerystring . urlencode($entity['entityid']) . '">'; + } + $html .= $entity['translated']; + if (array_key_exists('icon', $entity) && $entity['icon'] !== null) { + $iconUrl = \SimpleSAML\Utils\HTTP::resolveURL($entity['icon']); + $html .= '<img alt="Icon for identity provider" class="entryicon" src="' . htmlspecialchars($iconUrl) . '" />'; + } + $html .= '</a>'; + $entity['html'] = $html; + + // Save processed data + $metadata[$tab][$entityid] = $entity; + } + } + return $metadata; + } /** * Get the IdP entities saved in the common domain cookie. @@ -319,7 +394,7 @@ class sspmod_discopower_PowerIdPDisco extends SimpleSAML_XHTML_IdPDisco */ protected function setPreviousIdP($idp) { - assert(is_string($idp)); + assert('is_string($idp)'); if ($this->cdcDomain === null) { parent::setPreviousIdP($idp); diff --git a/modules/discopower/templates/disco.tpl.php b/modules/discopower/templates/disco.tpl.php index b7b1001219a31da01cb39fd8219fd950f990631d..cbb3c787df72b2156bea5a9231e98f5bdd61ce7d 100644 --- a/modules/discopower/templates/disco.tpl.php +++ b/modules/discopower/templates/disco.tpl.php @@ -8,28 +8,8 @@ $this->data['jquery'] = array('core' => TRUE, 'ui' => TRUE, 'css' => TRUE); $this->data['head'] = '<link rel="stylesheet" media="screen" type="text/css" href="' . SimpleSAML\Module::getModuleUrl('discopower/style.css') . '" />'; -$this->data['head'] .= '<script type="text/javascript" src="' . SimpleSAML\Module::getModuleUrl('discopower/js/jquery.livesearch.js') . '"></script>'; -$this->data['head'] .= '<script type="text/javascript" src="' . SimpleSAML\Module::getModuleUrl('discopower/js/' . $this->data['score'] . '.js') . '"></script>'; - -$this->data['head'] .= '<script type="text/javascript"> - -$(document).ready(function() { - $("#discotabs").tabs({ selected: ' . $this->data['defaulttab'] . ' }); '; - -$i = 0; -foreach ($this->data['idplist'] AS $tab => $slist) { - $this->data['head'] .= "\n" . '$("#query_' . $tab . '").liveUpdate("#list_' . $tab . '")' . - (($i++ == 0) && (empty($this->data['faventry'])) ? '.focus()' : '') . - ';'; - - -} - -$this->data['head'] .= ' -}); - -</script>'; - +$this->data['post'] = '<script type="text/javascript" src="' . SimpleSAML\Module::getModuleUrl('discopower/js/jquery.livesearch.js') . '"></script>'; +$this->data['post'] .= '<script type="text/javascript" src="' . SimpleSAML\Module::getModuleUrl('discopower/js/quicksilver.js') . '"></script>'; @@ -70,7 +50,7 @@ function showEntry($t, $metadata, $favourite = FALSE) { function getTranslatedName($t, $metadata) { if (isset($metadata['UIInfo']['DisplayName'])) { $displayName = $metadata['UIInfo']['DisplayName']; - assert(is_array($displayName)); // Should always be an array of language code -> translation + assert('is_array($displayName)'); // Should always be an array of language code -> translation if (!empty($displayName)) { return $t->getTranslator()->getPreferredTranslation($displayName); } @@ -116,15 +96,21 @@ if (!empty($this->data['faventry'])) { -<div id="discotabs"> +<div id="tabdiv"> <ul class="tabset_tabs"> <?php $tabs = array_keys( $this->data['idplist']); + $i = 1; foreach ($tabs AS $tab) { if(!empty($this->data['idplist'][$tab])) { - echo '<li><a href="#' . $tab . '"><span>' . $this->t($this->data['tabNames'][$tab]) . '</span></a></li> '; + if ($i === 1) { + echo '<li class="tab-link current" data-tab="'.$tab.'"><a href="#' . $tab . '"><span>' . $this->t($this->data['tabNames'][$tab]) . '</span></a></li>'; + } else { + echo '<li class="tab-link" data-tab="'.$tab.'"><a href="#' . $tab . '"><span>' . $this->t($this->data['tabNames'][$tab]) . '</span></a></li> '; + } + $i++; } } @@ -138,14 +124,17 @@ if (!empty($this->data['faventry'])) { foreach( $this->data['idplist'] AS $tab => $slist) { - - echo '<div id="' . $tab . '">'; - + $first = array_keys($this->data['idplist']); + if ($first[0] === $tab) { + echo '<div id="' . $tab . '" class="tabset_content current">'; + } else { + echo '<div id="' . $tab . '" class="tabset_content">'; + } if (!empty($slist)) { echo(' <div class="inlinesearch">'); echo(' <p>Incremental search...</p>'); - echo(' <form id="idpselectform" action="?" method="get"><input class="inlinesearchf" type="text" value="" name="query_' . $tab . '" id="query_' . $tab . '" /></form>'); + echo(' <form id="idpselectform" action="?" method="get"><input class="inlinesearch" type="text" value="" name="query_' . $tab . '" id="query_' . $tab . '" /></form>'); echo(' </div>'); echo(' <div class="metalist" id="list_' . $tab . '">'); @@ -171,5 +160,22 @@ foreach( $this->data['idplist'] AS $tab => $slist) { </div> - -<?php $this->includeAtTemplateBase('includes/footer.php'); +<script type="text/javascript"> +$(document).ready(function() { +<?php +$i = 0; +foreach ($this->data['idplist'] AS $tab => $slist) { + echo "\n" . '$("#query_' . $tab . '").liveUpdate("#list_' . $tab . '")' . + (($i++ == 0) && (empty($this->data['faventry'])) ? '.focus()' : '') . + ';'; + + +} +?> +}); + +</script> + +<?php +$this->data['post'] .= '<script type="text/javascript" src="' . SimpleSAML\Module::getModuleUrl('discopower/js/javascript.js') . '"></script>'; +$this->includeAtTemplateBase('includes/footer.php'); diff --git a/modules/discopower/templates/disco.twig b/modules/discopower/templates/disco.twig new file mode 100644 index 0000000000000000000000000000000000000000..3645cdb169a6b53dc3b78446236430b7b425ec87 --- /dev/null +++ b/modules/discopower/templates/disco.twig @@ -0,0 +1,66 @@ +{% set pagetitle = 'selectidp'|trans %} +{% extends "base.twig" %} + +{% block preload %} + <link href="{{ baseurlpath }}style.css" rel="stylesheet" type="text/css" media="screen" /> +{% endblock %} +{% block postload %} + <script type="text/javascript" src="{{ baseurlpath }}js/jquery.livesearch.js"></script> + <script type="text/javascript" src="{{ baseurlpath }}js/{{ score }}.js"></script> + {{ search|raw }} +{% endblock %} + +{% block content %} + {% if faventry is not empty %} + <div class="favourite">{{ '{disco:previous_auth}'|trans }} + <strong>{{ faventry.translated|escape('html') }}</strong> + <form id="idpselectform" method="get" action="{{ urlpattern }}"> + <input type="hidden" name="entityID" value="{{ entityID|escape('html') }}" /> + <input type="hidden" name="return" value="{{ return|escape('html') }}" /> + <input type="hidden" name="returnIDParam" value="{{ returnIDParam|escape('html') }}" /> + <input type="hidden" name="idpentityid" value="{{ faventry.entityid|escape('html') }}" /> + <input type="submit" name="formsubmit" id="favouritesubmit" value="{{ '{disco:login_at}'|trans }} {{ faventry.translated|escape('html') }}" /> + </form> + </div> + {% endif %} + + <div id="tabdiv"> + <ul class="tabset_tabs"> + {% set i = 1 %} + {% for tab, idps in idplist %} + {% if idps is not empty %} + {% if i == 1 %} + <li class="tab-link current" data-tab="{{ tab }}"><a href="#{{ tab }}"><span>{{ tabNames[tab]|trans }}</span></a></li> + {% set i = 2 %} + {% else %} + <li class="tab-link" data-tab="{{ tab }}"><a href="#{{ tab }}"><span>{{ tabNames[tab]|trans }}</span></a></li> + {% endif %} + {% endif %} + {% endfor %} + </ul> + + {% set i = 1 %} + {% for tab, idps in idplist %} + {% if idps is not empty %} + {% if i == 1 %} + <div id="{{ tab }}" class="tabset_content current"> + {% set i = 2 %} + {% else %} + <div id="{{ tab }}" class="tabset_content"> + {% endif %} + <div class="inlinesearch"> + <p>Incremental search...</p> + <form id="idpselectform" method="get"> + <input class="inlinesearch" type="text" value="" name="query_{{ tab }}" id="query_{{ tab }}" /> + </form> + </div> + <div class="metalist" id="list_{{ tab }}"> + {% for entityid, entity in idps %} + {{ entity.html|raw }} + {% endfor %} + </div> + </div> + {% endif %} + {% endfor %} + </div> +{% endblock %} diff --git a/modules/discopower/www/style.css b/modules/discopower/www/style.css index 3af002dff4a6006a83c75275ea6d9870465a30e8..dddb03c2221ba40ca07a1783f20b0f1b345ed233 100644 --- a/modules/discopower/www/style.css +++ b/modules/discopower/www/style.css @@ -1,76 +1,107 @@ -.inlinesearch:hover { - -} .inlinesearch { - float: right; - margin: 0em 3px .5em 1em; - -/* padding: .3em;*/ + float: right; + margin: 0em 3px .5em 1em; } .inlinesearch p { - font-size: 94%; - color: #aaa; - + font-size: 94%; + color: #aaa; } .inlinesearch input { - background-image:url('../../resources/icons/silk/magnifier.png'); - background-repeat:no-repeat; - background-position:center left; - border: 1px solid #ccc; - padding: 2px 2px 2px 20px; - margin: 0px 2px 0px 0px; + background-image:url('../../resources/icons/silk/magnifier.png'); + background-repeat:no-repeat; + background-position:center left; + border: 1px solid #ccc; + padding: 2px 2px 2px 20px; + margin: 0px 2px 0px 0px; } .inlinesearch * { - margin: 0px; - padding: 0px; + margin: 0px; + padding: 0px; } div.metalist { - clear: both; - list-style: none; - margin: 1em 2px .5em 2px; - padding: 0px; + clear: both; + list-style: none; + margin: 1em 2px .5em 2px; + padding: 0px; } a.metaentry { - display: block; - border: 1px solid #ccc; - margin: 0px 0px -1px 0px; - padding: .2em 1em .2em 20px; - cursor: pointer; - cursor: hand; + display: block; + border: 1px solid #ccc; + margin: 0px 0px -1px 0px; + padding: .2em 1em .2em 20px; + cursor: pointer; + cursor: hand; } a.metaentry.favourite { - background-image:url('../../resources/icons/silk/heart.png'); - background-repeat:no-repeat; - background-position:center left; - + background-image:url('../../resources/icons/silk/heart.png'); + background-repeat:no-repeat; + background-position:center left; } a.metaentry:hover { - border: 1px solid #ccc; - background: #eee; - - background-image:url('../../resources/icons/silk/star.png'); - background-repeat:no-repeat; - background-position:center left; + border: 1px solid #ccc; + background: #eee; + background-image:url('../../resources/icons/silk/star.png'); + background-repeat:no-repeat; + background-position:center left; } a.metaentry img.entryicon { - display: none; + display: none; } a.metaentry:hover img.entryicon { - display: inline; - top: 0px; - bottom: 0px; - clear: both; - float: right; - margin: 1em; - padding: 3px; - border: 1px solid #999; + display: inline; + top: 0px; + bottom: 0px; + clear: both; + float: right; + margin: 1em; + padding: 3px; + border: 1px solid #999; } div.favourite { + margin: 1em 0px; + padding: 1em; + border: 1px solid #ccc; + background-color: #eee; +} + +div#content { + margin: .4em ! important; +} + +form { + display: inline; +} - margin: 1em 0px; - padding: 1em; - border: 1px solid #ccc; - background-color: #eee; +table#statmeta { + width: 100%; +} + +ul.tabset_tabs { + margin: 0px; + padding: 0px; + list-style: none; +} + +ul.tabset_tabs li { + background: none; + color: #222; + display: inline-block; + padding: 10px 15px; + cursor: pointer; +} + +ul.tabset_tabs li.current { + background: #ededed; + color: #222; +} + +.tabset_content { + display: none; + background: #ededed; + padding: 15px; +} +.tabset_content.current { + display: inherit; }