Objectify locale negotiator and template files, add documentation
This commit is contained in:
parent
9820686776
commit
61f563c9b0
7
404.php
7
404.php
|
@ -1,12 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
require("config.php");
|
require("config.php");
|
||||||
require("header.php");
|
require("template.php");
|
||||||
require("footer.php");
|
Template::render_header("Page not found");
|
||||||
render_header("Page not found");
|
|
||||||
?>
|
?>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<h1><?php echo _("Page Not Found");?></h1>
|
<h1><?php echo _("Page Not Found");?></h1>
|
||||||
<p><?php echo _("Sorry, but the page you were trying to view does not exist.");?></p>
|
<p><?php echo _("Sorry, but the page you were trying to view does not exist.");?></p>
|
||||||
</div>
|
</div>
|
||||||
<?php
|
<?php
|
||||||
render_footer();
|
Template::render_footer();
|
|
@ -19,7 +19,7 @@ if (isset($_GET['delete']))
|
||||||
Incident::delete($_GET['delete']);
|
Incident::delete($_GET['delete']);
|
||||||
}
|
}
|
||||||
|
|
||||||
render_header(_("Dashboard"), true);
|
Template::render_header(_("Dashboard"), true);
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
session_start();
|
session_start();
|
||||||
require("../config.php");
|
require("../config.php");
|
||||||
require("../classes/constellation.php");
|
require("../classes/constellation.php");
|
||||||
require("../header.php");
|
require("../template.php");
|
||||||
require("../footer.php");
|
|
||||||
|
|
||||||
if(isset($_COOKIE['user'])&&!isset($_SESSION['user']))
|
if(isset($_COOKIE['user'])&&!isset($_SESSION['user']))
|
||||||
{
|
{
|
||||||
|
@ -66,5 +65,5 @@ else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
render_footer(true);
|
Template::render_footer(true);
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
render_header(_("Login"));
|
Template::render_header(_("Login"));
|
||||||
?>
|
?>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<h1><?php echo _("Login");?></h1>
|
<h1><?php echo _("Login");?></h1>
|
||||||
|
@ -29,4 +29,4 @@ render_header(_("Login"));
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<?php
|
<?php
|
||||||
render_footer();
|
Template::render_footer();
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
render_header(_("Lost password"));
|
Template::render_header(_("Lost password"));
|
||||||
?>
|
?>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<h1><?php echo _("Lost password");?></h1>
|
<h1><?php echo _("Lost password");?></h1>
|
||||||
|
@ -69,4 +69,4 @@ render_header(_("Lost password"));
|
||||||
<?php }?>
|
<?php }?>
|
||||||
</div>
|
</div>
|
||||||
<?php
|
<?php
|
||||||
render_footer();
|
Template::render_footer();
|
|
@ -4,7 +4,7 @@ if (isset($_GET['new']))
|
||||||
User::add();
|
User::add();
|
||||||
}
|
}
|
||||||
|
|
||||||
render_header(_("New user"), true); ?>
|
Template::render_header(_("New user"), true); ?>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<h2>Add new user</h2>
|
<h2>Add new user</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -9,7 +9,7 @@ if (isset($_GET['delete']))
|
||||||
Service::delete();
|
Service::delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
render_header(_("Settings"), true);
|
Template::render_header(_("Settings"), true);
|
||||||
?>
|
?>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<h2>Settings</h2>
|
<h2>Settings</h2>
|
||||||
|
|
|
@ -32,7 +32,7 @@ if (isset($_GET['what']) && $_GET['what']=='toggle')
|
||||||
$displayed_user->toggle();
|
$displayed_user->toggle();
|
||||||
}
|
}
|
||||||
|
|
||||||
render_header(_("User"), true);
|
Template::render_header(_("User"), true);
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
|
|
|
@ -10,6 +10,13 @@ require(__DIR__ . "/token.php");
|
||||||
class Constellation
|
class Constellation
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders incidents matching specified constraints.
|
||||||
|
* @param Boolean $future - specifies whether to render old or upcoming incidents
|
||||||
|
* @param int $offset - specifies offset - used for pagination
|
||||||
|
* @param int $limit - limits the number of incidents rendered
|
||||||
|
* @param Boolean $admin - specifies whether to render admin controls
|
||||||
|
*/
|
||||||
public function render_incidents($future=false, $offset=0, $limit = 5, $admin = 0){
|
public function render_incidents($future=false, $offset=0, $limit = 5, $admin = 0){
|
||||||
global $mysqli;
|
global $mysqli;
|
||||||
if ($offset<0)
|
if ($offset<0)
|
||||||
|
@ -57,6 +64,11 @@ class Constellation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders service status - in admin page it returns array so it can be processed further.
|
||||||
|
* @param boolean $admin
|
||||||
|
* @return array of services
|
||||||
|
*/
|
||||||
public function render_status($admin = 0){
|
public function render_status($admin = 0){
|
||||||
global $mysqli;
|
global $mysqli;
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,13 @@ class Incident
|
||||||
private $title;
|
private $title;
|
||||||
private $username;
|
private $username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs service from its data.
|
||||||
|
* @param array $data incident data
|
||||||
|
*/
|
||||||
function __construct($data)
|
function __construct($data)
|
||||||
{
|
{
|
||||||
|
//TODO: Maybe get data from id?
|
||||||
$this->id = $data['status_id'];
|
$this->id = $data['status_id'];
|
||||||
$this->date = new DateTime("@".$data['time']);
|
$this->date = new DateTime("@".$data['time']);
|
||||||
$this->date = $this->date->format('Y-m-d H:i:sP');
|
$this->date = $this->date->format('Y-m-d H:i:sP');
|
||||||
|
@ -27,7 +32,12 @@ class Incident
|
||||||
$this->username = $data['username'];
|
$this->username = $data['username'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes incident by ID.
|
||||||
|
* @param int ID
|
||||||
|
*/
|
||||||
public static function delete($id){
|
public static function delete($id){
|
||||||
|
//TODO: This should check whether it's admin or their own post...
|
||||||
global $mysqli, $message;
|
global $mysqli, $message;
|
||||||
|
|
||||||
$stmt = $mysqli->prepare("DELETE FROM services_status WHERE status_id = ?");
|
$stmt = $mysqli->prepare("DELETE FROM services_status WHERE status_id = ?");
|
||||||
|
@ -42,6 +52,12 @@ class Incident
|
||||||
header("Location: /admin");
|
header("Location: /admin");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes submitted form and adds incident unless problem is encountered,
|
||||||
|
* calling this is possible only for admin or higher rank. Also checks requirements
|
||||||
|
* for char limits.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public static function add()
|
public static function add()
|
||||||
{
|
{
|
||||||
global $mysqli, $message;
|
global $mysqli, $message;
|
||||||
|
@ -120,6 +136,12 @@ class Incident
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders incident
|
||||||
|
* @param Boolean $admin - decides whether admin controls should be rendered
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function render($admin=0){
|
public function render($admin=0){
|
||||||
global $icons;
|
global $icons;
|
||||||
global $classes, $user;
|
global $classes, $user;
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This class is used to negotiate language displayed to user.
|
||||||
|
* Reads browser preferences and chooses the best language from list
|
||||||
|
*/
|
||||||
|
class LocaleNegotiator
|
||||||
|
{
|
||||||
|
private $accepted_langs = [];
|
||||||
|
private $default_language;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method scans for languages and creates a list of language and its name (localized ofc.)
|
||||||
|
* @param String $default_language language displayed to user in case no suitable lang is found
|
||||||
|
*/
|
||||||
|
function __construct($default_language)
|
||||||
|
{
|
||||||
|
$tmp = glob(__DIR__ . '/locale/*' , GLOB_ONLYDIR);
|
||||||
|
$this->default_language = $default_language;
|
||||||
|
//Works only if the server supports the locale
|
||||||
|
//This basically means $accepted_langs[<lang_code>] = "<lang name>";
|
||||||
|
foreach ($accepted_langs as $key => $value) {
|
||||||
|
$this->accepted_langs[basename($value)] = self::mb_ucfirst(locale_get_display_language($lang, $lang));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns list of accepted langs so it can be reused for rendering language list for switching...
|
||||||
|
*/
|
||||||
|
public function get_accepted_langs(){
|
||||||
|
return $this->accepted_langs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This methid does ucfirst() on multibyte encodings like UTF-8 - good for edge cases when locale starts with Č or similar.
|
||||||
|
* @param String $string string
|
||||||
|
* @return String string with first char uppercase
|
||||||
|
*/
|
||||||
|
private static function mb_ucfirst($string)
|
||||||
|
{
|
||||||
|
return mb_strtoupper(mb_substr($string, 0, 1)).mb_strtolower(mb_substr($string, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method does the actual negotiation. It has override parameter in case user wants to switch
|
||||||
|
* languages.
|
||||||
|
* @param String $override adds language to list of preffered languages with highest priority
|
||||||
|
* @return String language code that matched best with browser preferences
|
||||||
|
*/
|
||||||
|
public function negotiate($override = null){
|
||||||
|
$langs = [];
|
||||||
|
|
||||||
|
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
|
||||||
|
preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $lang_parse);
|
||||||
|
|
||||||
|
if (count($lang_parse[1])) {
|
||||||
|
$langs = array_combine($lang_parse[1], $lang_parse[4]);
|
||||||
|
|
||||||
|
foreach ($langs as $lang => $val) {
|
||||||
|
//If browser didn't send quality of language, it is 1 by default
|
||||||
|
if ($val === '') $langs[$lang] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($override))
|
||||||
|
{
|
||||||
|
//More important than the best lang of browser
|
||||||
|
$langs[$override] = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
arsort($langs, SORT_NUMERIC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//So we have lang code as value
|
||||||
|
$langs = array_flip($langs);
|
||||||
|
//False unless we set it, so we know to set default locale
|
||||||
|
$best_match = false;
|
||||||
|
//So we have also lang code as value
|
||||||
|
$accepted_langs = array_flip($this->accepted_langs);
|
||||||
|
foreach ($langs as $lang) {
|
||||||
|
if (strlen($lang)>2){
|
||||||
|
if (in_array($lang, $accepted_langs)){
|
||||||
|
$best_match = $lang;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
$possible = array_filter($accepted_langs, function($key) {
|
||||||
|
global $lang;
|
||||||
|
return strpos($key, $lang) === 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (count($possible)){
|
||||||
|
$best_match = $possible[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($best_match === false){
|
||||||
|
$best_match = $this->default_language;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $best_match;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Class for creating and rendering an incident
|
* Class for managing services
|
||||||
*/
|
*/
|
||||||
class Service
|
class Service
|
||||||
{
|
{
|
||||||
|
@ -8,28 +8,53 @@ class Service
|
||||||
private $name;
|
private $name;
|
||||||
private $status;
|
private $status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs service from its data.
|
||||||
|
* @param int $id service ID
|
||||||
|
* @param String $name service name
|
||||||
|
* @param int $status current service status
|
||||||
|
*/
|
||||||
function __construct($id, $name, $status=3)
|
function __construct($id, $name, $status=3)
|
||||||
{
|
{
|
||||||
|
//TODO: Maybe get data from ID?
|
||||||
$this->id = $id;
|
$this->id = $id;
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
$this->status = $status;
|
$this->status = $status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns status of this service
|
||||||
|
* @return int status
|
||||||
|
*/
|
||||||
public function get_status()
|
public function get_status()
|
||||||
{
|
{
|
||||||
return $this->status;
|
return $this->status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns id of this service
|
||||||
|
* @return int id
|
||||||
|
*/
|
||||||
public function get_id()
|
public function get_id()
|
||||||
{
|
{
|
||||||
return $this->id;
|
return $this->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns name of this service
|
||||||
|
* @return String name
|
||||||
|
*/
|
||||||
public function get_name()
|
public function get_name()
|
||||||
{
|
{
|
||||||
return $this->name;
|
return $this->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes submitted form and adds service unless problem is encountered,
|
||||||
|
* calling this is possible only for admin or higher rank. Also checks requirements
|
||||||
|
* for char limits.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public static function add()
|
public static function add()
|
||||||
{
|
{
|
||||||
global $user, $message;
|
global $user, $message;
|
||||||
|
@ -57,6 +82,10 @@ class Service
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes this service - first checks if user has permission to do that.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public static function delete()
|
public static function delete()
|
||||||
{
|
{
|
||||||
global $user;
|
global $user;
|
||||||
|
@ -95,6 +124,11 @@ class Service
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders current status for services from passed array of services.
|
||||||
|
* @param Service[] $array array of services
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public static function current_status($array){
|
public static function current_status($array){
|
||||||
global $all, $some, $classes;
|
global $all, $some, $classes;
|
||||||
$statuses = array(0,0,0,0);
|
$statuses = array(0,0,0,0);
|
||||||
|
@ -118,6 +152,10 @@ class Service
|
||||||
echo '</div>';
|
echo '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders this service.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function render(){
|
public function render(){
|
||||||
global $statuses;
|
global $statuses;
|
||||||
global $classes;
|
global $classes;
|
||||||
|
|
|
@ -4,6 +4,13 @@
|
||||||
*/
|
*/
|
||||||
class Token
|
class Token
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Generates a new token from user id and randomly generated salt.
|
||||||
|
* @param int $user ID
|
||||||
|
* @param String $data associated with token that are important
|
||||||
|
* @param timestamp $expire expiration time
|
||||||
|
* @return String token
|
||||||
|
*/
|
||||||
public static function new($id, $data, $expire)
|
public static function new($id, $data, $expire)
|
||||||
{
|
{
|
||||||
global $mysqli;
|
global $mysqli;
|
||||||
|
@ -16,6 +23,13 @@ class Token
|
||||||
return $token;
|
return $token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether token exists in the database and has not expired.
|
||||||
|
* @param String $token
|
||||||
|
* @param int $id user ID
|
||||||
|
* @param String $data
|
||||||
|
* @return int count of results in database
|
||||||
|
*/
|
||||||
public static function validate_token($token, $id, $data)
|
public static function validate_token($token, $id, $data)
|
||||||
{
|
{
|
||||||
global $mysqli;
|
global $mysqli;
|
||||||
|
@ -27,6 +41,11 @@ class Token
|
||||||
return $query->fetch_assoc()['count'];
|
return $query->fetch_assoc()['count'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes token.
|
||||||
|
* @param String $token
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public static function delete($token)
|
public static function delete($token)
|
||||||
{
|
{
|
||||||
global $mysqli;
|
global $mysqli;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Class for creating and rendering an incident
|
* Class that encapsulates everything that can be done with a user
|
||||||
*/
|
*/
|
||||||
class User
|
class User
|
||||||
{
|
{
|
||||||
|
@ -12,6 +12,10 @@ class User
|
||||||
private $rank;
|
private $rank;
|
||||||
private $active;
|
private $active;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets user data from database and creates the class
|
||||||
|
* @param int $id user ID
|
||||||
|
*/
|
||||||
function __construct($id)
|
function __construct($id)
|
||||||
{
|
{
|
||||||
global $mysqli;
|
global $mysqli;
|
||||||
|
@ -36,26 +40,47 @@ class User
|
||||||
$this->rank = $result['permission'];
|
$this->rank = $result['permission'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns username of this user
|
||||||
|
* @return String username
|
||||||
|
*/
|
||||||
public function get_username()
|
public function get_username()
|
||||||
{
|
{
|
||||||
return $this->username;
|
return $this->username;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this user is active
|
||||||
|
* @return Boolean user active status
|
||||||
|
*/
|
||||||
public function is_active()
|
public function is_active()
|
||||||
{
|
{
|
||||||
return $this->active;
|
return $this->active;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns rank of this user
|
||||||
|
* @return int rank
|
||||||
|
*/
|
||||||
public function get_rank()
|
public function get_rank()
|
||||||
{
|
{
|
||||||
return $this->rank;
|
return $this->rank;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns full name of this user
|
||||||
|
* @return String name in "Name Surname" format
|
||||||
|
*/
|
||||||
public function get_name()
|
public function get_name()
|
||||||
{
|
{
|
||||||
return $this->name . " " . $this->surname;
|
return $this->name . " " . $this->surname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles active status of this user. First checks if the user
|
||||||
|
* making the change has permission to do that.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function toggle()
|
public function toggle()
|
||||||
{
|
{
|
||||||
global $mysqli, $message, $user;
|
global $mysqli, $message, $user;
|
||||||
|
@ -78,6 +103,13 @@ class User
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes submitted form and adds user unless problem is encountered,
|
||||||
|
* calling this is possible only for Superadmin (other ranks cannot add users)
|
||||||
|
* or when the installation script is being run. Also checks requirements
|
||||||
|
* for username and email being unique and char limits.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public static function add()
|
public static function add()
|
||||||
{
|
{
|
||||||
global $user, $message, $mysqli;
|
global $user, $message, $mysqli;
|
||||||
|
@ -146,6 +178,13 @@ class User
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes submitted form and logs user in, unless the user is deactivated or wrong
|
||||||
|
* password or email has been submitted. The script doesn't let anyone know which
|
||||||
|
* field was wrong as it is not possible to verify email address from outside admin panel,
|
||||||
|
* so this actually helps with security :)
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public static function login()
|
public static function login()
|
||||||
{
|
{
|
||||||
global $message, $mysqli;
|
global $message, $mysqli;
|
||||||
|
@ -200,6 +239,12 @@ class User
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether token is valid (this means is in database and associated
|
||||||
|
* with the user) and sets session data if it is, so user remains logged in.
|
||||||
|
* The script deletes the token either way.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public static function restore_session()
|
public static function restore_session()
|
||||||
{
|
{
|
||||||
global $mysqli, $message;
|
global $mysqli, $message;
|
||||||
|
@ -225,7 +270,10 @@ class User
|
||||||
|
|
||||||
Token::delete($token);
|
Token::delete($token);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Renders settings for this user so it can be displayed in admin panel.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function render_user_settings()
|
public function render_user_settings()
|
||||||
{
|
{
|
||||||
global $permissions, $user;
|
global $permissions, $user;
|
||||||
|
@ -307,7 +355,12 @@ class User
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes user password and deletes all remember tokens so all other sessions
|
||||||
|
* won't stay logged in without knowing new pass. Uses token when reseting password.
|
||||||
|
* @param String $token
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function change_password($token = false)
|
public function change_password($token = false)
|
||||||
{
|
{
|
||||||
global $mysqli, $user, $message;
|
global $mysqli, $user, $message;
|
||||||
|
@ -344,6 +397,10 @@ class User
|
||||||
$stmt->bind_param("si", $hash, $id);
|
$stmt->bind_param("si", $hash, $id);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
$stmt->close();
|
$stmt->close();
|
||||||
|
$stmt = $mysqli->prepare("DELETE FROM tokens WHERE user = ? AND data = 'remember'");
|
||||||
|
$stmt->bind_param("d", $id);
|
||||||
|
$stmt->execute();
|
||||||
|
$query = $stmt->get_result();
|
||||||
User::logout();
|
User::logout();
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
@ -366,6 +423,10 @@ class User
|
||||||
$stmt->bind_param("si", $hash,$id);
|
$stmt->bind_param("si", $hash,$id);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
$stmt->close();
|
$stmt->close();
|
||||||
|
$stmt = $mysqli->prepare("DELETE FROM tokens WHERE user = ? AND data = 'remember'");
|
||||||
|
$stmt->bind_param("d", $id);
|
||||||
|
$stmt->execute();
|
||||||
|
$query = $stmt->get_result();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -377,6 +438,10 @@ class User
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends email with link for password reset, link is token protected and valid only once.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public static function password_link()
|
public static function password_link()
|
||||||
{
|
{
|
||||||
global $mysqli;
|
global $mysqli;
|
||||||
|
@ -405,6 +470,10 @@ class User
|
||||||
mail($to, $subject, $msg, $headers);
|
mail($to, $subject, $msg, $headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends email with link for email change confirmation (security reasons), link is token protected and valid only once.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function email_link(){
|
public function email_link(){
|
||||||
global $mysqli;
|
global $mysqli;
|
||||||
$email = $_POST['email'];
|
$email = $_POST['email'];
|
||||||
|
@ -426,9 +495,12 @@ class User
|
||||||
mail($to, $subject, $msg, $headers);
|
mail($to, $subject, $msg, $headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes email.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function change_email()
|
public function change_email()
|
||||||
{
|
{
|
||||||
//TODO: Get message from this somehow
|
|
||||||
global $mysqli, $message;
|
global $mysqli, $message;
|
||||||
$time = time();
|
$time = time();
|
||||||
$token = $_GET['token'];
|
$token = $_GET['token'];
|
||||||
|
@ -456,6 +528,10 @@ class User
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs current user out.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public static function logout(){
|
public static function logout(){
|
||||||
global $mysqli;
|
global $mysqli;
|
||||||
session_unset();
|
session_unset();
|
||||||
|
@ -469,6 +545,10 @@ class User
|
||||||
header("Location: /admin");
|
header("Location: /admin");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes permissions of current user - only super admin can do this, so it checks permission first.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function change_permission(){
|
public function change_permission(){
|
||||||
global $mysqli, $message, $user;
|
global $mysqli, $message, $user;
|
||||||
if ($user->get_rank()==0)
|
if ($user->get_rank()==0)
|
||||||
|
|
|
@ -9,13 +9,27 @@ define("MAILER_ADDRESS", "##mailer_email##"); //Mailer address
|
||||||
define("INSTALL_OVERRIDE", false);
|
define("INSTALL_OVERRIDE", false);
|
||||||
define("DEFAULT_LANGUAGE", "en_GB");
|
define("DEFAULT_LANGUAGE", "en_GB");
|
||||||
|
|
||||||
require("locale.php");
|
require("classes/locale-negotiator.php");
|
||||||
|
|
||||||
|
if (!isset($_SESSION['locale'])||isset($_GET['lang']))
|
||||||
|
{
|
||||||
|
$override = ((isset($_GET['lang']))?$_GET['lang']:null);
|
||||||
|
$negotiator = new LocaleNegotiator(DEFAULT_LANGUAGE);
|
||||||
|
$best_match = $negotiator->negotiate($override);
|
||||||
|
$_SESSION['locale'] = $best_match;
|
||||||
|
setlocale(LC_ALL, $_SESSION['locale'].".UTF-8");
|
||||||
|
|
||||||
|
bindtextdomain("server-status", __DIR__ . "/locale/");
|
||||||
|
bind_textdomain_codeset($_SESSION['locale'], "utf-8");
|
||||||
|
textdomain("server-status");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//Database connection
|
//Database connection
|
||||||
$mysqli = new mysqli("##server##","##user##","##password##","##database##");
|
$mysqli = new mysqli("##server##","##user##","##password##","##database##");
|
||||||
|
|
||||||
if ($mysqli->connect_errno) {
|
if ($mysqli->connect_errno) {
|
||||||
printf("Connection failed: %s\n", $mysqli->connect_error);
|
printf(_("Connection failed: %s\n"), $mysqli->connect_error);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
45
footer.php
45
footer.php
|
@ -1,45 +0,0 @@
|
||||||
<?php
|
|
||||||
function render_footer($admin = false)
|
|
||||||
{
|
|
||||||
global $lang_names;
|
|
||||||
?>
|
|
||||||
</div>
|
|
||||||
<div id="footerwrap">
|
|
||||||
<div class="container">
|
|
||||||
<div class="row centered">
|
|
||||||
<div class="col-md-4 text-left">Copyright © <?php echo date("Y");?> Vojtěch Sajdl</div>
|
|
||||||
<div class="col-md-4 text-center">
|
|
||||||
<div class="btn-group dropup">
|
|
||||||
<button type="button" class="btn btn-primary"><?php echo '<img src="'.WEB_URL.'/locale/'.$_SESSION['locale'].'/flag.png" alt="'.$lang_names[$_SESSION['locale']].'">'.$lang_names[$_SESSION['locale']];?></button>
|
|
||||||
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<span class="caret"></span>
|
|
||||||
<span class="sr-only"><?php echo _("Toggle Dropdown");?></span>
|
|
||||||
</button>
|
|
||||||
<ul class="dropdown-menu">
|
|
||||||
<?php
|
|
||||||
foreach ($lang_names as $key => $value) {
|
|
||||||
echo '<a href="?lang='.$key.'"><img src="'.WEB_URL.'/locale/'.$key.'/flag.png" alt="'.$value.'">'.$value.'</a>';
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<hr role="separator" class="divider">
|
|
||||||
<a href="https://poeditor.com/join/project/37SpmJtyOm"><?php echo _("Help with translation!");?></a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4 text-right"><a href="https://github.com/Pryx/server-status/" target="_blank"><i class="fa fa-github" aria-hidden="true"></i></a></div>
|
|
||||||
</div><!--/row -->
|
|
||||||
</div><!--/container -->
|
|
||||||
</div>
|
|
||||||
<script src="/js/vendor/jquery-1.11.2.min.js"></script>
|
|
||||||
<script src="/js/vendor/jquery.timeago.js"></script>
|
|
||||||
<?php if ($admin){?>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
|
|
||||||
<script src="/js/admin.js"></script>
|
|
||||||
<script src="/js/vendor/jquery.growl.js"></script>
|
|
||||||
<? }?>
|
|
||||||
<script src="/js/vendor/bootstrap.min.js"></script>
|
|
||||||
<script src="/js/main.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
<?
|
|
||||||
}
|
|
79
header.php
79
header.php
|
@ -1,79 +0,0 @@
|
||||||
<?php
|
|
||||||
function render_header($page_name, $admin = false){
|
|
||||||
if (!$admin)
|
|
||||||
{
|
|
||||||
?>
|
|
||||||
|
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title><?php echo $page_name." - ".NAME ?></title>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<meta name="description" content="Current service status for <?php echo NAME;?> can be found here as well as incident history.">
|
|
||||||
<link rel="shortcut icon" href="/favicon.ico" type="image/png">
|
|
||||||
<link rel="stylesheet" href="/css/bootstrap.min.css">
|
|
||||||
<link rel="stylesheet" href="/css/main.css" media="screen">
|
|
||||||
<link rel="stylesheet" href="/css/print.css" media="print">
|
|
||||||
<link href="/css/font-awesome.min.css" rel="stylesheet">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="navbar navbar-default" role="navigation">
|
|
||||||
<div class="container">
|
|
||||||
<div class="navbar-header">
|
|
||||||
<a class="navbar-brand" href="<?php echo WEB_URL;?>"><img src="/img/logo_white.png" alt="logo" class="menu-logo" width="50" height="50"></a>
|
|
||||||
</div>
|
|
||||||
<div class="navbar-left hidden-xs">
|
|
||||||
<ul class="nav navbar-nav">
|
|
||||||
<li><a href="<?php echo WEB_URL;?>/"><h1><?php echo _("Service Status");?></h1></a></li>
|
|
||||||
</ul>
|
|
||||||
</div><!--/.nav-collapse -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="wrapper" class="center">
|
|
||||||
<?php
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
global $user;
|
|
||||||
?>
|
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title><?php echo $page_name." - ".NAME ?></title>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="shortcut icon" href="/favicon.ico" type="image/png">
|
|
||||||
<link rel="stylesheet" href="/css/bootstrap.min.css">
|
|
||||||
<link rel="stylesheet" href="/css/main.css">
|
|
||||||
<link href="/css/font-awesome.min.css" rel="stylesheet">
|
|
||||||
<link href="/css/jquery.growl.css" rel="stylesheet">
|
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
|
|
||||||
</head>
|
|
||||||
<body class="admin">
|
|
||||||
<div class="navbar navbar-default" role="navigation">
|
|
||||||
<div class="container">
|
|
||||||
<div class="navbar-header">
|
|
||||||
|
|
||||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
|
||||||
<span class="sr-only"><?php echo _("Toggle navigation");?></span>
|
|
||||||
<span class="icon-bar"></span>
|
|
||||||
<span class="icon-bar"></span>
|
|
||||||
<span class="icon-bar"></span>
|
|
||||||
</button>
|
|
||||||
<a class="navbar-brand" href="<?php echo WEB_URL;?>/admin"><img src="/img/logo_white.png" alt="logo" class="menu-logo" width="50" height="50"></a>
|
|
||||||
</div>
|
|
||||||
<div class="navbar-collapse collapse navbar-right navbar-admin">
|
|
||||||
<ul class="nav navbar-nav">
|
|
||||||
<li><a href="<?php echo WEB_URL;?>/admin/"><?php echo _("Dashboard");?></a></li>
|
|
||||||
<li><a href="<?php echo WEB_URL;?>/admin/?do=user"><?php printf(_("User (%s)"), $user->get_username());?></a></li>
|
|
||||||
<li><a href="<?php echo WEB_URL;?>/admin/?do=settings"><?php echo _("Settings");?></a></li>
|
|
||||||
<li><a href="<?php echo WEB_URL;?>/admin/?do=logout"><?php echo _("Logout");?></a></li>
|
|
||||||
</ul>
|
|
||||||
</div><!--/.nav-collapse -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="wrapper" class="center admin">
|
|
||||||
<?php
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
require("header.php");
|
require("template.php");
|
||||||
require("footer.php");
|
|
||||||
|
|
||||||
if (!file_exists("config.php"))
|
if (!file_exists("config.php"))
|
||||||
{
|
{
|
||||||
|
@ -22,7 +21,7 @@ if (isset($_GET['ajax']))
|
||||||
$offset = $_GET['offset'];
|
$offset = $_GET['offset'];
|
||||||
}
|
}
|
||||||
|
|
||||||
render_header("Status");
|
Template::render_header("Status");
|
||||||
?>
|
?>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<h2><?php echo _("Current status");?></h2>
|
<h2><?php echo _("Current status");?></h2>
|
||||||
|
@ -47,5 +46,5 @@ render_header("Status");
|
||||||
</div>
|
</div>
|
||||||
<?php }
|
<?php }
|
||||||
|
|
||||||
render_footer();
|
Template::render_footer();
|
||||||
}
|
}
|
77
locale.php
77
locale.php
|
@ -1,77 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
function mb_ucfirst($string)
|
|
||||||
{
|
|
||||||
return mb_strtoupper(mb_substr($string, 0, 1)).mb_strtolower(mb_substr($string, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$accepted_langs = glob(__DIR__ . '/locale/*' , GLOB_ONLYDIR);
|
|
||||||
$lang_names = array();
|
|
||||||
foreach ($accepted_langs as $key => $value) {
|
|
||||||
$accepted_langs[$key] = basename($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($accepted_langs as $lang) {
|
|
||||||
$lang_names[$lang] = mb_ucfirst(locale_get_display_language($lang, $lang));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($_SESSION['locale'])||isset($_GET['lang']))
|
|
||||||
{
|
|
||||||
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
|
|
||||||
preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $lang_parse);
|
|
||||||
|
|
||||||
if (count($lang_parse[1])) {
|
|
||||||
$langs = array_combine($lang_parse[1], $lang_parse[4]);
|
|
||||||
|
|
||||||
foreach ($langs as $lang => $val) {
|
|
||||||
if ($val === '') $langs[$lang] = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($_GET['lang']))
|
|
||||||
{
|
|
||||||
$langs[$_GET['lang']] = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
arsort($langs, SORT_NUMERIC);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$langs = array_flip($langs);
|
|
||||||
|
|
||||||
$best_match = false;
|
|
||||||
|
|
||||||
foreach ($langs as $lang) {
|
|
||||||
if (strlen($lang)>2){
|
|
||||||
if (in_array($lang, $accepted_langs)){
|
|
||||||
$best_match = $lang;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
$possible = array_filter($accepted_langs, function($key) {
|
|
||||||
global $lang;
|
|
||||||
return strpos($key, $lang) === 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (count($possible)){
|
|
||||||
$best_match = $possible[0];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($best_match === false){
|
|
||||||
$best_match = DEFAULT_LANGUAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
$_SESSION['locale'] = $best_match;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
setlocale(LC_ALL, $_SESSION['locale'].".UTF-8");
|
|
||||||
|
|
||||||
bindtextdomain("server-status", __DIR__ . "/locale/");
|
|
||||||
bind_textdomain_codeset($_SESSION['locale'], "utf-8");
|
|
||||||
textdomain("server-status");
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
<?php
|
||||||
|
class Template(){
|
||||||
|
public static function render_header($page_name, $admin = false){
|
||||||
|
if (!$admin)
|
||||||
|
{
|
||||||
|
?>
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title><?php echo $page_name." - ".NAME ?></title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="description" content="Current service status for <?php echo NAME;?> can be found here as well as incident history.">
|
||||||
|
<link rel="shortcut icon" href="/favicon.ico" type="image/png">
|
||||||
|
<link rel="stylesheet" href="/css/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="/css/main.css" media="screen">
|
||||||
|
<link rel="stylesheet" href="/css/print.css" media="print">
|
||||||
|
<link href="/css/font-awesome.min.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="navbar navbar-default" role="navigation">
|
||||||
|
<div class="container">
|
||||||
|
<div class="navbar-header">
|
||||||
|
<a class="navbar-brand" href="<?php echo WEB_URL;?>"><img src="/img/logo_white.png" alt="logo" class="menu-logo" width="50" height="50"></a>
|
||||||
|
</div>
|
||||||
|
<div class="navbar-left hidden-xs">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<li><a href="<?php echo WEB_URL;?>/"><h1><?php echo _("Service Status");?></h1></a></li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="wrapper" class="center">
|
||||||
|
<?php
|
||||||
|
}else{
|
||||||
|
global $user;
|
||||||
|
?>
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title><?php echo $page_name." - ".NAME ?></title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="shortcut icon" href="/favicon.ico" type="image/png">
|
||||||
|
<link rel="stylesheet" href="/css/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="/css/main.css">
|
||||||
|
<link href="/css/font-awesome.min.css" rel="stylesheet">
|
||||||
|
<link href="/css/jquery.growl.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
|
||||||
|
</head>
|
||||||
|
<body class="admin">
|
||||||
|
<div class="navbar navbar-default" role="navigation">
|
||||||
|
<div class="container">
|
||||||
|
<div class="navbar-header">
|
||||||
|
|
||||||
|
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||||
|
<span class="sr-only"><?php echo _("Toggle navigation");?></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</button>
|
||||||
|
<a class="navbar-brand" href="<?php echo WEB_URL;?>/admin"><img src="/img/logo_white.png" alt="logo" class="menu-logo" width="50" height="50"></a>
|
||||||
|
</div>
|
||||||
|
<div class="navbar-collapse collapse navbar-right navbar-admin">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<li><a href="<?php echo WEB_URL;?>/admin/"><?php echo _("Dashboard");?></a></li>
|
||||||
|
<li><a href="<?php echo WEB_URL;?>/admin/?do=user"><?php printf(_("User (%s)"), $user->get_username());?></a></li>
|
||||||
|
<li><a href="<?php echo WEB_URL;?>/admin/?do=settings"><?php echo _("Settings");?></a></li>
|
||||||
|
<li><a href="<?php echo WEB_URL;?>/admin/?do=logout"><?php echo _("Logout");?></a></li>
|
||||||
|
</ul>
|
||||||
|
</div><!--/.nav-collapse -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="wrapper" class="center admin">
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function render_footer($admin = false)
|
||||||
|
{
|
||||||
|
global $lang_names;
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
<div id="footerwrap">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row centered">
|
||||||
|
<div class="col-md-4 text-left">Copyright © <?php echo date("Y");?> Vojtěch Sajdl</div>
|
||||||
|
<div class="col-md-4 text-center">
|
||||||
|
<div class="btn-group dropup">
|
||||||
|
<button type="button" class="btn btn-primary"><?php echo '<img src="'.WEB_URL.'/locale/'.$_SESSION['locale'].'/flag.png" alt="'.$lang_names[$_SESSION['locale']].'">'.$lang_names[$_SESSION['locale']];?></button>
|
||||||
|
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
|
<span class="caret"></span>
|
||||||
|
<span class="sr-only"><?php echo _("Toggle Dropdown");?></span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<?php
|
||||||
|
foreach ($lang_names as $key => $value) {
|
||||||
|
echo '<a href="?lang='.$key.'"><img src="'.WEB_URL.'/locale/'.$key.'/flag.png" alt="'.$value.'">'.$value.'</a>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<hr role="separator" class="divider">
|
||||||
|
<a href="https://poeditor.com/join/project/37SpmJtyOm"><?php echo _("Help with translation!");?></a>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 text-right"><a href="https://github.com/Pryx/server-status/" target="_blank"><i class="fa fa-github" aria-hidden="true"></i></a></div>
|
||||||
|
</div><!--/row -->
|
||||||
|
</div><!--/container -->
|
||||||
|
</div>
|
||||||
|
<script src="/js/vendor/jquery-1.11.2.min.js"></script>
|
||||||
|
<script src="/js/vendor/jquery.timeago.js"></script>
|
||||||
|
<?php if ($admin){?>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
|
||||||
|
<script src="/js/admin.js"></script>
|
||||||
|
<script src="/js/vendor/jquery.growl.js"></script>
|
||||||
|
<? }?>
|
||||||
|
<script src="/js/vendor/bootstrap.min.js"></script>
|
||||||
|
<script src="/js/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
<?
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue