diff --git a/.gitignore b/.gitignore index 4adf12f..ccae322 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,5 @@ Thumbs.db # Generic git files *.orig -# Package Helpers \ No newline at end of file +# Files not part of software +app/vault \ No newline at end of file diff --git a/app/core/class/di.php b/app/core/class/di.php index bbabae5..c1a4658 100644 --- a/app/core/class/di.php +++ b/app/core/class/di.php @@ -25,7 +25,7 @@ class DI * @param $abstract * @param null $concrete */ - public function push($abstract, $concrete = null) + public function set($abstract, $concrete = null) { if ($concrete === null) { $concrete = $abstract; @@ -40,7 +40,7 @@ public function push($abstract, $concrete = null) * @return mixed|null|object * @throws Exception */ - public function pull($abstract, $values = []) + public function get($abstract, $values = []) { // if we don't have it, just register it if (!isset($this->instances[$abstract])) { diff --git a/app/core/class/htgen.php b/app/core/class/htgen.php new file mode 100644 index 0000000..fa0b115 --- /dev/null +++ b/app/core/class/htgen.php @@ -0,0 +1,65 @@ + + * @source https://github.com/elyzin/elyzin Base repository + * @link http://elyz.in + * @copyright 2018 Elyzin + * @license MIT + * + * @todo Namespace + * @todo Interface, Form elements, Markdown Parser + */ + +class HTGen +{ + protected $void_tags = ['area', 'base', 'br', 'col', 'hr', 'img', 'input', 'link', 'meta', 'param', 'command', 'keygen', 'source']; // HTML5 Compliant Void Tags + + public function __construct() + { + } + + /** + * HTML Element Generator (all pre-structured elements depend on this method) + * + * @param string $tag + * @param string $content + * @param array $arg + * @param boolean $multiline + * @param boolean $xhtml + * @return string + */ + public function elem($tag = 'br', $content = '', $arg = array(), $multiline = true, $xhtml = false) + { + $decl = ""; + if (!empty($arg)) { // && !in_array($tag, ['br','hr'])) + $decl = array(); + foreach ($arg as $attrib => $value) { + if (is_array($value)) $value = implode(', ', $value); + if (is_numeric($attrib)) { + $attrib = $value; + $value = ''; + } + $value = (!$value) ? '' : '="' . $value . '"'; + $decl[] = $attrib . $value; + } + $decl = empty($decl) ? '' : ' ' . implode(' ', $decl); + } + if (in_array($tag, $this->void_tags)) { + $multiline = false; // Force oneline for void tags + $startclose = $content = ''; + $endopen = $xhtml ? ' /' : ''; // XHTML compatibility, false by default + } else { + $startclose = '>'; + $endopen = ''; + } +} \ No newline at end of file diff --git a/app/core/class/page.php b/app/core/class/page.php index 0bd3996..f33bb9a 100644 --- a/app/core/class/page.php +++ b/app/core/class/page.php @@ -480,7 +480,6 @@ public function out(int $pagegen = 0) $this->mustext['all'][] = 'nav'; $varhr['name'] = conf('basename'); $varhr['caption'] = $this->caption; - $varhr['project_name'] = isset($_SESSION['project']['name']) ? $_SESSION['project']['name'] : $this->lang('base', ['project_na']); $varhr['navigation'] = $this->buildNav(); // Generate the visible header diff --git a/app/core/class/user.php b/app/core/class/user.php index c889dcf..1c846f6 100644 --- a/app/core/class/user.php +++ b/app/core/class/user.php @@ -17,121 +17,138 @@ class User { - public $id; + public $id = 0; public $dispname; - public $error; - protected $message; public $permit; protected $who = 'other'; // 'self' represents object of user operating this class + public $error; + protected $di; + protected $message; private $pref; - private $site = ''; - private $userstatpath = ''; - private $avatarpath = ''; - - public function __construct(int $id=0){ - $this->site = conf('basename'); - $this->userstatpath = syspath('userstat'); - $this->avatarpath = syspath('avatar'); - if($id === 0 && isset($_SESSION['user']['id'])) $id = $_SESSION['user']['id']; - if($id === $_SESSION['user']['id']) $this->who = 'self'; - - $this->id = $id; - if($id > 0) $this->setUser($id); - - } - - protected function setUser($id=0){ // Use __set_state? - if(is_numeric($id) && $id > 0) { - $base = new db(); - $details = (array)$base->table($this->site.'_user')->where(['id'=>$id])->get(); //USE CACHE - if(!empty($details)){ - foreach ($details as $key => $value) $this->{$key} = $value; // Set all fields to class - if($this->who === 'self') $this->lastproj = $_SESSION['user']['lastproj']; // Override - if(empty($this->pref)) $this->pref = json_encode(parse_ini_file(ART.'core/conf/userpref.ini')); // Set default values if preference not defined - $this->dispname = empty($this->fullname) ? $this->name : $this->fullname; - // Set remaining days til password expiry - $clock = new clock(); - $this->passdays = conf('pass_expiry','user')-floor((time()-($clock->stamp($this->passtime,'site'))/86400)); - - } else { - $this->id = 0; - } - } - } - - public function setLast(bool $login=false, bool $proj=false, bool $commit=true){ //<< DEPRECIATE - if($this->who != 'self'){// Self environment method only - $this->error = 'Modifying last actions of other users restricted.'; - return false; - } - - $update = array(); - - if($login){ // Last login time to update - if(!isset($_SESSION['user']['thislogin'])){ - $this->error = 'Unidentifined login time.'; - return false; - } - // While changing last login to this in database, actual last login can only be accessed through session vars - $clock = new clock(); - $update['lastlogin'] = $clock->stamp($_SESSION['user']['thislogin'],'db'); - } - - if($proj){ // Last project to update - if(!isset($_SESSION['project']['code'])){ - $this->error = 'Undefined current project.'; - return false; - } - // While changing last project to this in database, actual last ptoject can only be accessed through session vars - $update['lastproj'] = $_SESSION['project']['code']; - } - - if($commit){ // Commit changes to database - global $dbx; - //$where = array('id' => $this->id); - if($dbx->table($this->site.'_user')->where('id', $this->id)->update($update)){ - //if($db->update( $this->site.'_user', $update, $where, 1 )){ - reCache($this->site.'_user'); - return true; // Commit Succeeded - } else { - $this->error = 'Database Operations Failed.'; - return false; - } - } else { - return $update; // Return update array for some other function to commit changes in database (reduce query count) - } - } - - public function getState(bool $mode=false){ + private $userstatpath = ''; + private $avatarpath = ''; + + public function __construct(db $db, Clock $clock) + { + $this->userstatpath = syspath('userstat'); + $this->avatarpath = syspath('avatar'); + $this->di['db'] = $db; + $this->di['clock'] = $clock; + $this->setUser(); + } + + public function setUser(int $id = 0) + { + if ($id === 0 && isset($_SESSION['user']['id'])) $this->id = (int)$_SESSION['user']['id']; + if (isset($_SESSION['user']['id']) && $this->id === (int)$_SESSION['user']['id']) $this->who = 'self'; + if ($this->id > 0) { + $details = (array)$this->di['db']->table(conf('basename') . '_user')->where(['id' => $this->id])->get(); //USE CACHE + if (!empty($details)) { + foreach ($details as $key => $value) $this->{$key} = $value; // Set all fields to class + if (empty($this->pref)) $this->pref = json_encode(parse_ini_file(ART . 'core/conf/userpref.ini')); // Set default values if preference not defined + if (empty($this->passdate)) $this->passdate = $this->regdate; // Set registration date as password set date if not available + $this->dispname = empty($this->fullname) ? $this->name : $this->fullname; + } else { + $this->unsetUser(); + } + } + // Set timezone as per user preference + if (!empty($this->pref('timezone'))) { + $timezone = $this->pref('timezone'); + } elseif (isset($_COOKIE['timeoffset'])) { // Detected browser time zone. Cookie set by jquery in base.js + $timezone = timezone_name_from_abbr("", $_COOKIE['timeoffset'] * 60, false); + } else { // Load timezone from site configuration + $timezone = conf('timezone'); + } + date_default_timezone_set($timezone); + if($this->id > 0) $_SESSION['user']['timezone'] = $timezone; // Save user timezone to session, reduce dependency + } + + protected function unsetUser() + { + $this->id = 0; + $this->dispname = ""; + $this->who = "other"; + $this->permit = null; + unset($this->name); + } + + public function setLast(bool $login = false, bool $proj = false, bool $commit = true) + { //<< DEPRECIATE + if ($this->who != 'self') {// Self environment method only + $this->error = 'Modifying last actions of other users restricted.'; + return false; + } + + $update = array(); + + if ($login) { // Last login time to update + if (!isset($_SESSION['user']['thislogin'])) { + $this->error = 'Unidentifined login time.'; + } else { + // While changing last login to this in database, actual last login can only be accessed through session vars + $update['lastlogin'] = $this->di['clock']->stamp($_SESSION['user']['thislogin'], 'db'); + } + } + + if ($proj) { // Last project to update + if (!isset($_SESSION['project']['code'])) { + $this->error = 'Undefined current project.'; + } else { + // While changing last project to this in database, actual last ptoject can only be accessed through session vars + $update['lastproj'] = $_SESSION['project']['code']; + } + } + + if (count($update)) { + if ($commit) { // Commit changes to database + if ($this->di['db']->table(conf('basename') . '_user')->where('id', $this->id)->update($update)) { + reCache(conf('basename') . '_user'); + return true; // Commit Succeeded + } else { + $this->error = 'Database Operations Failed.'; + return false; + } + } else { + return $update; // Return update array for some other function to commit changes in database (reduce query count) + } + } + return false; + } + + public function getState(bool $mode = false) + { // Code this, use as for each user. Depreciate users_getstate(); return users_getstate($mode); } - public function setState(int $state=3){ - if($state >= 0 && $state <= 3){ //Ensure range. 0 = Offline, 1 = Away, 2 = Busy, 3 = Online - $clock = new clock(); - $status[] = array('uid'=>$this->id, 'name'=>$this->dispname,'last_seen'=> $clock->stamp(time(),'db'), 'state'=>$state); - $file_handle = fopen($this->userstatpath.$this->id.'.stt', "w"); + public function setState(int $state = 3) + { + if ($state >= 0 && $state <= 3) { //Ensure range. 0 = Offline, 1 = Away, 2 = Busy, 3 = Online + $status[] = array('uid' => $this->id, 'name' => $this->dispname, 'last_seen' => $this->di['clock']->stamp(time(), 'db'), 'state' => $state); + $file_handle = fopen($this->userstatpath . $this->id . '.stt', "w"); $result = fwrite($file_handle, json_encode($status)); // SAFE WRITER?? fclose($file_handle); return $result; } else { return false; } - } - - public function permit(string $prop='lvl', string $proj=null, string $unit=null){ - if(!sizeof($this->permit) || !in_array($prop, ['lvl','prj','unt'])) return 0; + } + public function permit(string $prop = 'lvl', string $proj = null, string $unit = null) + { $permit = json_decode($this->permit, true); + if (!is_array($permit)) $permit = []; + if (!sizeof($permit) || !in_array($prop, ['lvl', 'prj', 'unt'])) return 0; + $lvl = key($permit); - if($prop === 'lvl') return $lvl; + if ($prop === 'lvl') return $lvl; - if($prop === 'prj'){ + if ($prop === 'prj') { $prj = array(); // Blank container - if($lvl >= 6){ // Have access to all projects + if ($lvl >= 6) { // Have access to all projects // Get all projects - $all_projects = [];//enCache('SELECT code FROM '.$this->site.'_projects'); + $all_projects = [];//enCache('SELECT code FROM '.conf('basename').'_projects'); foreach ($all_projects as $proj) { $prj[] = $proj['code']; } @@ -141,65 +158,52 @@ public function permit(string $prop='lvl', string $proj=null, string $unit=null) return $prj; } - if($prop === 'unt'){ + if ($prop === 'unt') { $unt = 0; //Set Unit access - if(empty($proj)){ - if(isset($_SESSION['project']['code'])) $proj = $_SESSION['project']['code']; + if (empty($proj)) { + if (isset($_SESSION['project']['code'])) $proj = $_SESSION['project']['code']; } - if(isset($proj)){ - if(!isset($unit)){ - if(isset($_SESSION['project']['unit'])) $unit = $_SESSION['project']['unit']; + if (isset($proj)) { + if (!isset($unit)) { + if (isset($_SESSION['project']['unit'])) $unit = $_SESSION['project']['unit']; } } - if(isset($unit)){ - if($lvl > 6){ + if (isset($unit)) { + if ($lvl > 6) { $unt = '7'; } else { - $unit_key = array_search($unit, array_column(array_column(include('presets/units.php'),'name'),0)); - if(!empty($permit[$lvl]) && isset($permit[$lvl][$proj][$unit_key])) //<< CHECK SECOND CONDITION - $unt = explode(',',$permit[$lvl][$proj])[$unit_key]; + $unit_key = array_search($unit, array_column(array_column(include('presets/units.php'), 'name'), 0)); + if (!empty($permit[$lvl]) && isset($permit[$lvl][$proj][$unit_key])) //<< CHECK SECOND CONDITION + $unt = explode(',', $permit[$lvl][$proj])[$unit_key]; } } return $unt; } - } + } // Return user preference - public function pref(string $prop){ - if($this->id){ - if(in_array($prop, array_keys(json_decode($this->pref,true)))){ - return json_decode($this->pref)->$prop; - } - } - } - - public function avatar($id=0){ - $id = $this->id; - $avatar = glob($this->avatarpath.$id.'.*'); // < USE $file->getPath()? - $avatar = (count($avatar)>0) ? $avatar[0] : $this->avatarpath.'0.jpg'; + public function pref(string $prop) + { + if ($this->id) { + if (in_array($prop, array_keys(json_decode($this->pref, true)))) { + return json_decode($this->pref)->$prop; + } + } + } + + /** + * Generates user avatar image path + * + * @param integer $id // User ID + * @return string + * @todo Gravatar Support + */ + public function avatar($id = 0) + { + $id = $this->id; + $avatar = glob($this->avatarpath . $id . '.*'); // < USE $file->getPath()? + $avatar = (count($avatar) > 0) ? $avatar[0] : $this->avatarpath . '0.jpg'; return $avatar; - } - - public function logout($mode=0){ // Only self. Mode 0 is manual logout, mode 1 is auto - - $this->setState(0); - - if($mode){ // Auto logout, session timeout - $mode = 1; // Reset positive value to 1, in case - $uptime = $this->ontime + ($_SESSION['user']['lastact'] - $_SESSION['user']['thislogin']) + conf('session_timeout','user')*60; - $msg = "Session timed out. Please login again."; - } else { // Manual logout - $uptime = $this->ontime + time() - $_SESSION['user']['thislogin']; - $msg = "Logged out successfully."; - } - global $db; - $update = $this->setLast(1,1,0); - $update['ontime'] = $uptime; - $db->table($this->site.'_user')->where('id', $this->id)->update($update); - foreach ($_SESSION as $key => $value) { unset($_SESSION[$key]); } - global $page; - $page->message($msg,$mode+1); - $page->redirect(); - } + } } \ No newline at end of file diff --git a/public/index.php b/public/index.php index e880831..b17401f 100644 --- a/public/index.php +++ b/public/index.php @@ -1,4 +1,5 @@ pull['user']; -$page = $di->pull['page']; + +$di = new DI(); +$me = $di->get('User'); +$page = $di->get('Page'); // Set timezone as per user preference -if(!empty($me->pref('timezone'))){ +if (!empty($me->pref('timezone'))) { $timezone = $me->pref('timezone'); -} elseif(isset($_COOKIE['timeoffset'])){ // Detected browser time zone. Cookie set by jquery in base.js - $timezone = timezone_name_from_abbr("", $_COOKIE['timeoffset']*60, false); +} elseif (isset($_COOKIE['timeoffset'])) { // Detected browser time zone. Cookie set by jquery in base.js + $timezone = timezone_name_from_abbr("", $_COOKIE['timeoffset'] * 60, false); } else { // Load timezone from site configuration $timezone = conf('timezone'); }