From 83a9cfa8a5d5afbc4e98cc163d7f87e4ec1dfa04 Mon Sep 17 00:00:00 2001
From: Hanne Moa <hanne.moa@uninett.no>
Date: Fri, 26 Feb 2016 12:35:17 +0100
Subject: [PATCH] Start of Twigification

---
 cache/.gitkeep                    |   0
 lib/SimpleSAML/XHTML/Template.php | 164 +++++++++++++++++++++++++++---
 templates/_footer.twig.html       |   6 ++
 templates/_header.twig.html       |  12 +++
 templates/base.twig.html          |  31 ++++++
 templates/index.twig.html         |  32 ++++++
 templates/sandbox.twig.html       |   6 ++
 www/admin/index.php               |  27 +++++
 www/admin/sandbox.php             |  19 ++++
 9 files changed, 281 insertions(+), 16 deletions(-)
 create mode 100644 cache/.gitkeep
 create mode 100644 templates/_footer.twig.html
 create mode 100644 templates/_header.twig.html
 create mode 100644 templates/base.twig.html
 create mode 100644 templates/index.twig.html
 create mode 100644 templates/sandbox.twig.html
 create mode 100644 www/admin/index.php
 create mode 100644 www/admin/sandbox.php

diff --git a/cache/.gitkeep b/cache/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/lib/SimpleSAML/XHTML/Template.php b/lib/SimpleSAML/XHTML/Template.php
index 7cbf70939..b67758982 100644
--- a/lib/SimpleSAML/XHTML/Template.php
+++ b/lib/SimpleSAML/XHTML/Template.php
@@ -1,6 +1,5 @@
 <?php
 
-
 /**
  * A minimalistic XHTML PHP based template system implemented for SimpleSAMLphp.
  *
@@ -46,14 +45,32 @@ class SimpleSAML_XHTML_Template
      * @param string                   $template Which template file to load
      * @param string|null              $defaultDictionary The default dictionary where tags will come from.
      */
-    public function __construct(SimpleSAML_Configuration $configuration, $template, $defaultDictionary = null)
+    public function __construct(\SimpleSAML_Configuration $configuration, $template, $defaultDictionary = null)
     {
         $this->configuration = $configuration;
         $this->template = $template;
         $this->data['baseurlpath'] = $this->configuration->getBaseURL();
-        $this->translator = new SimpleSAML\Locale\Translate($configuration, $defaultDictionary);
+        $this->translator = new \SimpleSAML\Locale\Translate($configuration, $defaultDictionary);
+        $this->useTwig =  $this->setupTwig();
     }
 
+    /**
+     * Setup twig
+     */
+    private function setupTwig()
+    {
+        $twig_filename = basename($this->template, '.php').'.twig.html';
+        $filename = $this->findTemplatePath($twig_filename, $throw_exception=false);
+        // twig not in use for this page
+        if (is_null($filename)) {
+            return false;
+        }
+        $cache = $this->configuration->resolvePath('cache');
+        $this->template = $twig_filename;
+        $loader = new \Twig_Loader_Filesystem(array(dirname($filename), $this->configuration->resolvePath('templates')));
+        $this->twig = new \Twig_Environment($loader, array('cache' => $cache));
+        return true;
+    }
 
     /**
      * Return the internal translator object used by this template.
@@ -65,14 +82,121 @@ class SimpleSAML_XHTML_Template
         return $this->translator;
     }
 
+    /**
+     * Generate languagebar
+     */
+    private function generateLanguageBar()
+    {
+        $languages = $this->translator->getLanguage()->getLanguageList();
+        $langmap = NULL;
+        if ( count($languages) > 1 ) {
+            $langnames = array(
+                'no' => 'BokmĂĄl', // Norwegian BokmĂĄl
+                'nn' => 'Nynorsk', // Norwegian Nynorsk
+                'se' => 'Sámegiella', // Northern Sami
+                'sam' => 'Ă…arjelh-saemien giele', // Southern Sami
+                'da' => 'Dansk', // Danish
+                'en' => 'English',
+                'de' => 'Deutsch', // German
+                'sv' => 'Svenska', // Swedish
+                'fi' => 'Suomeksi', // Finnish
+                'es' => 'Español', // Spanish
+                'fr' => 'Français', // French
+                'it' => 'Italiano', // Italian
+                'nl' => 'Nederlands', // Dutch
+                'lb' => 'LĂ«tzebuergesch', // Luxembourgish
+                'cs' => 'Čeština', // Czech
+                'sl' => 'Slovenščina', // Slovensk
+                'lt' => 'LietuviĹł kalba', // Lithuanian
+                'hr' => 'Hrvatski', // Croatian
+                'hu' => 'Magyar', // Hungarian
+                'pl' => 'Język polski', // Polish
+                'pt' => 'PortuguĂŞs', // Portuguese
+                'pt-br' => 'PortuguĂŞs brasileiro', // Portuguese
+                'ru' => 'русский язык', // Russian
+                'et' => 'eesti keel', // Estonian
+                'tr' => 'Türkçe', // Turkish
+                'el' => 'ελληνικά', // Greek
+                'ja' => '日本語', // Japanese
+                'zh' => '简体中文', // Chinese (simplified)
+                'zh-tw' => '繁體中文', // Chinese (traditional)
+                'ar' => 'العربية', // Arabic
+                'fa' => 'پارسی', // Persian
+                'ur' => 'اردو', // Urdu
+                'he' => 'עִבְרִית', // Hebrew
+                'id' => 'Bahasa Indonesia', // Indonesian
+                'sr' => 'Srpski', // Serbian
+                'lv' => 'Latviešu', // Latvian
+                'ro' => 'Românește', // Romanian
+                'eu' => 'Euskara', // Basque
+            );
+            $parameterName = $this->getTranslator()->getLanguage()->getLanguageParameterName();
+            $langmap = array();
+            foreach ($languages AS $lang => $current) {
+                $lang = strtolower($lang);
+                $langname = $langnames[$lang];
+                $url = false;
+                if (!$current) {
+                    $url = htmlspecialchars(\SimpleSAML\Utils\HTTP::addURLParameters('', array($parameterName => $lang)));
+                }
+                $langmap[$langname] = $url;
+            }
+        }
+        return $langmap;
+    }
+
+    /**
+     * Set some default context
+     */
+    private function twigDefaultContext()
+    {
+        $this->data['currentLanguage'] = $this->translator->getLanguage()->getLanguage();
+        // show language bar by default
+        if (!isset($this->data['hideLanguageBar'])) {
+            $this->data['hideLanguageBar'] = false;
+        }
+        // get languagebar
+        $this->data['languageBar'] = NULL;
+        if ($this->data['hideLanguageBar'] === false) {
+            $languageBar = $this->generateLanguageBar();
+            if (is_null($languageBar)) {
+                $this->data['hideLanguageBar'] = true;
+            } else {
+                $this->data['languageBar'] = $languageBar;
+            }
+        }
+
+        // assure that there is a <title> and <h1>
+        if (isset($this->data['header']) && !isset($this->data['pagetitle'])) {
+            $this->data['pagetitle'] = $this->data['header'];
+        }
+        if (!isset($this->data['pagetitle'])) {
+            $this->data['pagetitle'] = 'SimpleSAMLphp';
+        }
+
+        // set RTL
+        $this->data['isRTL'] = false;
+        if ($this->translator->getLanguage()->isLanguageRTL())
+        {
+            $this->data['isRTL'] = true;
+        }
+    }
+
 
     /**
      * Show the template to the user.
      */
     public function show()
     {
-        $filename = $this->findTemplatePath($this->template);
-        require($filename);
+        if ($this->useTwig) {
+            $this->twigDefaultContext();
+            echo $this->twig->render($this->template, $this->data);
+        }
+        else
+        {
+            $filename = $this->findTemplatePath($this->template);
+            require($filename);
+        }
     }
 
 
@@ -91,7 +215,7 @@ class SimpleSAML_XHTML_Template
      *
      * @throws Exception If the template file couldn't be found.
      */
-    private function findTemplatePath($template)
+    private function findTemplatePath($template, $throw_exception=true)
     {
         assert('is_string($template)');
 
@@ -117,11 +241,11 @@ class SimpleSAML_XHTML_Template
         if ($themeModule !== null) {
             // .../module/<themeModule>/themes/<themeName>/<templateModule>/<templateName>
 
-            $filename = SimpleSAML_Module::getModuleDir($themeModule).
+            $filename = \SimpleSAML\Module::getModuleDir($themeModule).
                 '/themes/'.$themeName.'/'.$templateModule.'/'.$templateName;
         } elseif ($templateModule !== 'default') {
             // .../module/<templateModule>/templates/<themeName>/<templateName>
-            $filename = SimpleSAML_Module::getModuleDir($templateModule).'/templates/'.$templateName;
+            $filename = \SimpleSAML\Module::getModuleDir($templateModule).'/templates/'.$templateName;
         } else {
             // .../templates/<theme>/<templateName>
             $filename = $this->configuration->getPathValue('templatedir', 'templates/').$templateName;
@@ -132,7 +256,7 @@ class SimpleSAML_XHTML_Template
         }
 
         // not found in current theme
-        SimpleSAML_Logger::debug(
+        \SimpleSAML_Logger::debug(
             $_SERVER['PHP_SELF'].' - Template: Could not find template file ['. $template.'] at ['.
             $filename.'] - now trying the base template'
         );
@@ -140,7 +264,7 @@ class SimpleSAML_XHTML_Template
         // try default theme
         if ($templateModule !== 'default') {
             // .../module/<templateModule>/templates/<templateName>
-            $filename = SimpleSAML_Module::getModuleDir($templateModule).'/templates/'.$templateName;
+            $filename = \SimpleSAML\Module::getModuleDir($templateModule).'/templates/'.$templateName;
         } else {
             // .../templates/<templateName>
             $filename = $this->configuration->getPathValue('templatedir', 'templates/').'/'.$templateName;
@@ -150,11 +274,19 @@ class SimpleSAML_XHTML_Template
             return $filename;
         }
 
-        // not found in default template - log error and throw exception
-        $error = 'Template: Could not find template file ['.$template.'] at ['.$filename.']';
-        SimpleSAML_Logger::critical($_SERVER['PHP_SELF'].' - '.$error);
+        // not found in default template
+        if ($throw_exception) {
+            // log error and throw exception
+            $error = 'Template: Could not find template file ['.$template.'] at ['.$filename.']';
+            \SimpleSAML_Logger::critical($_SERVER['PHP_SELF'].' - '.$error);
 
-        throw new Exception($error);
+            throw new Exception($error);
+        }
+        else
+        {
+            // missing template expected, return NULL
+            return NULL;
+        }
     }
 
 
@@ -241,10 +373,10 @@ class SimpleSAML_XHTML_Template
 
 
     /**
-     * Temporary wrapper for SimpleSAML\Locale\Translate::getPreferredTranslation().
+     * Temporary wrapper for \SimpleSAML\Locale\Translate::getPreferredTranslation().
      *
      * @deprecated This method will be removed in SSP 2.0. Please use
-     * SimpleSAML\Locale\Translate::getPreferredTranslation() instead.
+     * \SimpleSAML\Locale\Translate::getPreferredTranslation() instead.
      */
     public function getTranslation($translations)
     {
diff --git a/templates/_footer.twig.html b/templates/_footer.twig.html
new file mode 100644
index 000000000..c1edf5214
--- /dev/null
+++ b/templates/_footer.twig.html
@@ -0,0 +1,6 @@
+    <hr>
+
+    <img src="/{{ baseurlpath }}resources/icons/ssplogo-fish-small.png" alt="Small fish logo" style="float: right">
+    Copyright © 2007-2015 <a href="http://uninett.no/">UNINETT AS</a>
+
+    <br style="clear: right">
diff --git a/templates/_header.twig.html b/templates/_header.twig.html
new file mode 100644
index 000000000..a97cde065
--- /dev/null
+++ b/templates/_header.twig.html
@@ -0,0 +1,12 @@
+    <div id="header">
+        <h1><a style="text-decoration: none; color: white" href="/{{ baseurlpath }}">{{ pagetitle }}</a></h1>
+    </div>
+
+    {% if not hideLanguageBar %}
+    <div id="languagebar">
+        {% for language, param in languageBar %}
+        {% if not loop.first %}|{% endif %}
+        {% if param %}<a href="{{ param }}">{{ language }}</a>{% else %}{{ language }}{% endif %}
+        {% endfor %}
+    </div>
+    {% endif %}
diff --git a/templates/base.twig.html b/templates/base.twig.html
new file mode 100644
index 000000000..ad30a6335
--- /dev/null
+++ b/templates/base.twig.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+    <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0">
+    <script type="text/javascript" src="/{{ baseurlpath }}resources/script.js"></script>
+    <title>{{ pagetitle }}</title>
+    <link rel="stylesheet" type="text/css" href="/{{ baseurlpath }}resources/default.css">
+    <link rel="icon" type="image/icon" href="/{{ baseurlpath }}resources/icons/favicon.ico">
+    <link rel="stylesheet" media="screen" type="text/css" href="/{{ baseurlpath }}resources/uitheme1.8/jquery-ui.css">
+    {% if isRTL %}<link rel="stylesheet" type="text/css" href="/{{ baseurlpath }}resources/default-rtl.css" />{% endif %}
+    <meta name="robots" content="noindex, nofollow">
+    {% block preload %}{% endblock %}
+</head>
+<body>
+    <div id="wrap">
+
+        {% block header %}{% include "_header.twig.html" %}{% endblock %}
+
+        <div id="content">
+            {% block content %}{% endblock %}
+        </div><!-- #content -->
+
+        <div id="footer">
+            {% block footer %}{% include "_footer.twig.html" %}{% endblock %}
+        </div>
+
+    </div><!-- #wrap -->
+
+    {% block postload %}{% endblock %}
+</body></html>
diff --git a/templates/index.twig.html b/templates/index.twig.html
new file mode 100644
index 000000000..9e17fcb12
--- /dev/null
+++ b/templates/index.twig.html
@@ -0,0 +1,32 @@
+{% extends "base.twig.html" %}
+{% block content %}
+    <div id="portalmenu" class="ui-tabs ui-widget ui-widget-content ui-corner-all">
+        <ul class="tabset_tabs ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all">
+            <li class="ui-state-default ui-corner-top"><a href="http://simplesaml.arrakis.uninett.no/simplesaml/module.php/core/frontpage_welcome.php">Welcome</a></li>
+            <li class="ui-state-default ui-corner-top ui-tabs-selected ui-state-active"><a href="#">Configuration</a></li>
+            <li class="ui-state-default ui-corner-top"><a href="http://simplesaml.arrakis.uninett.no/simplesaml/module.php/core/frontpage_auth.php">Authentication</a></li>
+            <li class="ui-state-default ui-corner-top"><a href="http://simplesaml.arrakis.uninett.no/simplesaml/module.php/core/frontpage_federation.php">Federation</a></li>
+        </ul>
+        <div id="portalcontent" class="ui-tabs-panel ui-widget-content ui-corner-bottom">
+
+        <div style="clear: both" class="enablebox mini">
+            <table>
+
+                <tr class="disabled"><td>SAML 2.0 IdP</td>
+                    <td><img src="/{{ baseurlpath }}resources/icons/silk/delete.png" alt="disabled" /></td></tr>
+
+                <tr class="disabled"><td>Shib 1.3 IdP</td>
+                    <td><img src="/{{ baseurlpath }}resources/icons/silk/delete.png" alt="disabled" /></td></tr>
+
+            </table>
+        </div>
+        <h2>Configuration</h2>
+        <ul>
+            {% for url, page in adminpages %}
+            <li></li>
+            <a href="{{ url }}">{{ page }}</li>
+            {% endfor %}
+        </ul>
+        </div>
+    </div>
+{% endblock content %}
diff --git a/templates/sandbox.twig.html b/templates/sandbox.twig.html
new file mode 100644
index 000000000..e37201e0c
--- /dev/null
+++ b/templates/sandbox.twig.html
@@ -0,0 +1,6 @@
+{% extends "base.twig.html" %}
+{% block content %}
+    <p>This page exists as a sandbox to play with twig without affecting anything else. The template is in ./templates.</p>
+    <p>{{ sometext }}</p>
+    <p>Current locale set: {{ currentLanguage }}</p>
+{% endblock content %}
diff --git a/www/admin/index.php b/www/admin/index.php
new file mode 100644
index 000000000..a1f9558e1
--- /dev/null
+++ b/www/admin/index.php
@@ -0,0 +1,27 @@
+<?php
+
+require_once('../_include.php');
+
+// Load SimpleSAMLphp, configuration
+$config = SimpleSAML_Configuration::getInstance();
+$session = SimpleSAML_Session::getSessionFromRequest();
+
+// Check if valid local session exists..
+//SimpleSAML\Utils\Auth::requireAdmin();
+
+$adminpages = array(
+    'hostnames.php' => 'Diagnostics on hostname, port and protocol',
+    'phpinfo.php' => 'PHP info',
+    '../module.php/sanitycheck/index.php' => 'Sanity check of your SimpleSAMLphp setup',
+    'sandbox.php' => 'Sandbox for testing changes to layout and css',
+);
+
+$template = new SimpleSAML_XHTML_Template($config, 'index.php');
+
+$template->data['pagetitle'] = 'Admin';
+$template->data['adminpages'] = $adminpages;
+$template->data['remaining']  = $session->getAuthData('admin', 'Expire') - time();
+$template->data['valid'] = 'na';
+$template->data['logout'] = null;
+
+$template->show();
diff --git a/www/admin/sandbox.php b/www/admin/sandbox.php
new file mode 100644
index 000000000..ec77569cf
--- /dev/null
+++ b/www/admin/sandbox.php
@@ -0,0 +1,19 @@
+<?php
+
+require_once('../_include.php');
+
+// Load SimpleSAMLphp, configuration
+$config = SimpleSAML_Configuration::getInstance();
+$session = SimpleSAML_Session::getSessionFromRequest();
+
+// Check if valid local session exists..
+//SimpleSAML\Utils\Auth::requireAdmin();
+
+$template = new SimpleSAML_XHTML_Template($config, 'sandbox.php');
+
+$template->data['pagetitle'] = 'Sandbox';
+$template->data['sometext'] = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur.';
+$template->data['remaining']  = $session->getAuthData('admin', 'Expire') - time();
+$template->data['logout'] = null;
+
+$template->show();
-- 
GitLab