Refactor project structure

This commit is contained in:
Thilina Hasantha
2018-04-29 17:46:42 +02:00
parent 889baf124c
commit e3a7e18d9c
5513 changed files with 32 additions and 27 deletions

View File

@@ -0,0 +1,40 @@
<?php
/*
This file is part of Ice Framework.
Ice Framework is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Ice Framework is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Ice Framework. If not, see <http://www.gnu.org/licenses/>.
------------------------------------------------------------------
Original work Copyright (c) 2012 [Gamonoid Media Pvt. Ltd]
Developer: Thilina Hasantha (thilina.hasantha[at]gmail.com / facebook.com/thilinah)
*/
namespace Classes;
abstract class AbstractInitialize
{
/* @var \Classes\BaseService $baseService */
public $baseService = null;
public function setBaseService($baseService)
{
$this->baseService = $baseService;
}
public function getCurrentProfileId()
{
return $this->baseService->getCurrentProfileId();
}
abstract public function init();
}

View File

@@ -0,0 +1,278 @@
<?php
/**
*The base class for module manager classes. ModuleManager classes which extend this
* class provide core backend functionality
*to each module such as defining models, error handliing and other configuration details
*@class AbstractModuleManager
*/
namespace Classes;
use Utils\LogManager;
abstract class AbstractModuleManager
{
private $fileFieldMappings = array();
private $userClasses = array();
private $errorMappings = array();
private $modelClasses = array();
private $modulePath = null;
private $moduleObject = null;
private $moduleType = null;
private $actionManager = null;
/**
* Override this method in module manager class to define user classes.
* A user class is a class that is mapped to a table having a field named profile.
* The profile field is mapped to the id of a Profile element.
* When a user is saving this type of an object in db, profile field will be set to the id of the
* Profile of currently logged in or switched user.
* When a user is retriving this type of records, only the records having profile field set to c
* urrently logged in users profile id will be released.
* @method initializeUserClasses
* @example
public function initializeUserClasses(){
$this->addUserClass("EmployeeDocument");
}
*
*/
abstract public function initializeUserClasses();
/**
* Override this method in module manager class to define file field mappings.
* If you have a table field that stores a name of a file which need to be
* deleted from the disk when the record is deleted a file field mapping should be added.
* @method initializeFieldMappings
* @example
public function initializeFieldMappings(){
$this->addFileFieldMapping('EmployeeDocument', 'attachment', 'name');
}
*/
abstract public function initializeFieldMappings();
/**
* Override this method in module manager class to define DB error mappings. Some actions to your
* model classes trigger database errors.
* These errors need to be translated to user friendly texts using DB error mappings
* @method initializeDatabaseErrorMappings
* @example
public function initializeDatabaseErrorMappings(){
$this->addDatabaseErrorMapping('CONSTRAINT `Fk_User_Employee` FOREIGN KEY',"Can not delete Employee,
* please delete the User for this employee first.");
$this->addDatabaseErrorMapping("Duplicate entry|for key 'employee'","A duplicate entry found");
}
*/
abstract public function initializeDatabaseErrorMappings();
/**
* Override this method in module manager class to add model classes to this module.
* All the model classes defind for the module should be added here
* @method setupModuleClassDefinitions
* @example
public function setupModuleClassDefinitions(){
$this->addModelClass('Employee');
$this->addModelClass('EmploymentStatus');
}
*/
abstract public function setupModuleClassDefinitions();
public function initCalculationHooks()
{
}
public function initQuickAccessMenu()
{
}
/**
* @return null
*/
public function getInitializer()
{
return null;
}
public function setModuleObject($obj)
{
$this->moduleObject = $obj;
}
public function getModuleObject()
{
return $this->moduleObject;
}
/**
* @return null
*/
public function getActionManager()
{
return $this->actionManager;
}
/**
* @param null $actionManager
*/
public function setActionManager($actionManager)
{
$this->actionManager = $actionManager;
}
public function setModuleType($type)
{
$this->moduleType = $type;
}
public function getModuleType()
{
return $this->moduleType;
}
public function getModulePath()
{
/*
$subClass = get_called_class();
$reflector = new \ReflectionClass($subClass);
$fn = $reflector->getFileName();
$this->modulePath = realpath(dirname($fn)."/..");
LogManager::getInstance()->info("Module Path: [$subClass | $fn]".$this->modulePath);
*/
return $this->modulePath;
}
public function setModulePath($modulePath)
{
$this->modulePath = $modulePath;
}
public function getDashboardItemData()
{
return array();
}
public function getDashboardItem()
{
$this->getModulePath();
if (!file_exists($this->modulePath."/dashboard.html")) {
//LogManager::getInstance()->error("Dashboard file not found :".$this->modulePath."/dashboard.html");
return null;
}
$dashboardItem = file_get_contents($this->modulePath."/dashboard.html");
if (empty($dashboardItem)) {
//LogManager::getInstance()->error("Dashboard file is empty :".$this->modulePath."/dashboard.html");
return null;
}
$data = $this->getDashboardItemData();
$data['moduleLink'] = $this->getModuleLink();
LogManager::getInstance()->info("Module Link:".$data['moduleLink']);
foreach ($data as $k => $v) {
$dashboardItem = str_replace("#_".$k."_#", $v, $dashboardItem);
}
return $dashboardItem;
}
public function getDashboardItemIndex()
{
$metaData = json_decode(file_get_contents($this->modulePath."/meta.json"), true);
if (!isset($metaData['dashboardPosition'])) {
return 100;
} else {
return $metaData['dashboardPosition'];
}
}
private function getModuleLink()
{
$metaData = json_decode(file_get_contents($this->modulePath."/meta.json"), true);
$mod = basename($this->modulePath);
$group = basename(realpath($this->modulePath."/.."));
//?g=admin&n=candidates&m=admin_Recruitment
return CLIENT_BASE_URL."?g=".$group."&n=".$mod."&m=".$group."_".str_replace(" ", "_", $metaData['label']);
}
public function setupRestEndPoints()
{
}
public function setupFileFieldMappings(&$fileFields)
{
foreach ($this->fileFieldMappings as $mapping) {
if (empty($fileFields[$mapping[0]])) {
$fileFields[$mapping[0]] = array();
}
$fileFields[$mapping[0]][$mapping[1]] = $mapping[2];
}
}
public function setupUserClasses(&$userTables)
{
foreach ($this->userClasses as $className) {
if (!in_array($className, $userTables)) {
$userTables[] = $className;
}
}
}
public function setupErrorMappings(&$mysqlErrors)
{
foreach ($this->errorMappings as $name => $desc) {
$mysqlErrors[$name] = $desc;
}
}
public function getModelClasses()
{
return $this->modelClasses;
}
protected function addFileFieldMapping($className, $fieldName, $fileTableFieldName)
{
$this->fileFieldMappings[] = array($className, $fieldName, $fileTableFieldName);
}
protected function addUserClass($className)
{
$this->userClasses[] = $className;
}
protected function addDatabaseErrorMapping($error, $description)
{
$this->errorMappings[$error] = $description;
}
protected function addModelClass($className)
{
$this->modelClasses[] = $className;
BaseService::getInstance()->addModelClass($className, $this->moduleObject['model_namespace']."\\".$className);
}
protected function addHistoryGeneric($type, $table, $refName, $refId, $field, $oldValue, $newValue)
{
/* @var \Model\BaseModel $eh */
$nsTable = BaseService::getInstance()->getFullQualifiedModelClassName($table);
$eh = new $nsTable();
$eh->type = $type;
$eh->$refName = $refId;
$eh->field = $field;
$eh->user = BaseService::getInstance()->getCurrentUser()->id;
$eh->old_value = $oldValue;
$eh->new_value = $newValue;
$eh->created = date("Y-m-d H:i:s");
$eh->updated = date("Y-m-d H:i:s");
$eh->Save();
}
public function addCalculationHook($code, $name, $class, $method)
{
BaseService::getInstance()->addCalculationHook($code, $name, $class, $method);
}
}

View File

@@ -0,0 +1,199 @@
<?php
/*
Copyright 2017 Thilina Hasantha (thilina@gamonoid.com | http://lk.linkedin.com/in/thilinah)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
namespace Classes\Approval;
use Classes\BaseService;
use Classes\IceResponse;
use Employees\Common\Model\Employee;
use Employees\Common\Model\EmployeeApproval;
use Model\BaseModel;
use Utils\LogManager;
class ApprovalStatus
{
const APP_ST_APPROVED = 1;
const APP_ST_REJECTED = 0;
private static $me = null;
private function __construct()
{
}
public static function getInstance()
{
if (empty(self::$me)) {
self::$me = new ApprovalStatus();
}
return self::$me;
}
public function isDirectApproval($employeeId)
{
$emp = new Employee();
$emp->Load("id = ?", array($employeeId));
if (empty($emp->approver1) && empty($emp->approver2) && empty($emp->approver3)) {
return true;
}
return false;
}
public function getResolvedStatuses($type, $id)
{
$employeeApproval = new EmployeeApproval();
$eas = $employeeApproval->Find("type = ? and element = ? and status > -1 order by level", array($type, $id));
return $eas;
}
public function approvalChainExists($type, $id)
{
$list = $this->getAllStatuses($type, $id);
return count($list) > 0;
}
public function getAllStatuses($type, $id)
{
$employeeApproval = new EmployeeApproval();
$eas = $employeeApproval->Find("type = ? and element = ? order by level", array($type, $id));
return $eas;
}
public function initializeApprovalChain($type, $id)
{
/* @var \Model\BaseModel $element */
$nsClass = BaseService::getInstance()->getFullQualifiedModelClassName($type);
$element = new $nsClass();
$element->Load("id = ?", array($id));
$employeeId = $element->employee;
for ($i = 1; $i < 4; $i++) {
$approver = $this->getApproverByLevel($i, $employeeId);
if (!empty($approver)) {
$employeeApproval = new EmployeeApproval();
$employeeApproval->type = $type;
$employeeApproval->element = $id;
$employeeApproval->approver = $approver;
$employeeApproval->level = $i;
$employeeApproval->status = -1;
$employeeApproval->active = 0;
$employeeApproval->created = date("Y-m-d H:i:s");
$employeeApproval->updated = date("Y-m-d H:i:s");
$ok = $employeeApproval->Save();
if (!$ok) {
LogManager::getInstance()->error("Error:".$employeeApproval->ErrorMsg());
}
} else {
LogManager::getInstance()->error("Approver is empty level:".$i);
}
}
}
public function updateApprovalStatus($type, $id, $currentEmployee, $status)
{
if (!$this->approvalChainExists($type, $id)) {
return new IceResponse(IceResponse::SUCCESS, array(null, null));
}
if ($status != 0 && $status != 1) {
return new IceResponse(IceResponse::ERROR, "Invalid data");
}
/* @var BaseModel $element */
$nsClass = BaseService::getInstance()->getFullQualifiedModelClassName($type);
$element = new $nsClass();
$element->Load("id = ?", array($id));
$eas = $this->getAllStatuses($type, $id);
$level = 0;
//check if the element is already rejected
foreach ($eas as $ea) {
if ($ea->status == 0) {
return new IceResponse(IceResponse::ERROR, "This item is already rejected");
} elseif ($ea->active == 1) {
$level = intval($ea->level);
}
}
$currentAL = null;
if ($level > 0) {
$currentAL = new EmployeeApproval();
$currentAL->Load("type = ? and element = ? and level = ?", array($type, $id, $level));
}
$nextAL = null;
if ($level < 3) {
$nextAL = new EmployeeApproval();
$nextAL->Load("type = ? and element = ? and level = ?", array($type, $id, intval($level)+1));
if (empty($nextAL->id)) {
$nextAL = null;
}
}
//Check if the current employee is allowed to approve
if ($level > 0 && $currentEmployee != $currentAL->approver) {
return new IceResponse(IceResponse::ERROR, "You are not allowed to approve or reject");
}
if (!empty($currentAL)) {
//Now mark the approval status
$currentAL->status = $status;
$currentAL->Save();
}
if (!empty($nextAL)) {
/* @var EmployeeApproval $ea */
foreach ($eas as $ea) {
if ($ea->id == $nextAL->id) {
$nextAL->active = 1;
$nextAL->Save();
} else {
$ea->active = 0;
$ea->Save();
}
}
}
if (!empty($currentAL)) {
$oldCurrAlId = $currentAL->id;
$currentAL = new EmployeeApproval();
$currentAL->Load("id = ?", array($oldCurrAlId));
}
return new IceResponse(IceResponse::SUCCESS, array($currentAL, $nextAL));
}
/**
* @param $level
* @param $employeeId
* @return int $approverId
*/
private function getApproverByLevel($level, $employeeId)
{
$emp = new Employee();
$emp->Load("id = ?", array($employeeId));
$approver = null;
$alevel = "approver".$level;
return $emp->$alevel;
}
}

View File

@@ -0,0 +1,174 @@
<?php
namespace Classes\Approval;
use Classes\BaseService;
use Classes\IceConstants;
use Classes\IceResponse;
use Classes\StatusChangeLogManager;
use Model\BaseModel;
use Utils\LogManager;
abstract class ApproveAdminActionManager extends ApproveCommonActionManager
{
abstract public function getModelClass();
abstract public function getItemName();
abstract public function getModuleName();
abstract public function getModuleTabUrl();
abstract public function getModuleSubordinateTabUrl();
abstract public function getModuleApprovalTabUrl();
public function changeStatus($req)
{
$class = $this->getModelClass();
$itemName = $this->getItemName();
/* @var BaseModel $obj */
$nsClass = BaseService::getInstance()->getFullQualifiedModelClassName($class);
$obj = new $nsClass();
$obj->Load("id = ?", array($req->id));
if ($obj->id != $req->id) {
return new IceResponse(IceResponse::ERROR, "$itemName not found");
}
/*
if($this->user->user_level != 'Admin' && $this->user->user_level != 'Manager'){
return new IceResponse(IceResponse::ERROR,"Only an admin or manager can do this");
}*/
//Check if this needs to be multi-approved
$apStatus = 0;
if ($req->status == "Approved") {
$apStatus = 1;
}
if ($req->status == "Approved" || $req->status == "Rejected") {
$approvalResp = ApprovalStatus::getInstance()->updateApprovalStatus(
$class,
$obj->id,
BaseService::getInstance()->getCurrentProfileId(),
$apStatus
);
if ($approvalResp->getStatus() == IceResponse::SUCCESS) {
$objResp = $approvalResp->getObject();
$currentAp = $objResp[0];
$nextAp = $objResp[1];
$sendApprovalEmailto = null;
if (empty($currentAp) && empty($nextAp)) {
//No multi level approvals
LogManager::getInstance()->debug($obj->id."|No multi level approvals|");
if ($req->status == "Approved") {
$req->status = "Approved";
}
} elseif (empty($currentAp) && !empty($nextAp)) {
//Approval process is defined, but this person is a supervisor
LogManager::getInstance()->debug(
$obj->id."|Approval process is defined, but this person is a supervisor|"
);
$sendApprovalEmailto = $nextAp->approver;
if ($req->status == "Approved") {
$req->status = "Processing";
}
} elseif (!empty($currentAp) && empty($nextAp)) {
//All multi level approvals completed, now we can approve
LogManager::getInstance()->debug(
$obj->id."|All multi level approvals completed, now we can approve|"
);
if ($req->status == "Approved") {
$req->status = "Approved";
}
} else {
//Current employee is an approver and we have another approval level left
LogManager::getInstance()->debug(
$obj->id."|Current employee is an approver and we have another approval level left|"
);
$sendApprovalEmailto = $nextAp->approver;
if ($req->status == "Approved") {
$req->status = "Processing";
}
}
} else {
return $approvalResp;
}
}
$oldStatus = $obj->status;
$obj->status = $req->status;
if ($oldStatus == $req->status && $req->status != "Processing") {
return new IceResponse(IceResponse::SUCCESS, "");
}
$ok = $obj->Save();
if (!$ok) {
LogManager::getInstance()->info($obj->ErrorMsg());
return new IceResponse(
IceResponse::ERROR,
"Error occurred while saving $itemName information. Please contact admin"
);
}
StatusChangeLogManager::getInstance()->addLog(
$class,
$obj->id,
BaseService::getInstance()->getCurrentUser()->id,
$oldStatus,
$req->status,
""
);
$this->baseService->audit(
IceConstants::AUDIT_ACTION,
"$itemName status changed from:".$oldStatus." to:".$obj->status." id:".$obj->id
);
$currentEmpId = $this->getCurrentProfileId();
if (!empty($currentEmpId)) {
$employee = $this->baseService->getElement('Employee', $currentEmpId);
$notificationMsg
= "Your $itemName has been $obj->status by ".$employee->first_name." ".$employee->last_name;
if (!empty($req->reason)) {
$notificationMsg.=" (Note:".$req->reason.")";
}
$this->baseService->notificationManager->addNotification(
$obj->employee,
$notificationMsg,
'{"type":"url","url":"'.$this->getModuleTabUrl().'"}',
$this->getModuleName(),
null,
false,
true
);
}
if (!empty($sendApprovalEmailto)) {
$employee = $this->baseService->getElement(
'Employee',
BaseService::getInstance()->getCurrentProfileId()
);
$notificationMsg
= "You have been assigned ".$itemName." for approval by ".
$employee->first_name." ".$employee->last_name;
$this->baseService->notificationManager->addNotification(
$sendApprovalEmailto,
$notificationMsg,
'{"type":"url","url":"'.$this->getModuleApprovalTabUrl().'"}',
$this->getModuleName(),
null,
false,
true
);
}
return new IceResponse(IceResponse::SUCCESS, "");
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Classes\Approval;
use Classes\IceResponse;
use Classes\StatusChangeLogManager;
use Classes\SubActionManager;
abstract class ApproveCommonActionManager extends SubActionManager
{
public function getLogs($req)
{
$class = $this->getModelClass();
$logs = StatusChangeLogManager::getInstance()->getLogs($class, $req->id);
return new IceResponse(IceResponse::SUCCESS, $logs);
}
}

View File

@@ -0,0 +1,76 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/20/17
* Time: 9:25 AM
*/
namespace Classes\Approval;
use Classes\BaseService;
use Classes\IceConstants;
use Classes\IceResponse;
use Utils\LogManager;
abstract class ApproveModuleActionManager extends ApproveCommonActionManager
{
abstract public function getModelClass();
abstract public function getItemName();
abstract public function getModuleName();
abstract public function getModuleTabUrl();
public function cancel($req)
{
$employee = $this->baseService->getElement('Employee', $this->getCurrentProfileId(), null, true);
$class = $this->getModelClass();
$itemName = $this->getItemName();
/* @var \Model\BaseModel $obj */
$nsClass = BaseService::getInstance()->getFullQualifiedModelClassName($class);
$obj = new $nsClass();
$obj->Load("id = ?", array($req->id));
if ($obj->id != $req->id) {
return new IceResponse(IceResponse::ERROR, "$itemName record not found");
}
if ($this->user->user_level != 'Admin' && $this->getCurrentProfileId() != $obj->employee) {
return new IceResponse(IceResponse::ERROR, "Only an admin or owner of the $itemName can do this");
}
if ($obj->status != 'Approved') {
return new IceResponse(IceResponse::ERROR, "Only an approved $itemName can be cancelled");
}
$obj->status = 'Cancellation Requested';
$ok = $obj->Save();
if (!$ok) {
LogManager::getInstance()->error("Error occurred while cancelling the $itemName:".$obj->ErrorMsg());
return new IceResponse(
IceResponse::ERROR,
"Error occurred while cancelling the $itemName. Please contact admin."
);
}
$this->baseService->audit(
IceConstants::AUDIT_ACTION,
"Expense cancellation | start:".$obj->date_start."| end:".$obj->date_end
);
$notificationMsg
= $employee->first_name." ".$employee->last_name
." cancelled a expense. Visit expense management module to approve";
$this->baseService->notificationManager->addNotification(
$employee->supervisor,
$notificationMsg,
'{"type":"url","url":"'.$this->getModuleTabUrl().'"}',
$this->getModuleName(),
null,
false,
true
);
return new IceResponse(IceResponse::SUCCESS, $obj);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,51 @@
<?php
namespace Classes\Cron;
class CronUtils
{
public $clientBasePath;
public $cronFile;
private static $me = null;
private function __construct($clientBasePath, $cronFile)
{
$this->clientBasePath = $clientBasePath."/";
$this->cronFile = $cronFile;
}
public static function getInstance($clientBasePath, $cronFile)
{
if (empty(self::$me)) {
self::$me = new CronUtils($clientBasePath, $cronFile);
}
return self::$me;
}
public function run()
{
$ams = scandir($this->clientBasePath);
$count = 0;
foreach ($ams as $am) {
if (is_dir($this->clientBasePath.$am) && $am != '.' && $am != '..') {
$command = "php ".$this->clientBasePath.$am."/".$this->cronFile;
if (file_exists($this->clientBasePath.$am."/".$this->cronFile)) {
echo "Run:".$command."\r\n";
error_log("Run:".$command);
passthru($command, $res);
echo "Result :".$res."\r\n";
error_log("Result :".$res);
$count++;
if ($count > 25) {
sleep(1);
$count = 0;
}
} else {
echo "Error (File Not Found):".$command."\r\n";
error_log("Error (File Not Found):".$command);
}
}
}
}
}

View File

@@ -0,0 +1,125 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/20/17
* Time: 9:33 AM
*/
namespace Classes\Cron;
use Model\Cron;
use Utils\LogManager;
class IceCron
{
const MINUTELY = "Minutely";
const HOURLY = "Hourly";
const DAILY = "Daily";
const WEEKLY = "Weekly";
const MONTHLY = "Monthly";
const YEARLY = "Yearly";
/* @var Cron $cron */
private $cron;
public function __construct($cron)
{
$this->cron = $cron;
}
public function isRunNow()
{
LogManager::getInstance()->debug("Cron ".print_r($this->cron, true));
$lastRunTime = $this->cron->lastrun;
if (empty($lastRunTime)) {
LogManager::getInstance()->debug("Cron ".$this->cron->name." is running since last run time is empty");
return true;
}
$type = $this->cron->type;
$frequency = intval($this->cron->frequency);
$time = intval($this->cron->time);
if (empty($frequency) || !is_int($frequency)) {
LogManager::getInstance()->debug(
"Cron ".$this->cron->name." is not running since frequency is not an integer"
);
return false;
}
if ($type == self::MINUTELY) {
$diff = (strtotime("now") - strtotime($lastRunTime));
if (empty($time) || !is_int($time)) {
if ($diff > 60) {
return true;
}
} else {
if ($diff > 60 * $time) {
return true;
}
}
} elseif ($type == self::HOURLY) {
if (empty($time) || !is_int($time)) {
if (date('H') != date('H', strtotime($lastRunTime))) {
return true;
}
} else {
if (intval(date('i')) >= intval($time) && date('H') != date('H', strtotime($lastRunTime))) {
return true;
}
}
} elseif ($type == self::DAILY) {
if (empty($time) || !is_int($time)) {
if (date('d') != date('d', strtotime($lastRunTime))) {
return true;
}
} else {
if (intval(date('H')) >= intval($time) && date('d') != date('d', strtotime($lastRunTime))) {
return true;
}
}
} elseif ($type == self::MONTHLY) {
if (empty($time) || !is_int($time)) {
if (date('m') != date('m', strtotime($lastRunTime))) {
return true;
}
} else {
if (intval(date('d')) >= intval($time) && date('m') != date('m', strtotime($lastRunTime))) {
return true;
}
}
} elseif ($type == self::YEARLY) {
if (empty($time) || !is_int($time)) {
if (date('Y') != date('Y', strtotime($lastRunTime))) {
return true;
}
} else {
if (intval(date('m')) >= intval($time) && date('Y') != date('Y', strtotime($lastRunTime))) {
return true;
}
}
}
return false;
}
public function execute()
{
$class = '\\Classes\\Cron\\Task\\'.$this->cron->class;
/* @var IceTask $obj */
$obj = new $class();
$obj->execute($this->cron);
$this->cronCompleted();
}
private function cronCompleted()
{
$this->cron->lastrun = date("Y-m-d H:i:s");
$ok = $this->cron->Save();
if (!$ok) {
LogManager::getInstance()->error("Error saving cron due to :".$this->cron->ErrorMsg());
}
}
}

View File

@@ -0,0 +1,14 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/20/17
* Time: 9:34 AM
*/
namespace Classes\Cron;
interface IceTask
{
public function execute($cron);
}

View File

@@ -0,0 +1,58 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/20/17
* Time: 9:34 AM
*/
namespace Classes\Cron\Task;
use Classes\BaseService;
use Classes\Cron\IceTask;
use Classes\SettingsManager;
use Employees\Common\Model\Employee;
use Model\IceEmail;
use Utils\LogManager;
abstract class EmailIceTask implements IceTask
{
abstract public function execute($cron);
public function sendEmployeeEmails($emailList, $subject)
{
foreach ($emailList as $employeeId => $emailData) {
$ccList = array();
if (SettingsManager::getInstance()->getSetting(
'Notifications: Copy Document Expiry Emails to Manager'
) == '1'
) {
$employee = new Employee();
$employee->Load("id = ?", array($employeeId));
if (!empty($employee->supervisor)) {
$supperuser = BaseService::getInstance()->getUserFromProfileId($employee->supervisor);
if (!empty($supperuser)) {
$ccList[] = $supperuser->email;
}
}
}
$user = BaseService::getInstance()->getUserFromProfileId($employeeId);
if (!empty($user) && !empty($user->email)) {
$email = new IceEmail();
$email->subject = $subject;
$email->toEmail = $user->email;
$email->template = $emailData;
$email->params = '[]';
$email->cclist = json_encode($ccList);
$email->bcclist = '[]';
$email->status = 'Pending';
$email->created = date('Y-m-d H:i:s');
$email->updated = date('Y-m-d H:i:s');
$ok = $email->Save();
if (!$ok) {
LogManager::getInstance()->error("Error Saving Email: ".$email->ErrorMsg());
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/20/17
* Time: 1:35 PM
*/
namespace Classes\Cron\Task;
use Classes\BaseService;
use Classes\Cron\IceTask;
use Model\IceEmail;
use Utils\LogManager;
class EmailSenderTask implements IceTask
{
public function execute($cron)
{
$email = new IceEmail();
$emails = $email->Find("status = ? limit 10", array('Pending'));
$emailSender = BaseService::getInstance()->getEmailSender();
/* @var IceEmail $email */
foreach ($emails as $email) {
try {
$emailSender->sendEmailFromDB($email);
} catch (\Exception $e) {
LogManager::getInstance()->error("Error sending email:".$e->getMessage());
}
$email->status = 'Sent';
$email->updated = date('Y-m-d H:i:s');
$email->Save();
}
}
}

View File

@@ -0,0 +1,213 @@
<?php
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* AES implementation in PHP (c) Chris Veness 2005-2011. Right of free use is granted for all */
/* commercial or non-commercial use under CC-BY licence. No warranty of any form is offered. */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
namespace Classes\Crypt;
class Aes
{
/**
* AES Cipher function: encrypt 'input' with Rijndael algorithm
*
* @param $input string as byte-array (16 bytes)
* @param w array key schedule as 2D byte-array (Nr+1 x Nb bytes) -
* generated from the cipher key by keyExpansion()
* @return array ciphertext as byte-array (16 bytes)
*/
public static function cipher($input, $w)
{
// main cipher function [<5B>5.1]
$Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
$Nr = count($w)/$Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys
$state = array(); // initialise 4xNb byte-array 'state' with input [<5B>3.4]
for ($i = 0; $i<4*$Nb;
$i++) {
$state[$i%4][floor($i/4)] = $input[$i];
}
$state = self::addRoundKey($state, $w, 0, $Nb);
for ($round = 1; $round<$Nr; $round++) { // apply Nr rounds
$state = self::subBytes($state, $Nb);
$state = self::shiftRows($state, $Nb);
$state = self::mixColumns($state, $Nb);
$state = self::addRoundKey($state, $w, $round, $Nb);
}
$state = self::subBytes($state, $Nb);
$state = self::shiftRows($state, $Nb);
$state = self::addRoundKey($state, $w, $Nr, $Nb);
$output = array(4*$Nb); // convert state to 1-d array before returning [<5B>3.4]
for ($i = 0; $i<4*$Nb;
$i++) {
$output[$i] = $state[$i%4][floor($i/4)];
}
return $output;
}
private static function addRoundKey($state, $w, $rnd, $Nb)
{
// xor Round Key into state S [<5B>5.1.4]
for ($r = 0; $r<4; $r++) {
for ($c = 0; $c<$Nb;
$c++) {
$state[$r][$c] ^= $w[$rnd*4+$c][$r];
}
}
return $state;
}
private static function subBytes($s, $Nb)
{
// apply SBox to state S [<5B>5.1.1]
for ($r = 0; $r<4; $r++) {
for ($c = 0; $c<$Nb;
$c++) {
$s[$r][$c] = self::$sBox[$s[$r][$c]];
}
}
return $s;
}
private static function shiftRows($s, $Nb)
{
// shift row r of state S left by r bytes [<5B>5.1.2]
$t = array(4);
for ($r = 1; $r<4; $r++) {
for ($c = 0; $c<4;
$c++) {
$t[$c] = $s[$r][($c+$r)%$Nb]; // shift into temp copy
}
for ($c = 0; $c<4;
$c++) {
$s[$r][$c] = $t[$c]; // and copy back
}
} // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
return $s; // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf
}
private static function mixColumns($s, $Nb)
{
// combine bytes of each col of state S [<5B>5.1.3]
for ($c = 0; $c<4; $c++) {
$a = array(4); // 'a' is a copy of the current column from 's'
$b = array(4); // 'b' is a<>{02} in GF(2^8)
for ($i = 0; $i<4; $i++) {
$a[$i] = $s[$i][$c];
$b[$i] = $s[$i][$c]&0x80 ? $s[$i][$c]<<1 ^ 0x011b : $s[$i][$c]<<1;
}
// a[n] ^ b[n] is a<>{03} in GF(2^8)
$s[0][$c] = $b[0] ^ $a[1] ^ $b[1] ^ $a[2] ^ $a[3]; // 2*a0 + 3*a1 + a2 + a3
$s[1][$c] = $a[0] ^ $b[1] ^ $a[2] ^ $b[2] ^ $a[3]; // a0 * 2*a1 + 3*a2 + a3
$s[2][$c] = $a[0] ^ $a[1] ^ $b[2] ^ $a[3] ^ $b[3]; // a0 + a1 + 2*a2 + 3*a3
$s[3][$c] = $a[0] ^ $b[0] ^ $a[1] ^ $a[2] ^ $b[3]; // 3*a0 + a1 + a2 + 2*a3
}
return $s;
}
/**
* Key expansion for Rijndael cipher(): performs key expansion on cipher key
* to generate a key schedule
*
* @param key array cipher key byte-array (16 bytes)
* @return array key schedule as 2D byte-array (Nr+1 x Nb bytes)
*/
public static function keyExpansion($key)
{
// generate Key Schedule from Cipher Key [<5B>5.2]
$Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
$Nk = count($key)/4; // key length (in words): 4/6/8 for 128/192/256-bit keys
$Nr = $Nk + 6; // no of rounds: 10/12/14 for 128/192/256-bit keys
$w = array();
$temp = array();
for ($i = 0; $i<$Nk; $i++) {
$r = array($key[4*$i], $key[4*$i+1], $key[4*$i+2], $key[4*$i+3]);
$w[$i] = $r;
}
for ($i = $Nk; $i<($Nb*($Nr+1)); $i++) {
$w[$i] = array();
for ($t = 0; $t<4;
$t++) {
$temp[$t] = $w[$i-1][$t];
}
if ($i % $Nk == 0) {
$temp = self::subWord(self::rotWord($temp));
for ($t = 0; $t<4;
$t++) {
$temp[$t] ^= self::$rCon[$i/$Nk][$t];
}
} elseif ($Nk > 6 && $i%$Nk == 4) {
$temp = self::subWord($temp);
}
for ($t = 0; $t<4;
$t++) {
$w[$i][$t] = $w[$i-$Nk][$t] ^ $temp[$t];
}
}
return $w;
}
private static function subWord($w)
{
// apply SBox to 4-byte word w
for ($i = 0; $i<4;
$i++) {
$w[$i] = self::$sBox[$w[$i]];
}
return $w;
}
private static function rotWord($w)
{
// rotate 4-byte word w left by one byte
$tmp = $w[0];
for ($i = 0; $i<3;
$i++) {
$w[$i] = $w[$i+1];
}
$w[3] = $tmp;
return $w;
}
// sBox is pre-computed multiplicative inverse in GF(2^8) used in subBytes and keyExpansion [<5B>5.1.1]
private static $sBox = array(
0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16);
// rCon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [<5B>5.2]
private static $rCon = array(
array(0x00, 0x00, 0x00, 0x00),
array(0x01, 0x00, 0x00, 0x00),
array(0x02, 0x00, 0x00, 0x00),
array(0x04, 0x00, 0x00, 0x00),
array(0x08, 0x00, 0x00, 0x00),
array(0x10, 0x00, 0x00, 0x00),
array(0x20, 0x00, 0x00, 0x00),
array(0x40, 0x00, 0x00, 0x00),
array(0x80, 0x00, 0x00, 0x00),
array(0x1b, 0x00, 0x00, 0x00),
array(0x36, 0x00, 0x00, 0x00) );
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

View File

@@ -0,0 +1,205 @@
<?php
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* AES counter (CTR) mode implementation in PHP (c) Chris Veness 2005-2011. Right of free use is */
/* granted for all commercial or non-commercial use under CC-BY licence. No warranty of any */
/* form is offered. */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
namespace Classes\Crypt;
class AesCtr extends Aes
{
/**
* Encrypt a text using AES encryption in Counter mode of operation
* - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
*
* Unicode multi-byte character safe
*
* @param plaintext string source text to be encrypted
* @param password string the password to use to generate a key
* @param nBits number of bits to be used in the key (128, 192, or 256)
* @return string encrypted text
*/
public static function encrypt($plaintext, $password, $nBits)
{
$blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
if (!($nBits==128 || $nBits==192 || $nBits==256)) {
return ''; // standard allows 128/192/256 bit keys
}
// note PHP (5) gives us plaintext and password in UTF8 encoding!
// use AES itself to encrypt password to get cipher key (using plain password as source for
// key expansion) - gives us well encrypted key
$nBytes = $nBits/8; // no bytes in key
$pwBytes = array();
for ($i = 0; $i<$nBytes;
$i++) {
$pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
}
$key = Aes::cipher($pwBytes, Aes::keyExpansion($pwBytes));
$key = array_merge($key, array_slice($key, 0, $nBytes-16)); // expand key to 16/24/32 bytes long
// initialise 1st 8 bytes of counter block with nonce (NIST SP800-38A <20>B.2): [0-1] = millisec,
// [2-3] = random, [4-7] = seconds, giving guaranteed sub-ms uniqueness up to Feb 2106
$counterBlock = array();
$nonce = floor(microtime(true)*1000); // timestamp: milliseconds since 1-Jan-1970
$nonceMs = $nonce%1000;
$nonceSec = floor($nonce/1000);
$nonceRnd = floor(rand(0, 0xffff));
for ($i = 0; $i<2;
$i++) {
$counterBlock[$i] = self::urs($nonceMs, $i*8) & 0xff;
}
for ($i = 0; $i<2;
$i++) {
$counterBlock[$i+2] = self::urs($nonceRnd, $i*8) & 0xff;
}
for ($i = 0; $i<4;
$i++) {
$counterBlock[$i+4] = self::urs($nonceSec, $i*8) & 0xff;
}
// and convert it to a string to go on the front of the ciphertext
$ctrTxt = '';
for ($i = 0; $i<8;
$i++) {
$ctrTxt .= chr($counterBlock[$i]);
}
// generate key schedule - an expansion of the key into distinct Key Rounds for each round
$keySchedule = Aes::keyExpansion($key);
//print_r($keySchedule);
$blockCount = ceil(strlen($plaintext)/$blockSize);
$ciphertxt = array(); // ciphertext as array of strings
for ($b = 0; $b<$blockCount; $b++) {
// set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
// done in two stages for 32-bit ops: using two words allows us to go past 2^32 blocks (68GB)
for ($c = 0; $c<4;
$c++) {
$counterBlock[15-$c] = self::urs($b, $c*8) & 0xff;
}
for ($c = 0; $c<4;
$c++) {
$counterBlock[15-$c-4] = self::urs($b/0x100000000, $c*8);
}
$cipherCntr = Aes::cipher($counterBlock, $keySchedule); // -- encrypt counter block --
// block size is reduced on final block
$blockLength = $b<$blockCount-1 ? $blockSize : (strlen($plaintext)-1)%$blockSize+1;
$cipherByte = array();
for ($i = 0; $i<$blockLength; $i++) { // -- xor plaintext with ciphered counter byte-by-byte --
$cipherByte[$i] = $cipherCntr[$i] ^ ord(substr($plaintext, $b*$blockSize+$i, 1));
$cipherByte[$i] = chr($cipherByte[$i]);
}
$ciphertxt[$b] = implode('', $cipherByte); // escape troublesome characters in ciphertext
}
// implode is more efficient than repeated string concatenation
$ciphertext = $ctrTxt . implode('', $ciphertxt);
$ciphertext = base64_encode($ciphertext);
return $ciphertext;
}
/**
* Decrypt a text encrypted by AES in counter mode of operation
*
* @param ciphertext string source text to be decrypted
* @param password string the password to use to generate a key
* @param nBits number of bits to be used in the key (128, 192, or 256)
* @return string decrypted text
*/
public static function decrypt($ciphertext, $password, $nBits)
{
$blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
if (!($nBits==128 || $nBits==192 || $nBits==256)) {
return ''; // standard allows 128/192/256 bit keys
}
$ciphertext = base64_decode($ciphertext);
// use AES to encrypt password (mirroring encrypt routine)
$nBytes = $nBits/8; // no bytes in key
$pwBytes = array();
for ($i = 0; $i<$nBytes;
$i++) {
$pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
}
$key = Aes::cipher($pwBytes, Aes::keyExpansion($pwBytes));
$key = array_merge($key, array_slice($key, 0, $nBytes-16)); // expand key to 16/24/32 bytes long
// recover nonce from 1st element of ciphertext
$counterBlock = array();
$ctrTxt = substr($ciphertext, 0, 8);
for ($i = 0; $i<8;
$i++) {
$counterBlock[$i] = ord(substr($ctrTxt, $i, 1));
}
// generate key schedule
$keySchedule = Aes::keyExpansion($key);
// separate ciphertext into blocks (skipping past initial 8 bytes)
$nBlocks = ceil((strlen($ciphertext)-8) / $blockSize);
$ct = array();
for ($b = 0; $b<$nBlocks;
$b++) {
$ct[$b] = substr($ciphertext, 8+$b*$blockSize, 16);
}
$ciphertext = $ct; // ciphertext is now array of block-length strings
// plaintext will get generated block-by-block into array of block-length strings
$plaintxt = array();
for ($b = 0; $b<$nBlocks; $b++) {
// set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
for ($c = 0; $c<4;
$c++) {
$counterBlock[15-$c] = self::urs($b, $c*8) & 0xff;
}
for ($c = 0; $c<4;
$c++) {
$counterBlock[15-$c-4] = self::urs(($b+1)/0x100000000-1, $c*8) & 0xff;
}
$cipherCntr = Aes::cipher($counterBlock, $keySchedule); // encrypt counter block
$plaintxtByte = array();
for ($i = 0; $i<strlen($ciphertext[$b]); $i++) {
// -- xor plaintext with ciphered counter byte-by-byte --
$plaintxtByte[$i] = $cipherCntr[$i] ^ ord(substr($ciphertext[$b], $i, 1));
$plaintxtByte[$i] = chr($plaintxtByte[$i]);
}
$plaintxt[$b] = implode('', $plaintxtByte);
}
// join array of blocks into single plaintext string
$plaintext = implode('', $plaintxt);
return $plaintext;
}
/*
* Unsigned right shift function, since PHP has neither >>> operator nor unsigned ints
*
* @param a number to be shifted (32-bit integer)
* @param b number of bits to shift a to the right (0..31)
* @return a right-shifted and zero-filled by b bits
*/
private static function urs($a, $b)
{
$a &= 0xffffffff;
$b &= 0x1f; // (bounds check)
if ($a&0x80000000 && $b>0) { // if left-most bit set
$a = ($a>>1) & 0x7fffffff; // right-shift one bit & clear left-most bit
$a = $a >> ($b-1); // remaining right-shifts
} else { // otherwise
$a = ($a>>$b); // use normal right-shift
}
return $a;
}
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

View File

@@ -0,0 +1,145 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/20/17
* Time: 9:29 AM
*/
namespace Classes;
use Metadata\Common\Model\CustomFieldValue;
use Utils\LogManager;
class CustomFieldManager
{
public function addCustomField($type, $id, $name, $value)
{
if ($name[0] === '/') {
return;
}
$customFieldValue = new CustomFieldValue();
$customFieldValue->Load(
"type = ? and name = ? and object_id = ?",
array($type, $name, $id)
);
if ($customFieldValue->object_id != $id) {
$customFieldValue->name = $name;
$customFieldValue->object_id = $id;
$customFieldValue->type = $type;
$customFieldValue->created = date("Y-m-d H:i:s");
}
$customFieldValue->value = $value;
$customFieldValue->updated = date("Y-m-d H:i:s");
$ok = $customFieldValue->Save();
if (!$ok) {
LogManager::getInstance()->error("Error saving custom field: " . $customFieldValue->ErrorMsg());
return false;
}
return true;
}
public function getCustomFields($type, $id)
{
$customFieldValue = new CustomFieldValue();
$list = $customFieldValue->Find(
"type = ? and object_id = ?",
array($type, $id)
);
return $list;
}
public function enrichObjectCustomFields($table, $object)
{
$customFieldsList = BaseService::getInstance()->getCustomFields($table);
$customFieldsListOrdered = array();
$customFields = array();
foreach ($customFieldsList as $cf) {
$customFields[$cf->name] = $cf;
}
$customFieldValues = $this->getCustomFields($table, $object->id);
$object->customFields = array();
foreach ($customFieldValues as $cf) {
if (!isset($customFields[$cf->name])) {
continue;
}
$type = $customFields[$cf->name]->field_type;
$label = $customFields[$cf->name]->field_label;
$order = $customFields[$cf->name]->display_order;
$section = $customFields[$cf->name]->display_section;
$customFieldsListOrdered[] = $order;
if ($type == "text" || $type == "textarea") {
$object->customFields[$label] = $cf->value;
} elseif ($type == 'select' || $type == 'select2') {
$options = $customFields[$cf->name]->field_options;
if (empty($options)) {
continue;
}
$jsonOptions = json_decode($options);
foreach ($jsonOptions as $option) {
if ($option->value == $cf->value) {
$object->customFields[$label] = $option->label;
}
}
} elseif ($type == 'select2multi') {
$resArr = array();
$options = $customFields[$cf->name]->field_options;
if (empty($options) || empty($cf->value)) {
continue;
}
$jsonOptions = json_decode($options);
$jsonOptionsKeys = array();
foreach ($jsonOptions as $option) {
$jsonOptionsKeys[$option->value] = $option->label;
}
$valueList = json_decode($cf->value, true);
foreach ($valueList as $val) {
if (!isset($jsonOptionsKeys[$val])) {
$resArr[] = $val;
} else {
$resArr[] = $jsonOptionsKeys[$val];
}
}
$object->customFields[$label] = implode('<br/>', $resArr);
} elseif ($type == "date") {
if (!empty($cf->value)) {
$object->customFields[$label] = $cf->value;
} else {
$object->customFields[$label] = date("F j, Y", strtotime($cf->value));
}
} elseif ($type == "datetime") {
if (!empty($cf->value)) {
$object->customFields[$label] = $cf->value;
} else {
$object->customFields[$label] = date("F j, Y, g:i a", strtotime($cf->value));
}
} elseif ($type == "time") {
if (!empty($cf->value)) {
$object->customFields[$label] = $cf->value;
} else {
$object->customFields[$label] = date("g:i a", strtotime($cf->value));
}
}
$object->customFields[$label] = array($object->customFields[$label], $section);
}
array_multisort($customFieldsListOrdered, SORT_DESC, SORT_NUMERIC, $object->customFields);
return $object;
}
public function syncMigrations()
{
}
}

View File

@@ -0,0 +1,195 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/20/17
* Time: 9:38 AM
*/
namespace Classes\Email;
use Classes\Crypt\AesCtr;
use Classes\UIManager;
use Employees\Common\Model\Employee;
use Users\Common\Model\User;
abstract class EmailSender
{
/* @var \Classes\SettingsManager $settings */
public $settings = null;
public function __construct($settings)
{
$this->settings = $settings;
}
public function sendEmailFromNotification($notification)
{
$toEmail = null;
$user = new User();
$user->Load("id = ?", array($notification->toUser));
if (!empty($user->email)) {
$name = "User";
$employee = new Employee();
$employee->Load("id = ?", array($user->employee));
if ($employee->id == $user->employee && !empty($employee->id)) {
$name = $employee->first_name;
}
$action = json_decode($notification->action);
$emailBody = file_get_contents(APP_BASE_PATH.'/templates/email/notificationEmail.html');
$emailBody = str_replace("#_user_#", $name, $emailBody);
$emailBody = str_replace("#_message_#", $notification->message, $emailBody);
if ($action->type == "url") {
$emailBody = str_replace("#_url_#", CLIENT_BASE_URL."?".$action->url, $emailBody);
}
$this->sendEmail(
'IceHrm Notification from '.$notification->type,
$user->email,
$emailBody,
array(),
array(),
array()
);
}
}
public function sendEmailFromDB($email)
{
$params = array();
if (!empty($email->params)) {
$params = json_decode($email->params, true);
}
$cclist = array();
if (!empty($email->cclist)) {
$cclist = json_decode($email->cclist, true);
}
$bcclist = array();
if (!empty($email->bcclist)) {
$bcclist = json_decode($email->bcclist, true);
}
return $this->sendEmail($email->subject, $email->toEmail, $email->template, $params, $cclist, $bcclist);
}
public function sendEmail($subject, $toEmail, $template, $params, $ccList = array(), $bccList = array())
{
$body = $template;
foreach ($params as $k => $v) {
$body = str_replace("#_".$k."_#", $v, $body);
}
$fromEmail = $this->settings->getSetting("Email: Email From");
//Convert to an html email
$emailBody = file_get_contents(APP_BASE_PATH.'/templates/email/emailBody.html');
$emailBody = str_replace("#_emailBody_#", $body, $emailBody);
$emailBody = str_replace(
"#_logourl_#",
UIManager::getInstance()->getCompanyLogoUrl(),
$emailBody
);
$user = new User();
$user->Load("username = ?", array('admin'));
if (empty($user->id)) {
$users = $user->Find("user_level = ?", array('Admin'));
$user = $users[0];
}
$emailBody = str_replace("#_adminEmail_#", $user->email, $emailBody);
$emailBody = str_replace("#_url_#", CLIENT_BASE_URL, $emailBody);
foreach ($params as $k => $v) {
$emailBody = str_replace("#_".$k."_#", $v, $emailBody);
}
return $this->sendMail($subject, $emailBody, $toEmail, $fromEmail, $user->email, $ccList, $bccList, APP_NAME);
}
public function sendEmailWithoutWrap($subject, $toEmail, $template, $params, $ccList = array(), $bccList = array())
{
$body = $template;
foreach ($params as $k => $v) {
$body = str_replace("#_".$k."_#", $v, $body);
}
$fromEmail = APP_NAME." <".$this->settings->getSetting("Email: Email From").">";
//Convert to an html email
$emailBody = $body;
$emailBody = str_replace(
"#_logourl_#",
UIManager::getInstance()->getCompanyLogoUrl(),
$emailBody
);
$user = new User();
$user->Load("username = ?", array('admin'));
if (empty($user->id)) {
$users = $user->Find("user_level = ?", array('Admin'));
$user = $users[0];
}
$emailBody = str_replace("#_adminEmail_#", $user->email, $emailBody);
$emailBody = str_replace("#_url_#", CLIENT_BASE_URL, $emailBody);
foreach ($params as $k => $v) {
$emailBody = str_replace("#_".$k."_#", $v, $emailBody);
}
$this->sendMail($subject, $emailBody, $toEmail, $fromEmail, $user->email, $ccList, $bccList);
}
abstract protected function sendMail(
$subject,
$body,
$toEmail,
$fromEmail,
$replyToEmail = null,
$ccList = array(),
$bccList = array(),
$fromName = null
);
public function sendResetPasswordEmail($emailOrUserId)
{
$user = new User();
$user->Load("email = ?", array($emailOrUserId));
if (empty($user->id)) {
$user = new User();
$user->Load("username = ?", array($emailOrUserId));
if (empty($user->id)) {
return false;
}
}
$params = array();
//$params['user'] = $user->first_name." ".$user->last_name;
$params['url'] = CLIENT_BASE_URL;
$newPassHash = array();
$newPassHash["CLIENT_NAME"] = CLIENT_NAME;
$newPassHash["oldpass"] = $user->password;
$newPassHash["email"] = $user->email;
$newPassHash["time"] = time();
$json = json_encode($newPassHash);
$encJson = AesCtr::encrypt($json, $user->password, 256);
$encJson = urlencode($user->id."-".$encJson);
$params['passurl'] = CLIENT_BASE_URL."service.php?a=rsp&key=".$encJson;
$emailBody = file_get_contents(APP_BASE_PATH.'/templates/email/passwordReset.html');
$this->sendEmail("[".APP_NAME."] Password Change Request", $user->email, $emailBody, $params);
return true;
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/20/17
* Time: 9:40 AM
*/
namespace Classes\Email;
use Utils\LogManager;
class PHPMailer extends EmailSender
{
public function __construct($settings)
{
parent::__construct($settings);
}
protected function sendMail(
$subject,
$body,
$toEmail,
$fromEmail,
$replyToEmail = null,
$ccList = array(),
$bccList = array(),
$fromName = null
) {
try {
if ($fromName) {
$fromEmail = $fromName." <".$fromEmail.">";
}
if (empty($replyToEmail)) {
$replyToEmail = $fromEmail;
}
LogManager::getInstance()->info("Sending email to: " . $toEmail . "/ from: " . $fromEmail);
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
$headers .= 'From: ' . $fromEmail . "\r\n";
if (!empty($ccList)) {
$headers .= 'CC: ' . implode(",", $ccList) . "\r\n";
}
if (!empty($bccList)) {
$headers .= 'BCC: ' . implode(",", $bccList) . "\r\n";
}
$headers .= 'ReplyTo: ' . $replyToEmail . "\r\n";
$headers .= 'Ice-Mailer: PHP/' . phpversion();
return mail($toEmail, $subject, $body, $headers);
} catch (\Exception $e) {
LogManager::getInstance()->error("Error sending email:" . $e->getMessage());
return false;
}
}
}

View File

@@ -0,0 +1,89 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/20/17
* Time: 9:39 AM
*/
namespace Classes\Email;
use Utils\LogManager;
class SMTPEmailSender extends EmailSender
{
public function __construct($settings)
{
parent::__construct($settings);
}
protected function sendMail(
$subject,
$body,
$toEmail,
$fromEmail,
$replyToEmail = null,
$ccList = array(),
$bccList = array(),
$fromName = ''
) {
try {
if (empty($replyToEmail)) {
$replyToEmail = $fromEmail;
}
LogManager::getInstance()->info("Sending email to: " . $toEmail . "/ from: " . $fromEmail);
$host = $this->settings->getSetting("Email: SMTP Host");
$username = $this->settings->getSetting("Email: SMTP User");
$password = $this->settings->getSetting("Email: SMTP Password");
$port = $this->settings->getSetting("Email: SMTP Port");
if (empty($port)) {
$port = '25';
}
if ($this->settings->getSetting("Email: SMTP Authentication Required") == "0") {
$auth = array('host' => $host,
'auth' => false);
} else {
$auth = array('host' => $host,
'auth' => true,
'username' => $username,
'port' => $port,
'password' => $password);
}
$smtp = \Mail::factory('smtp', $auth);
$headers = array('MIME-Version' => '1.0',
'Content-type' => 'text/html',
'charset' => 'iso-8859-1',
'From' => $fromEmail,
'To' => $toEmail,
'Reply-To' => $replyToEmail,
'Subject' => $subject);
if (!empty($ccList)) {
$headers['Cc'] = implode(",", $ccList);
}
if (!empty($bccList)) {
$headers['Bcc'] = implode(",", $bccList);
}
$mail = $smtp->send($toEmail, $headers, $body);
if (\PEAR::isError($mail)) {
LogManager::getInstance()->info("SMTP Error Response:" . $mail->getMessage());
return false;
}
return true;
} catch (\Exception $e) {
LogManager::getInstance()->error("Error sending email:" . $e->getMessage());
return false;
}
}
}

View File

@@ -0,0 +1,83 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/20/17
* Time: 9:39 AM
*/
namespace Classes\Email;
use Aws\Ses\SesClient;
use Utils\LogManager;
class SNSEmailSender extends EmailSender
{
private $ses = null;
public function __construct($settings)
{
parent::__construct($settings);
$arr = array(
'key' => $this->settings->getSetting('Email: Amazon Access Key ID'),
'secret' => $this->settings->getSetting('Email: Amazon Secret Access Key'),
'region' => AWS_REGION
);
$this->ses = SesClient::factory($arr);
}
protected function sendMail(
$subject,
$body,
$toEmail,
$fromEmail,
$replyToEmail = null,
$ccList = array(),
$bccList = array(),
$fromName = null
) {
try {
if ($fromName) {
$fromEmail = $fromName." <".$fromEmail.">";
}
if (empty($replyToEmail)) {
$replyToEmail = $fromEmail;
}
LogManager::getInstance()->info("Sending email to: " . $toEmail . "/ from: " . $fromEmail);
$toArray = array('ToAddresses' => array($toEmail),
'CcAddresses' => $ccList,
'BccAddresses' => $bccList);
$message = array(
'Subject' => array(
'Data' => $subject,
'Charset' => 'UTF-8'
),
'Body' => array(
'Html' => array(
'Data' => $body,
'Charset' => 'UTF-8'
)
)
);
$response = $this->ses->sendEmail(
array(
'Source' => $fromEmail,
'Destination' => $toArray,
'Message' => $message,
'ReplyToAddresses' => array($replyToEmail),
'ReturnPath' => $fromEmail
)
);
LogManager::getInstance()->info("SES Response:" . print_r($response, true));
return true;
} catch (\Exception $e) {
LogManager::getInstance()->error("Error sending email:" . $e->getMessage());
return false;
}
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace Classes\Email;
use Utils\LogManager;
class SwiftMailer extends EmailSender
{
public function __construct($settings)
{
parent::__construct($settings);
}
protected function sendMail(
$subject,
$body,
$toEmail,
$fromEmail,
$replyToEmail = null,
$ccList = array(),
$bccList = array(),
$fromName = null
) {
try {
if (empty($replyToEmail)) {
$replyToEmail = $fromEmail;
}
LogManager::getInstance()->info("Sending email to: " . $toEmail . "/ from: " . $fromEmail);
$host = $this->settings->getSetting("Email: SMTP Host");
$username = $this->settings->getSetting("Email: SMTP User");
$password = $this->settings->getSetting("Email: SMTP Password");
$port = $this->settings->getSetting("Email: SMTP Port");
if (empty($port)) {
$port = '25';
}
$transport = new \Swift_SmtpTransport($host, $port);
$mail = new \Swift_Message();
if ($this->settings->getSetting("Email: SMTP Authentication Required") === "1") {
$transport->setUsername($username);
$transport->setPassword($password);
}
$mail->addFrom($fromEmail, $fromName);
$mail->addReplyTo($replyToEmail);
$mail->addTo($toEmail);
$mail->setSubject($subject);
$mail->setCc($ccList);
$mail->setBcc($bccList);
$mail->setBody($body);
$mailer = new \Swift_Mailer($transport);
return $mailer->send($mail);
} catch (\Exception $e) {
LogManager::getInstance()->error("Error sending email:" . $e->getMessage());
return false;
}
}
}

View File

@@ -0,0 +1,341 @@
<?php
/*
This file is part of Ice Framework.
Ice Framework is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Ice Framework is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Ice Framework. If not, see <http://www.gnu.org/licenses/>.
------------------------------------------------------------------
Original work Copyright (c) 2012 [Gamonoid Media Pvt. Ltd]
Developer: Thilina Hasantha (thilina.hasantha[at]gmail.com / facebook.com/thilinah)
*/
namespace Classes;
use Model\File;
use Utils\LogManager;
class FileService
{
private static $me = null;
private $memcache;
private function __construct()
{
}
public static function getInstance()
{
if (empty(self::$me)) {
self::$me = new FileService();
}
return self::$me;
}
public function getFromCache($key)
{
try {
$data = MemcacheService::getInstance()->get($key);
if (!empty($data)) {
return $data;
}
return null;
} catch (\Exception $e) {
return null;
}
}
public function saveInCache($key, $data, $expire)
{
if (!class_exists('\\Memcached')) {
return;
}
try {
if (empty($this->memcache)) {
$this->memcache = new \Memcached();
$this->memcache->addServer(GLOB_MEMCACHE_SERVER, 11211);
}
$this->memcache->set($key, $data, $expire);
} catch (\Exception $e) {
}
}
public function checkAddSmallProfileImage($profileImage)
{
$file = new File();
$file->Load('name = ?', array($profileImage->name."_small"));
if (empty($file->id)) {
LogManager::getInstance()->info("Small profile image ".$profileImage->name."_small not found");
$largeFileUrl = $this->getFileUrl($profileImage->name);
$file->name = $profileImage->name."_small";
$signInMappingField = SIGN_IN_ELEMENT_MAPPING_FIELD_NAME;
$file->$signInMappingField = $profileImage->$signInMappingField;
$file->filename = $file->name.str_replace($profileImage->name, "", $profileImage->filename);
$file->file_group = $profileImage->file_group;
file_put_contents("/tmp/".$file->filename."_orig", file_get_contents($largeFileUrl));
if (file_exists("/tmp/".$file->filename."_orig")) {
//Resize image to 100
$img = new \Classes\SimpleImage("/tmp/".$file->filename."_orig");
$img->fitToWidth(100);
$img->save("/tmp/".$file->filename);
$uploadFilesToS3Key = SettingsManager::getInstance()->getSetting(
"Files: Amazon S3 Key for File Upload"
);
$uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting(
"Files: Amazone S3 Secret for File Upload"
);
$s3Bucket = SettingsManager::getInstance()->getSetting("Files: S3 Bucket");
$uploadname = CLIENT_NAME."/".$file->filename;
$localFile = "/tmp/".$file->filename;
$s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret);
$result = $s3FileSys->putObject($s3Bucket, $uploadname, $localFile, 'authenticated-read');
unlink("/tmp/".$file->filename);
unlink("/tmp/".$file->filename."_orig");
LogManager::getInstance()->info("Upload Result:".print_r($result, true));
if (!empty($result)) {
$file->Save();
}
return $file;
}
return null;
}
return $file;
}
public function updateSmallProfileImage($profile)
{
$file = new File();
$file->Load('name = ?', array('profile_image_'.$profile->id));
if ($file->name == 'profile_image_'.$profile->id) {
$uploadFilesToS3 = SettingsManager::getInstance()->getSetting("Files: Upload Files to S3");
if ($uploadFilesToS3 == "1") {
try {
$fileNew = $this->checkAddSmallProfileImage($file);
if (!empty($fileNew)) {
$file = $fileNew;
}
$uploadFilesToS3Key = SettingsManager::getInstance()->getSetting(
"Files: Amazon S3 Key for File Upload"
);
$uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting(
"Files: Amazone S3 Secret for File Upload"
);
$s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret);
$s3WebUrl = SettingsManager::getInstance()->getSetting("Files: S3 Web Url");
$fileUrl = $s3WebUrl.CLIENT_NAME."/".$file->filename;
$expireUrl = $this->getFromCache($fileUrl);
if (empty($expireUrl)) {
$expireUrl = $s3FileSys->generateExpiringURL($fileUrl, 600);
$this->saveInCache($fileUrl, $expireUrl, 500);
}
$profile->image = $expireUrl;
} catch (\Exception $e) {
LogManager::getInstance()->error("Error generating profile image: ".$e->getMessage());
if ($profile->gender == 'Female') {
$profile->image = BASE_URL."images/user_female.png";
} else {
$profile->image = BASE_URL."images/user_male.png";
}
}
} else {
$profile->image = CLIENT_BASE_URL.'data/'.$file->filename;
}
} else {
if ($profile->gender == 'Female') {
$profile->image = BASE_URL."images/user_female.png";
} else {
$profile->image = BASE_URL."images/user_male.png";
}
}
return $profile;
}
public function updateProfileImage($profile)
{
$file = new File();
$file->Load('name = ?', array('profile_image_'.$profile->id));
if ($file->name == 'profile_image_'.$profile->id) {
$uploadFilesToS3 = SettingsManager::getInstance()->getSetting("Files: Upload Files to S3");
if ($uploadFilesToS3 == "1") {
$uploadFilesToS3Key = SettingsManager::getInstance()->getSetting(
"Files: Amazon S3 Key for File Upload"
);
$uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting(
"Files: Amazone S3 Secret for File Upload"
);
$s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret);
$s3WebUrl = SettingsManager::getInstance()->getSetting("Files: S3 Web Url");
$fileUrl = $s3WebUrl.CLIENT_NAME."/".$file->filename;
$expireUrl = $this->getFromCache($fileUrl);
if (empty($expireUrl)) {
$expireUrl = $s3FileSys->generateExpiringURL($fileUrl, 600);
$this->saveInCache($fileUrl, $expireUrl, 500);
}
$profile->image = $expireUrl;
} else {
$profile->image = CLIENT_BASE_URL.'data/'.$file->filename;
}
} else {
if ($profile->gender == 'Female') {
$profile->image = BASE_URL."images/user_female.png";
} else {
$profile->image = BASE_URL."images/user_male.png";
}
}
return $profile;
}
public function getFileUrl($fileName)
{
$file = new File();
$file->Load('name = ?', array($fileName));
$uploadFilesToS3 = SettingsManager::getInstance()->getSetting("Files: Upload Files to S3");
if ($uploadFilesToS3 == "1") {
$uploadFilesToS3Key = SettingsManager::getInstance()->getSetting(
"Files: Amazon S3 Key for File Upload"
);
$uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting(
"Files: Amazone S3 Secret for File Upload"
);
$s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret);
$s3WebUrl = SettingsManager::getInstance()->getSetting("Files: S3 Web Url");
$fileUrl = $s3WebUrl.CLIENT_NAME."/".$file->filename;
$expireUrl = $this->getFromCache($fileUrl);
if (empty($expireUrl)) {
$expireUrl = $s3FileSys->generateExpiringURL($fileUrl, 600);
$this->saveInCache($fileUrl, $expireUrl, 500);
}
return $expireUrl;
} else {
return CLIENT_BASE_URL.'data/'.$file->filename;
}
}
public function deleteProfileImage($profileId)
{
$file = new File();
$file->Load('name = ?', array('profile_image_'.$profileId));
if ($file->name == 'profile_image_'.$profileId) {
$ok = $file->Delete();
if ($ok) {
LogManager::getInstance()->info("Delete File:".CLIENT_BASE_PATH.$file->filename);
unlink(CLIENT_BASE_PATH.'data/'.$file->filename);
} else {
return false;
}
}
$file = new File();
$file->Load('name = ?', array('profile_image_'.$profileId."_small"));
if ($file->name == 'profile_image_'.$profileId."_small") {
$ok = $file->Delete();
if ($ok) {
LogManager::getInstance()->info("Delete File:".CLIENT_BASE_PATH.$file->filename);
unlink(CLIENT_BASE_PATH.'data/'.$file->filename);
} else {
return false;
}
}
return true;
}
public function deleteFileByField($value, $field)
{
LogManager::getInstance()->info("Delete file by field: $field / value: $value");
$file = new File();
$file->Load("$field = ?", array($value));
if ($file->$field == $value) {
$ok = $file->Delete();
if ($ok) {
$uploadFilesToS3 = SettingsManager::getInstance()->getSetting("Files: Upload Files to S3");
if ($uploadFilesToS3 == "1") {
$uploadFilesToS3Key = SettingsManager::getInstance()->getSetting(
"Files: Amazon S3 Key for File Upload"
);
$uploadFilesToS3Secret = SettingsManager::getInstance()->getSetting(
"Files: Amazone S3 Secret for File Upload"
);
$s3Bucket = SettingsManager::getInstance()->getSetting("Files: S3 Bucket");
$uploadname = CLIENT_NAME."/".$file->filename;
LogManager::getInstance()->info("Delete from S3:".$uploadname);
$s3FileSys = new S3FileSystem($uploadFilesToS3Key, $uploadFilesToS3Secret);
$s3FileSys->deleteObject($s3Bucket, $uploadname);
} else {
LogManager::getInstance()->info("Delete:".CLIENT_BASE_PATH.'data/'.$file->filename);
unlink(CLIENT_BASE_PATH.'data/'.$file->filename);
}
} else {
return false;
}
}
return true;
}
public function getFileData($name)
{
$file = new File();
$file->Load("name = ?", array($name));
if (!empty($file->id)) {
$arr = explode(".", $file->filename);
$file->type = $arr[count($arr) - 1];
} else {
return null;
}
return $file;
}
public function getReadableSize($size, $precision = 2)
{
$base = log($size, 1024);
$suffixes = array('', 'K', 'M', 'G', 'T');
return round(pow(1024, $base - floor($base)), $precision) .' '. $suffixes[floor($base)];
}
}

View File

@@ -0,0 +1,14 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/20/17
* Time: 9:31 AM
*/
namespace Classes;
interface HistoryManager
{
public function addHistory($type, $refId, $field, $oldValue, $newValue);
}

View File

@@ -0,0 +1,23 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/20/17
* Time: 9:30 AM
*/
namespace Classes;
class IceConstants
{
const AUDIT_AUTHENTICATION = "Authentication";
const AUDIT_ADD = "Add";
const AUDIT_EDIT = "Edit";
const AUDIT_DELETE = "Delete";
const AUDIT_ERROR = "Error";
const AUDIT_ACTION = "User Action";
const NOTIFICATION_LEAVE = "Leave Module";
const NOTIFICATION_TIMESHEET = "Time Module";
const NOTIFICATION_TRAINING = "Training Module";
}

View File

@@ -0,0 +1,76 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/20/17
* Time: 9:50 AM
*/
namespace Classes;
class IceResponse
{
const SUCCESS = "SUCCESS";
const ERROR = "ERROR";
public $status;
public $data;
public $code;
public function __construct($status, $data = null, $code = null)
{
$this->status = $status;
$this->data = $data;
$this->code = $code;
}
public function getStatus()
{
return $this->status;
}
public function getData()
{
return $this->data;
}
public function getObject()
{
return $this->data;
}
public function getCode()
{
return $this->code;
}
public function getJsonArray()
{
return array("status"=>$this->status,"data"=>$this->data);
}
/**
* @param mixed $status
*/
public function setStatus($status)
{
$this->status = $status;
}
/**
* @param null $data
*/
public function setData($data)
{
$this->data = $data;
}
/**
* @param null $code
*/
public function setCode($code)
{
$this->code = $code;
}
}

View File

@@ -0,0 +1,84 @@
<?php
namespace Classes;
use Utils\LogManager;
class LDAPManager
{
private static $me = null;
private function __construct()
{
}
public static function getInstance()
{
if (empty(self::$me)) {
self::$me = new LDAPManager();
}
return self::$me;
}
public function checkLDAPLogin($user, $password)
{
$ldap_host = SettingsManager::getInstance()->getSetting("LDAP: Server");
$ldap_port = SettingsManager::getInstance()->getSetting("LDAP: Port");
$ldap_dn = SettingsManager::getInstance()->getSetting("LDAP: Root DN");
$managerDN = SettingsManager::getInstance()->getSetting("LDAP: Manager DN");
$managerPassword = SettingsManager::getInstance()->getSetting("LDAP: Manager Password");
// connect to active directory
if (empty($ldap_port)) {
$ldap_port = 389;
}
$ldap = ldap_connect($ldap_host, intval($ldap_port));
if (!$ldap) {
return new IceResponse(IceResponse::ERROR, "Could not connect to LDAP Server");
}
LogManager::getInstance()->debug("LDAP Connect Result:".print_r($ldap, true));
if (SettingsManager::getInstance()->getSetting("LDAP: Version 3") == "1") {
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
}
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
// verify user and password
$bind = @ldap_bind($ldap, $managerDN, $managerPassword);
LogManager::getInstance()->debug("LDAP Manager Bind:".print_r($bind, true));
if ($bind) {
$userFilterStr = SettingsManager::getInstance()->getSetting("LDAP: User Filter");
$filter = str_replace("{}", $user, $userFilterStr); //"(uid=" . $user . ")";
$result = ldap_search($ldap, $ldap_dn, $filter);
LogManager::getInstance()->debug("LDAP Search Result:".print_r($result, true));
if (!$result) {
exit("Unable to search LDAP server");
}
$entries = ldap_get_entries($ldap, $result);
LogManager::getInstance()->debug("LDAP Search Entries:".print_r($entries, true));
if (empty($entries) || !isset($entries[0]) || !isset($entries[0]['dn'])) {
return new IceResponse(IceResponse::ERROR, "Invalid user");
}
$bind = @ldap_bind($ldap, $entries[0]['dn'], $password);
ldap_unbind($ldap);
if ($bind) {
return new IceResponse(IceResponse::SUCCESS, $entries[0]);
} else {
return new IceResponse(IceResponse::ERROR, "Invalid user");
}
} else {
return new IceResponse(IceResponse::ERROR, "Invalid manager user");
}
}
}

View File

@@ -0,0 +1,99 @@
<?php
namespace Classes;
use Gettext\Generators\Json;
use Gettext\Translations;
use Gettext\Translator;
use Metadata\Common\Model\SupportedLanguage;
use Utils\LogManager;
class LanguageManager
{
private static $me = [];
/* @var \Gettext\Translator $translator */
private $translator = null;
/* @var \Gettext\Translations $translations */
private $translations = null;
private function __construct()
{
}
private static function getInstance($lang = null)
{
if ($lang === null) {
$lang = self::getCurrentLang();
}
if (empty(self::$me[$lang])) {
self::$me[$lang] = new LanguageManager();
self::$me[$lang]->initialize($lang);
}
return self::$me[$lang];
}
private function initialize($lang)
{
$this->loadLanguage($lang);
}
public function loadLanguage($lang)
{
$this->translations = Translations::fromPoFile(APP_BASE_PATH.'lang/'.$lang.'.po');
$t = new Translator();
$t->loadTranslations($this->translations);
$t->register();
$this->translator = $t;
}
private static function getCurrentLang()
{
$user = BaseService::getInstance()->getCurrentUser();
if (empty($user) || empty($user->lang) || $user->lang == "NULL") {
$lang = SettingsManager::getInstance()->getSetting('System: Language');
LogManager::getInstance()->info("System Lang:".$lang);
} else {
$supportedLang = new SupportedLanguage();
$supportedLang->Load("id = ?", array($user->lang));
$lang = $supportedLang->name;
}
if (empty($lang) || !file_exists(APP_BASE_PATH.'lang/'.$lang.'.po')) {
$lang = 'en';
}
return $lang;
}
public static function getTranslations($lang = null)
{
$me = self::getInstance($lang);
return Json::toString($me->translations);
}
public static function getTranslationsObject($lang = null)
{
$me = self::getInstance($lang);
return $me->translations;
}
public static function tran($text)
{
$me = self::getInstance();
return $me->translator->gettext($text);
}
public static function translateTnrText($string)
{
$me = self::getInstance();
$pattern = "#<t>(.*?)</t>#";
preg_match_all($pattern, $string, $matches);
for ($i = 0; $i<count($matches[0]); $i++) {
$tagVal = $matches[1][$i];
$fullVal = $matches[0][$i];
$string = str_replace($fullVal, $me::tran($tagVal), $string);
}
return $string;
}
}

177
core/src/Classes/Macaw.php Executable file
View File

@@ -0,0 +1,177 @@
<?php
namespace Classes;
/**
* @method static Macaw get(string $route, Callable $callback)
* @method static Macaw post(string $route, Callable $callback)
* @method static Macaw put(string $route, Callable $callback)
* @method static Macaw delete(string $route, Callable $callback)
* @method static Macaw options(string $route, Callable $callback)
* @method static Macaw head(string $route, Callable $callback)
*/
class Macaw
{
public static $halts = false;
public static $routes = array();
public static $methods = array();
public static $callbacks = array();
public static $patterns = array(
':any' => '[^/]+',
':num' => '[0-9]+',
':all' => '.*'
);
public static $error_callback;
/**
* Defines a route w/ callback and method
*/
public static function __callstatic($method, $params)
{
$uri = dirname($_SERVER['PHP_SELF']).$params[0];
$callback = $params[1];
array_push(self::$routes, $uri);
array_push(self::$methods, strtoupper($method));
array_push(self::$callbacks, $callback);
}
/**
* Defines callback if route is not found
*/
public static function error($callback)
{
self::$error_callback = $callback;
}
public static function haltOnMatch($flag = true)
{
self::$halts = $flag;
}
/**
* Runs the callback for the given request
*/
public static function dispatch()
{
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$method = $_SERVER['REQUEST_METHOD'];
$searches = array_keys(static::$patterns);
$replaces = array_values(static::$patterns);
$found_route = false;
self::$routes = str_replace('//', '/', self::$routes);
// check if route is defined without regex
if (in_array($uri, self::$routes)) {
$route_pos = array_keys(self::$routes, $uri);
foreach ($route_pos as $route) {
//using an ANY option to match both GET and POST requests
if (self::$methods[$route] == $method || self::$methods[$route] == 'ANY') {
$found_route = true;
//if route is not an object
if (!is_object(self::$callbacks[$route])) {
//grab all parts based on a / separator
$parts = explode('/', self::$callbacks[$route]);
//collect the last index of the array
$last = end($parts);
//grab the controller name and method call
$segments = explode('@', $last);
//instanitate controller
$controller = new $segments[0]();
//call method
$controller->$segments[1]();
if (self::$halts) {
return;
}
} else {
//call closure
call_user_func(self::$callbacks[$route]);
if (self::$halts) {
return;
}
}
}
}
} else {
// check if defined with regex
$pos = 0;
foreach (self::$routes as $route) {
if (strpos($route, ':') !== false) {
$route = str_replace($searches, $replaces, $route);
}
if (preg_match('#^' . $route . '$#', $uri, $matched)) {
if (self::$methods[$pos] == $method) {
$found_route = true;
array_shift($matched); //remove $matched[0] as [1] is the first parameter.
if (!is_object(self::$callbacks[$pos])) {
//grab all parts based on a / separator
$parts = explode('/', self::$callbacks[$pos]);
//collect the last index of the array
$last = end($parts);
//grab the controller name and method call
$segments = explode('@', $last);
//instanitate controller
$controller = new $segments[0]();
//fix multi parameters
if (!method_exists($controller, $segments[1])) {
echo "controller and action not found";
} else {
call_user_func_array(array($controller, $segments[1]), $matched);
}
//call method and pass any extra parameters to the method
// $controller->$segments[1](implode(",", $matched));
if (self::$halts) {
return;
}
} else {
call_user_func_array(self::$callbacks[$pos], $matched);
if (self::$halts) {
return;
}
}
}
}
$pos++;
}
}
// run the error callback if the route was not found
if ($found_route == false) {
if (!self::$error_callback) {
self::$error_callback = function () {
header($_SERVER['SERVER_PROTOCOL']." 404 Not Found");
echo '404';
};
}
call_user_func(self::$error_callback);
}
}
}

View File

@@ -0,0 +1,99 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/20/17
* Time: 9:29 AM
*/
namespace Classes;
class MemcacheService
{
private $connection = null;
public static $openConnections = array();
private static $me = null;
private function __construct()
{
}
public static function getInstance()
{
if (self::$me == null) {
self::$me = new MemcacheService();
}
return self::$me;
}
private function connect()
{
if ($this->connection == null) {
$this->connection = new \Memcached();
$this->connection->addServer(MEMCACHE_HOST, MEMCACHE_PORT);
if (!$this->isConnected()) {
$this->connection = null;
} else {
self::$openConnections[] = $this->connection;
}
}
return $this->connection;
}
private function isConnected()
{
$statuses = $this->connection->getStats();
return isset($statuses[MEMCACHE_HOST.":".MEMCACHE_PORT]);
}
private function compressKey($key)
{
return crc32(APP_DB.$key).md5(CLIENT_NAME);
}
public function set($key, $value, $expiry = 3600)
{
if (!class_exists('\\Memcached')) {
return false;
}
$key = $this->compressKey($key);
$memcache = $this->connect();
if (!empty($memcache) && $this->isConnected()) {
$ok = $memcache->set($key, $value, time() + $expiry);
if (!$ok) {
return false;
}
return true;
}
return false;
}
public function get($key)
{
if (!class_exists('\\Memcached')) {
return false;
}
$key = $this->compressKey($key);
$memcache = $this->connect();
if (!empty($memcache) && $this->isConnected()) {
return $memcache->get($key);
} else {
return false;
}
}
public function close()
{
if ($this->connection != null) {
if ($this->isConnected()) {
$this->connection->quit();
}
$this->connection = null;
}
}
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/20/17
* Time: 9:51 AM
*/
namespace Classes;
class MenuItemTemplate
{
public $templateName;
public $params;
public function __construct($templateName, $params)
{
$this->templateName = $templateName;
$this->params = $params;
}
public function getHtml()
{
return UIManager::getInstance()->populateTemplate($this->templateName, 'menu', $this->params);
}
}

View File

@@ -0,0 +1,56 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/20/17
* Time: 9:44 AM
*/
namespace Classes\Migration;
abstract class AbstractMigration
{
protected $file;
private $db;
protected $lastError;
public function __construct($file)
{
$this->file = $file;
}
public function up()
{
return true;
}
public function down()
{
return true;
}
protected function db()
{
if ($this->db == null) {
$this->db = NewADOConnection('mysqli');
$res = $this->db->Connect(APP_HOST, APP_USERNAME, APP_PASSWORD, APP_DB);
}
return $this->db;
}
public function getLastError()
{
return $this->lastError;
}
public function executeQuery($sql)
{
$ret = $this->db()->Execute($sql);
if (!$ret) {
$this->lastError = $this->db()->ErrorMsg();
}
return $ret;
}
}

View File

@@ -0,0 +1,234 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/20/17
* Time: 9:45 AM
*/
namespace Classes\Migration;
use Model\Migration;
use Utils\LogManager;
class MigrationManager
{
private $migrationPath;
protected $db = null;
public function setMigrationPath($migrationPath)
{
$this->migrationPath = $migrationPath;
}
public function getMigrationById($id)
{
$migration = new Migration();
$migration->Load("id = ?", array($id));
return $migration;
}
public function getCurrentMigrations()
{
$migration = new Migration();
return $migration->Find("1 = 1");
}
public function getPendingMigrations()
{
$migration = new Migration();
return $migration->Find("status = ?", array('Pending'));
}
public function getFirstAddedMigration($statuses)
{
$migration = new Migration();
return $migration->Find("status in ('".implode("','", $statuses)."') order by created limit 1", array());
}
public function getLastRunMigration($statuses)
{
$migration = new Migration();
return $migration->Find("status in ('".implode("','", $statuses)."') order by updated desc limit 1", array());
}
public function queueMigrations()
{
$migrations = array();
$ams = scandir($this->migrationPath);
foreach ($ams as $am) {
if (is_file($this->migrationPath . $am) && $am !== '.' && $am !== '..' && !empty($am)) {
$migrations[$am] = $this->migrationPath . $am;
}
}
ksort($migrations);
if (!empty($migrations)) {
$migrationsInDB = $this->getCurrentMigrations();
$migrationsInDBKeyVal = array();
foreach ($migrationsInDB as $migration) {
$migrationsInDBKeyVal[$migration->file] = $migration;
}
foreach ($migrations as $file => $path) {
if (!isset($migrationsInDBKeyVal[$file])) {
if ($file == 'list.php') {
continue;
}
$this->createMigration($file);
}
}
}
}
public function createMigration($file)
{
if (file_exists($this->migrationPath . $file)) {
$migration = new Migration();
$migration->file = $file;
$parts = explode("_", $file);
$migration->version = intval($parts[1]);
$migration->created = date("Y-m-d H:i:s");
$migration->updated = date("Y-m-d H:i:s");
$migration->status = 'Pending';
$migration->Save();
return true;
}
return false;
}
public function runPendingMigrations()
{
$migrations = $this->getPendingMigrations();
foreach ($migrations as $migration) {
$this->runMigrationUp($migration);
}
}
public function runMigration($action)
{
$method = 'runMigration'.ucfirst($action);
if ($action == 'up') {
$statuses = array("Pending","Down");
$queryMethod = 'getFirstAddedMigration';
} elseif ($action == 'down') {
$statuses = array("Up");
$queryMethod = 'getLastRunMigration';
} else {
return false;
}
$migrations = $this->$queryMethod($statuses);
if (count($migrations) > 0) {
$this->$method($migrations[0]);
return $this->getMigrationById($migrations[0]->id);
} else {
$this->queueMigrations();
$migrations = $this->$queryMethod($statuses);
if (count($migrations) > 0) {
$this->$method($migrations[0]);
return $this->getMigrationById($migrations[0]->id);
}
}
return false;
}
/**
* @param string $migrationFileName
* @return AbstractMigration
*/
public function getMigrationObject($migrationFileName)
{
$path = $this->migrationPath . $migrationFileName;
$migrationName = str_replace('.php', '', $migrationFileName);
$migrationName = '\\Classes\\Migration\\'.$migrationName;
if (!class_exists($migrationName)) {
include $path;
}
if (!class_exists($migrationName)) {
return false;
}
/* @var AbstractMigration $migClass */
return new $migrationName($migrationFileName);
}
/**
* @param Migration $migration
* @return bool
*/
public function runMigrationUp($migration)
{
if ($migration->status != 'Pending' && $migration->status != 'UpError' && $migration->status != 'Down') {
return false;
}
/* @var AbstractMigration $migObject */
$migObject = $this->getMigrationObject($migration->file);
if (!$migObject) {
return false;
}
$res = $migObject->up();
if (!$res) {
$migration->last_error = $migObject->getLastError();
$migration->status = "UpError";
$migration->updated = date("Y-m-d H:i:s");
$migration->Save();
}
$migration->status = "Up";
$migration->updated = date("Y-m-d H:i:s");
$migration->Save();
return $migration;
}
/**
* @param Migration $migration
* @return bool
*/
public function runMigrationDown($migration)
{
if ($migration->status != 'Up' && $migration->status != 'UpError') {
return false;
}
/* @var AbstractMigration $migObject */
$migObject = $this->getMigrationObject($migration->file);
if (!$migObject) {
return false;
}
$res = $migObject->down();
if (!$res) {
$migration->last_error = $migObject->getLastError();
$migration->status = "DownError";
$migration->updated = date("Y-m-d H:i:s");
$migration->Save();
}
$migration->status = "Down";
$migration->updated = date("Y-m-d H:i:s");
$migration->Save();
return $migration;
}
public function ensureMigrations()
{
$migration = new Migration();
$migration->Load("1 = 1 order by id desc limit 1");
include $this->migrationPath . "list.php";
/* @var array $migrationList */
if (count($migrationList) > 0 && (empty($migration->id) || $migrationList[0].".php" != $migration->file)) {
LogManager::getInstance()->info("ensureMigrations - execute migrations");
$this->queueMigrations();
$this->runPendingMigrations();
}
}
}

View File

@@ -0,0 +1,74 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/20/17
* Time: 9:47 AM
*/
namespace Classes\ModuleBuilder;
class ModuleBuilder
{
public $modules = array();
/**
* @param ModuleTab $module
*/
public function addModuleOrGroup($module)
{
$this->modules[] = $module;
}
public function getTabHeadersHTML()
{
$html = "";
foreach ($this->modules as $module) {
$html .= $module->getHTML()."\r\n";
}
return $html;
}
public function getTabPagesHTML()
{
$html = "";
/* @var ModuleTab $module */
foreach ($this->modules as $module) {
if (get_class($module) === ModuleTab::class) {
$html .= $module->getPageHTML()."\r\n";
} else {
/* @var ModuleTab $mod */
foreach ($module->modules as $mod) {
$html .= $mod->getPageHTML()."\r\n";
}
}
}
return $html;
}
public function getModJsHTML()
{
$html = "var modJsList = new Array();\r\n";
$activeModule = "";
/* @var ModuleTab $module */
foreach ($this->modules as $module) {
if (get_class($module) == ModuleTab::class) {
$html .= $module->getJSObjectCode()."\r\n";
if ($module->isActive) {
$activeModule = $module->name;
}
} else {
/* @var ModuleTab $mod */
foreach ($module->modules as $mod) {
if ($module->isActive && $activeModule == "") {
$activeModule = $mod->name;
}
$html .= $mod->getJSObjectCode()."\r\n";
}
}
}
$html .= "var modJs = modJsList['tab".$activeModule."'];\r\n";
return $html;
}
}

View File

@@ -0,0 +1,85 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/20/17
* Time: 9:47 AM
*/
namespace Classes\ModuleBuilder;
class ModuleTab
{
public $name;
public $class;
public $label;
public $adapterName;
public $filter;
public $orderBy;
public $isActive = false;
public $isInsideGroup = false;
public $options = array();
public function __construct(
$name,
$class,
$label,
$adapterName,
$filter,
$orderBy,
$isActive = false,
$options = array()
) {
$this->name = $name;
$this->class = $class;
$this->label = $label;
$this->adapterName = $adapterName;
$this->filter = $filter;
$this->orderBy = $orderBy;
$this->isActive = $isActive;
$this->options = $options;
}
public function getHTML()
{
$active = ($this->isActive)?"active":"";
if (!$this->isInsideGroup) {
return '<li class="' . $active . '"><a id="tab' . $this->name
. '" href="#tabPage' . $this->name . '">' . t($this->label) . '</a></li>';
} else {
return '<li class="' . $active . '"><a id="tab' . $this->name
. '" href="#tabPage' . $this->name . '">' . t($this->label) . '</a></li>';
}
}
public function getPageHTML()
{
$active = ($this->isActive)?" active":"";
$html = '<div class="tab-pane'.$active.'" id="tabPage'.$this->name.'">'.
'<div id="'.$this->name.'" class="reviewBlock" data-content="List" style="padding-left:5px;"></div>'.
'<div id="'.$this->name.
'Form" class="reviewBlock" data-content="Form" style="padding-left:5px;display:none;"></div>'.
'</div>';
return $html;
}
public function getJSObjectCode()
{
$js = '';
if (empty($this->filter)) {
$js.= "modJsList['tab" . $this->name . "'] = new " .
$this->adapterName . "('" . $this->class . "','" . $this->name . "','','".$this->orderBy."');";
} else {
$js.= "modJsList['tab" . $this->name . "'] = new " .
$this->adapterName . "('" . $this->class . "','" . $this->name . "'," .
$this->filter . ",'".$this->orderBy."');";
}
foreach ($this->options as $key => $val) {
$js.= "modJsList['tab" . $this->name . "'].".$key."(".$val.");";
}
return $js;
}
}

View File

@@ -0,0 +1,53 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/20/17
* Time: 9:48 AM
*/
namespace Classes\ModuleBuilder;
class ModuleTabGroup
{
public $name;
public $label;
public $isActive = false;
public $modules = array();
public function __construct($name, $label)
{
$this->name = $name;
$this->label = $label;
}
public function addModuleTab($moduleTab)
{
if ($moduleTab->isActive) {
$this->isActive = true;
$moduleTab->isActive = false;
}
$moduleTab->isInsideGroup = true;
$this->modules[] = $moduleTab;
}
public function getHTML()
{
$html = "";
$active = ($this->isActive)?" active":"";
$html.= '<li class="dropdown'.$active.'">'."\r\n".
'<a href="#" id="'.$this->name.
'" class="dropdown-toggle" data-toggle="dropdown" aria-controls="'.$this->name.
'-contents">'.$this->label.' <span class="caret"></span></a>'."\r\n".
'<ul class="dropdown-menu" role="menu" aria-labelledby="'.$this->name.'" id="'.$this->name.'-contents">';
foreach ($this->modules as $module) {
$html.= $module->getHTML();
}
$html .= "</ul></li>";
return $html;
}
}

View File

@@ -0,0 +1,156 @@
<?php
namespace Classes;
use Model\Notification;
use Users\Common\Model\User;
class NotificationManager
{
/* @var \Classes\BaseService $baseService */
public $baseService;
public function setBaseService($baseService)
{
$this->baseService = $baseService;
}
public function addNotification(
$toEmployee,
$message,
$action,
$type,
$toUserId = null,
$fromSystem = false,
$sendEmail = false
) {
$userEmp = new User();
$toUser = null;
if (!empty($toEmployee)) {
$userEmp->Load("employee = ?", array($toEmployee));
if (!empty($userEmp->employee) && $userEmp->employee == $toEmployee) {
$toUser = $userEmp->id;
} else {
return;
}
} elseif (!empty($toUserId)) {
$toUser = $toUserId;
}
$noti = new Notification();
if ($fromSystem) {
$noti->fromUser = 0;
$noti->fromEmployee = 0;
$noti->image = BASE_URL."images/icehrm.png";
} else {
$user = $this->baseService->getCurrentUser();
$noti->fromUser = $user->id;
$noti->fromEmployee = $user->employee;
}
if (!empty($toEmployee)) {
$noti->employee = $toEmployee;
} elseif (!empty($toUserId)) {
$tempUser = new User();
$tempUser->Load("id = ?", array($toUserId));
$noti->employee = $tempUser->employee;
}
$noti->toUser = $toUser;
$noti->message = $message;
if (!empty($noti->fromEmployee) && $noti->fromEmployee != 0) {
$employee = $this->baseService->getElement('Employee', $noti->fromEmployee, null, true);
if (!empty($employee)) {
$employee = FileService::getInstance()->updateProfileImage($employee);
$noti->image = $employee->image;
}
}
if (empty($noti->image) && !empty($employee)) {
if ($employee->gender == 'Male') {
$noti->image = BASE_URL."images/user_male.png";
} else {
$noti->image = BASE_URL."images/user_female.png";
}
}
$noti->action = $action;
$noti->type = $type;
$noti->time = date('Y-m-d H:i:s');
$noti->status = 'Unread';
$ok = $noti->Save();
if (!$ok) {
error_log("Error adding notification: ".$noti->ErrorMsg());
} elseif ($sendEmail) {
$emailSender = BaseService::getInstance()->getEmailSender();
if (!empty($emailSender)) {
$emailSender->sendEmailFromNotification($noti);
}
}
}
public function clearNotifications($userId)
{
$notification = new Notification();
$listUnread = $notification->Find("toUser = ? and status = ?", array($userId,'Unread'));
/* @var Notification $not */
foreach ($listUnread as $not) {
$not->status = "Read";
$not->Save();
}
}
public function getNotificationByTypeAndDate($type, $date)
{
$noti = new Notification();
$noti->Load("date(time) = ? and type = ?", array($date,$type));
if (!empty($noti->id) && $noti->type = $type) {
return $noti;
}
return null;
}
public function getLatestNotificationsAndCounts($userId)
{
$notification = new Notification();
$listUnread = $notification->Find("toUser = ? and status = ?", array($userId,'Unread'));
$unreadCount = count($listUnread);
$limit = ($unreadCount < 10)?10:$unreadCount;
$list = $notification->Find("toUser = ? order by time desc limit ?", array($userId,$limit));
$newList = array();
$fs = FileService::getInstance();
foreach ($list as $noti) {
if ($noti->fromEmployee > 0) {
$employee = $this->baseService->getElement('Employee', $noti->fromEmployee, null, true);
if (!empty($employee)) {
$employee = $fs->updateProfileImage($employee);
$noti->image = $employee->image;
if (empty($noti->image)) {
if ($employee->gender == 'Male') {
$noti->image = BASE_URL."images/user_male.png";
} else {
$noti->image = BASE_URL."images/user_female.png";
}
}
$newList[] = $noti;
}
} else {
$noti->image = BASE_URL."images/syslogo.png";
$newList[] = $noti;
}
}
return array($unreadCount, $list);
}
}

View File

@@ -0,0 +1,116 @@
<?php
namespace Classes;
use Reports\Admin\Api\CSVReportBuilder;
use Reports\Admin\Api\ReportBuilder;
use Reports\Admin\Api\ReportBuilderInterface;
use Utils\LogManager;
class ReportHandler
{
public function handleReport($request)
{
if (!empty($request['id'])) {
$reportMgrClass = BaseService::getInstance()->getFullQualifiedModelClassName($request['t']);
/* @var \Model\Report $report */
$report = new $reportMgrClass();
$report->Load("id = ?", array($request['id']));
if ($report->id."" == $request['id']) {
if ($report->type == 'Query') {
$where = $this->buildQueryOmmit(json_decode($report->paramOrder, true), $request);
$query = str_replace("_where_", $where[0], $report->query);
return $this->executeReport(new CSVReportBuilder(), $report, $query, $where[1]);
} elseif ($report->type == 'Class') {
$className = $report->query;
if ($request['t'] == "Report") {
$className = '\\Reports\\Admin\\Reports\\'.$className;
} else {
$className = '\\Reports\\User\\Reports\\'.$className;
}
$cls = new $className();
$data = $cls->getData($report, $request);
if (empty($data)) {
return array("ERROR", "No data found");
}
return $this->generateReport($cls, $report, $data);
}
} else {
return array("ERROR","Report id not found");
}
}
}
private function executeReport($reportBuilder, $report, $query, $parameters)
{
$report->DB()->SetFetchMode(ADODB_FETCH_ASSOC);
$rs = $report->DB()->Execute($query, $parameters);
if (!$rs) {
LogManager::getInstance()->info($report->DB()->ErrorMsg());
return array("ERROR","Error generating report");
}
$reportNamesFilled = false;
$columnNames = array();
$reportData = array();
foreach ($rs as $rowId => $row) {
$reportData[] = array();
if (!$reportNamesFilled) {
foreach ($row as $name => $value) {
$columnNames[] = $name;
$reportData[count($reportData)-1][] = $value;
}
$reportNamesFilled = true;
} else {
foreach ($row as $name => $value) {
$reportData[count($reportData)-1][] = $value;
}
}
}
array_unshift($reportData, $columnNames);
return $this->generateReport($reportBuilder, $report, $reportData);
}
/**
* @param ReportBuilder $reportBuilder
* @param $report
* @param $data
* @return array
*/
protected function generateReport($reportBuilder, $report, $data)
{
$reportCreationData = $reportBuilder->createReportFile($report, $data);
$saveResp = $reportBuilder->saveFile($reportCreationData[0], $reportCreationData[1], $reportCreationData[2]);
$headers = array_shift($data);
return array($saveResp[0],array($saveResp[1],$headers,$data));
}
private function buildQueryOmmit($names, $params)
{
$parameters = array();
$query = "";
foreach ($names as $name) {
if ($params[$name] != "NULL") {
if ($query != "") {
$query.=" AND ";
}
$query.=$name." = ?";
$parameters[] = $params[$name];
}
}
if ($query != "") {
$query = "where ".$query;
}
return array($query, $parameters);
}
}

View File

@@ -0,0 +1,142 @@
<?php
namespace Classes;
use Classes\Crypt\AesCtr;
use Model\RestAccessToken;
use Users\Common\Model\User;
use Utils\LogManager;
class RestApiManager
{
private static $me = null;
protected $endPoints = array();
private function __construct()
{
}
public static function getInstance()
{
if (empty(self::$me)) {
self::$me = new RestApiManager();
}
return self::$me;
}
public function generateUserAccessToken($user)
{
$data = array();
$data['userId'] = $user->id;
$data['expires'] = strtotime('now') + 60*60;
$accessTokenTemp = AesCtr::encrypt(json_encode($data), $user->password, 256);
$accessTokenTemp = $user->id."|".$accessTokenTemp;
$accessToken = AesCtr::encrypt($accessTokenTemp, APP_SEC, 256);
return new IceResponse(IceResponse::SUCCESS, $accessToken);
}
public function getAccessTokenForUser($user)
{
$accessTokenObj = new RestAccessToken();
$accessTokenObj->Load("userId = ?", array($user->id));
$generateAccessToken = false;
$accessToken = $accessTokenObj->token;
if (!empty($accessToken)) {
$resp = $this->validateAccessTokenInner($accessToken);
if ($resp->getStatus() != IceResponse::SUCCESS) {
$generateAccessToken = true;
}
} else {
$generateAccessToken = true;
}
if ($generateAccessToken) {
$accessToken = $this->generateUserAccessToken($user)->getData();
if (!empty($accessTokenObj->id)) {
$accessTokenObj->token = $accessToken;
$accessTokenObj->hash = md5(CLIENT_BASE_URL.$accessTokenObj->token);
$accessTokenObj->updated = date("Y-m-d H:i:s");
$accessTokenObj->Save();
} else {
$accessTokenObj = new RestAccessToken();
$accessTokenObj->userId = $user->id;
$accessTokenObj->token = $accessToken;
$accessTokenObj->hash = md5(CLIENT_BASE_URL.$accessTokenObj->token);
$accessTokenObj->updated = date("Y-m-d H:i:s");
$accessTokenObj->created = date("Y-m-d H:i:s");
$accessTokenObj->Save();
}
}
return new IceResponse(IceResponse::SUCCESS, $accessTokenObj->hash);
}
public function validateAccessToken($hash)
{
$accessTokenObj = new RestAccessToken();
LogManager::getInstance()->info("AT Hash:".$hash);
$accessTokenObj->Load("hash = ?", array($hash));
LogManager::getInstance()->info("AT Hash Object:".json_encode($accessTokenObj));
if (!empty($accessTokenObj->id) && $accessTokenObj->hash == $hash) {
//No need to do user based validation for now
return $this->validateAccessTokenInner($accessTokenObj->token);
}
return new IceResponse(IceResponse::ERROR, "Authorization bearer token not found or invalid", 401);
}
private function validateAccessTokenInner($accessToken)
{
$accessTokenTemp = AesCtr::decrypt($accessToken, APP_SEC, 256);
$parts = explode("|", $accessTokenTemp);
$user = new User();
$user->Load("id = ?", array($parts[0]));
if (empty($user->id) || $user->id != $parts[0] || empty($parts[0])) {
return new IceResponse(IceResponse::ERROR, -1);
}
$accessToken = AesCtr::decrypt($parts[1], $user->password, 256);
$data = json_decode($accessToken, true);
if ($data['userId'] == $user->id) {
unset($user->password);
return new IceResponse(IceResponse::SUCCESS, $user);
}
return new IceResponse(IceResponse::ERROR, false);
}
/**
* @param RestEndPoint $endPoint
*/
// TODO - not used can be removed
public function addEndPoint($endPoint)
{
$url = $endPoint->getUrl();
LogManager::getInstance()->info("Adding REST end point for - ".$url);
$this->endPoints[$url] = $endPoint;
}
public function process($type, $url, $parameters)
{
$accessTokenValidation = $this->validateAccessToken($parameters['access_token']);
if ($accessTokenValidation->getStatus() == IceResponse::ERROR) {
return $accessTokenValidation;
}
if (isset($this->endPoints[$url])) {
return $this->endPoints[$url]->$type($parameters);
}
return new IceResponse(IceResponse::ERROR, "End Point ".$url." - Not Found");
}
}

View File

@@ -0,0 +1,326 @@
<?php
namespace Classes;
use Classes\Data\DataReader;
use Classes\Data\Query\DataQuery;
use Employees\Common\Model\Employee;
use Users\Common\Model\User;
use Utils\SessionUtils;
class RestEndPoint
{
const RESPONSE_ERR_ENTITY_NOT_FOUND = 'Entity not found';
const RESPONSE_ERR_PERMISSION_DENIED = 'Permission denied';
const RESPONSE_ERR_UNPROCESSABLE = 'Unprocessable Entity';
const RESPONSE_ERR_EMPLOYEE_NOT_FOUND = 'Employee not found';
const DEFAULT_LIMIT = 50;
const ELEMENT_NAME = '';
public function getModelObject($id)
{
return false;
}
public function checkBasicPermissions($user, $employeeId)
{
if (!isset($employeeId)) {
return new IceResponse(IceResponse::ERROR, self::RESPONSE_ERR_UNPROCESSABLE, 422);
}
$employee = new Employee();
$employee->Load("id = ?", array($employeeId));
if (empty($employee->id) || $employee->id !== $employeeId . '') {
return new IceResponse(IceResponse::ERROR, self::RESPONSE_ERR_EMPLOYEE_NOT_FOUND, 422);
}
if ($user->user_level !== 'Admin') {
if ($user->user_level === 'Manager') {
if (!PermissionManager::manipulationAllowed(
BaseService::getInstance()->getCurrentProfileId(),
$employee
)
) {
return new IceResponse(IceResponse::ERROR, self::RESPONSE_ERR_PERMISSION_DENIED, 403);
}
} elseif ($user->user_level === 'Employee'
&& $employeeId != BaseService::getInstance()->getCurrentProfileId()) {
return new IceResponse(IceResponse::ERROR, self::RESPONSE_ERR_PERMISSION_DENIED, 403);
} elseif ($user->user_level !== 'Employee' && $user->user_level !== 'Manager') {
return new IceResponse(IceResponse::ERROR, self::RESPONSE_ERR_PERMISSION_DENIED, 403);
}
return new IceResponse(IceResponse::ERROR, "Permission denied", 403);
}
return new IceResponse(IceResponse::SUCCESS);
}
public function process($type, $parameters = [])
{
if (!is_array($parameters)) {
$parameters = [$parameters];
}
$accessTokenValidation = $this->validateAccessToken();
if (!empty($accessTokenValidation) && $accessTokenValidation->getStatus() == IceResponse::ERROR) {
$resp = $accessTokenValidation;
} else {
BaseService::getInstance()->setCurrentUser($accessTokenValidation->getData());
SessionUtils::saveSessionObject('user', $accessTokenValidation->getData());
array_unshift($parameters, $accessTokenValidation->getData());
$resp = call_user_func_array(array($this, $type), $parameters);
}
header('Content-Type: application/json');
if ($resp->getStatus() == IceResponse::SUCCESS && $resp->getCode() == null) {
header('Content-Type: application/json');
http_response_code(200);
$this->printResponse($resp->getObject());
} elseif ($resp->getStatus() == IceResponse::SUCCESS) {
header('Content-Type: application/json');
http_response_code($resp->getCode());
$this->printResponse($resp->getObject());
} else {
header('Content-Type: application/json');
http_response_code($resp->getCode());
$messages = array();
$messages[] = array(
"code" => $resp->getCode(),
"message" => $resp->getObject()
);
$this->printResponse(array("error" => [$messages]));
}
}
protected function enrichElement($obj, $map)
{
if (!empty($map)) {
foreach ($map as $k => $v) {
if ($obj->$k !== null) {
$obj->$k = [
'type' => $v[0],
$v[1] => $obj->$k,
'display' => $obj->{$k . '_Name'}
];
} else {
unset($obj->$k);
}
unset($obj->{$k . '_Name'});
}
}
return $obj;
}
protected function cleanObject($obj)
{
$obj = BaseService::getInstance()->cleanUpAdoDB($obj);
unset($obj->keysToIgnore);
unset($obj->historyFieldsToTrack);
unset($obj->historyUpdateList);
unset($obj->oldObjOrig);
unset($obj->oldObj);
return $obj;
}
protected function removeNullFields($obj)
{
foreach ($obj as $k => $v) {
if ($obj->$k === null) {
unset($obj->$k);
}
}
return $obj;
}
public function listAll(User $user)
{
return new IceResponse(IceResponse::ERROR, "Method not Implemented", 404);
}
protected function listByQuery(DataQuery $query)
{
$page = 1;
if (isset($_GET['page']) && intval($_GET['page']) > 0) {
$page = intval($_GET['page']);
}
$limit = static::DEFAULT_LIMIT;
if (isset($_GET['limit']) && intval($_GET['limit']) > 0) {
$limit = intval($_GET['limit']);
}
$query->setStartPage(($page - 1) * $limit);
$query->setLength($limit);
$data = DataReader::getData($query);
$output = array();
$columns = $query->getColumns();
foreach ($data as $item) {
if (!empty($columns)) {
$obj = new \stdClass();
foreach ($columns as $column) {
$obj->$column = $item->$column;
}
} else {
$obj = $this->cleanObject($item);
}
$output[] = $obj;
}
return new IceResponse(
IceResponse::SUCCESS,
[
'data' => $output,
'nextPage' => $page + 1,
]
);
}
protected function listData(
$object,
$limit,
$page = 1,
$fieldsToRemove = array(),
$customQuery = null,
$params = []
) {
if (!isset($limit) || $limit <= 0) {
$limit = self::DEFAULT_LIMIT;
}
if ($customQuery) {
$query = $customQuery.' order by id limit ?,?';
$params[] = ($page - 1) * $limit;
$params[] = $limit + 1;
} else {
$query = '1=1 order by id limit ?,?';
$params = array(($page - 1) * $limit, ($limit + 1));
}
$allObjects = $object->Find($query, $params);
$count = 0;
$hasMore = 0;
$newObjects = array();
foreach ($allObjects as $object) {
$object = $this->cleanObject($object);
$object = $this->removeNullFields($object);
if (!empty($fieldsToRemove)) {
foreach ($fieldsToRemove as $field) {
unset($object->$field);
}
}
$newObjects[] = $object;
$count++;
if ($count === $limit) {
$hasMore = true;
break;
}
}
return new IceResponse(
IceResponse::SUCCESS,
[
'data' => $newObjects,
'prevPage' => ($page > 1) ? $page - 1 : '',
'nextPage' => $hasMore ? $page + 1 : '',
'limit' => $limit,
]
);
}
public function get(User $user, $parameter)
{
return new IceResponse(IceResponse::ERROR, "Method not Implemented", 404);
}
public function post(User $user)
{
return new IceResponse(IceResponse::ERROR, "Method not Implemented", 404);
}
public function put(User $user, $parameter)
{
return new IceResponse(IceResponse::ERROR, "Method not Implemented", 404);
}
public function delete(User $user, $parameter)
{
if ($user->user_level !== 'Admin') {
return new IceResponse(IceResponse::ERROR, "Permission denied", 403);
}
$response = BaseService::getInstance()->deleteElement(
static::ELEMENT_NAME,
$parameter
);
if ($response->getStatus() === IceResponse::SUCCESS) {
return new IceResponse(IceResponse::SUCCESS, ['id' => $parameter], 200);
}
return new IceResponse(IceResponse::ERROR, $response->getData(), 400);
}
public function validateAccessToken()
{
$accessTokenValidation = RestApiManager::getInstance()->validateAccessToken($this->getBearerToken());
return $accessTokenValidation;
}
public function printResponse($response)
{
echo json_encode($response, JSON_PRETTY_PRINT);
}
/**
* Get hearder Authorization
* */
private function getAuthorizationHeader()
{
$headers = null;
if (isset($_SERVER['Authorization'])) {
$headers = trim($_SERVER["Authorization"]);
} elseif (isset($_SERVER['HTTP_AUTHORIZATION'])) { //Nginx or fast CGI
$headers = trim($_SERVER["HTTP_AUTHORIZATION"]);
} elseif (function_exists('apache_request_headers')) {
$requestHeaders = apache_request_headers();
// Server-side fix for bug in old Android versions
// (a nice side-effect of this fix means we don't care about capitalization
// for Authorization)
$requestHeaders = array_combine(
array_map(
'ucwords',
array_keys($requestHeaders)
),
array_values($requestHeaders)
);
//print_r($requestHeaders);
if (isset($requestHeaders['Authorization'])) {
$headers = trim($requestHeaders['Authorization']);
}
}
return $headers;
}
/**
* get access token from header
* */
private function getBearerToken()
{
$headers = $this->getAuthorizationHeader();
// HEADER: Get the access token from the header
if (!empty($headers)) {
if (preg_match('/Bearer\s(\S+)/', $headers, $matches)) {
return $matches[1];
}
}
return null;
}
protected function getRequestBody()
{
$inputJSON = file_get_contents('php://input');
return json_decode($inputJSON, true);
}
}

View File

@@ -0,0 +1,118 @@
<?php
namespace Classes;
use Aws\S3\S3Client;
use Utils\LogManager;
class S3FileSystem
{
protected $s3;
protected $key;
protected $secret;
public function __construct($key, $secret)
{
$this->key = $key;
$this->secret = $secret;
$arr = array(
'key' => $key,
'secret' => $secret,
'region' => AWS_REGION
);
$this->s3 = S3Client::factory($arr);
}
public function putObject($bucket, $key, $sourceFile, $acl)
{
$res = null;
try {
$res = $this->s3->putObject(array(
'Bucket' => $bucket,
'Key' => $key,
'SourceFile' => $sourceFile,
'ACL' => $acl
/*'ContentType' => 'image/jpeg'*/
));
} catch (\Exception $e) {
LogManager::getInstance()->error($e->getMessage());
return null;
}
LogManager::getInstance()->info("Response from s3:".print_r($res, true));
$result = $res->get('RequestId');
if (!empty($result)) {
return $result;
}
return null;
}
public function deleteObject($bucket, $key)
{
$res = null;
try {
$res = $this->s3->deleteObject(array(
'Bucket' => $bucket,
'Key' => $key
));
} catch (\Exception $e) {
LogManager::getInstance()->info($e->getMessage());
return null;
}
LogManager::getInstance()->info("Response from s3:".print_r($res, true));
$result = $res->get('RequestId');
if (!empty($result)) {
return $result;
}
return null;
}
public function generateExpiringURL($url, $expiresIn = 600)
{
// Calculate expiry time
$expiresTimestamp = time() + intval($expiresIn);
$path = parse_url($url, PHP_URL_PATH);
$path = str_replace('%2F', '/', rawurlencode($path = ltrim($path, '/')));
$host = parse_url($url, PHP_URL_HOST);
$bucket = str_replace(".s3.amazonaws.com", "", $host);
// Path for signature starts with the bucket
$signpath = '/'. $bucket .'/'. $path;
// S3 friendly string to sign
$signsz = implode("\n", $pieces = array('GET', null, null, $expiresTimestamp, $signpath));
// Calculate the hash
$signature = $this->elCryptoHmacSHA1($this->secret, $signsz);
// ... to the query string ...
$qs = http_build_query($pieces = array(
'AWSAccessKeyId' => $this->key,
'Expires' => $expiresTimestamp,
'Signature' => $signature,
));
// ... and return the URL!
return $url.'?'.$qs;
}
private function elCryptoHmacSHA1($key, $data, $blocksize = 64)
{
if (strlen($key) > $blocksize) {
$key = pack('H*', sha1($key));
}
$key = str_pad($key, $blocksize, chr(0x00));
$ipad = str_repeat(chr(0x36), $blocksize);
$opad = str_repeat(chr(0x5c), $blocksize);
$hmac = pack('H*', sha1(
($key ^ $opad) . pack('H*', sha1(
($key ^ $ipad) . $data
))
));
return base64_encode($hmac);
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace Classes;
use Model\Setting;
class SettingsManager
{
private static $me = null;
private function __construct()
{
}
public static function getInstance()
{
if (empty(self::$me)) {
self::$me = new SettingsManager();
}
return self::$me;
}
public function getSetting($name)
{
if (class_exists("\\Classes\\ProVersion")) {
$pro = new ProVersion();
$val = $pro->getSetting($name);
if (!empty($val)) {
return $val;
}
}
$setting = new Setting();
$setting->Load("name = ?", array($name));
if ($setting->name == $name) {
return $setting->value;
}
return null;
}
public function setSetting($name, $value)
{
$setting = new Setting();
$setting->Load("name = ?", array($name));
if ($setting->name == $name) {
$setting->value = $value;
$setting->Save();
}
}
public function addSetting($name, $value)
{
$setting = new Setting();
$setting->Load("name = ?", array($name));
if ($setting->name == $name) {
$setting->value = $value;
$setting->Save();
} else {
$setting->name = $name;
$setting->value = $value;
$setting->description = $value;
$setting->meta = '';
$setting->Save();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,83 @@
<?php
namespace Classes;
use Employees\Common\Model\Employee;
use Model\StatusChangeLog;
use Users\Common\Model\User;
use Utils\LogManager;
class StatusChangeLogManager
{
private static $me = null;
private function __construct()
{
}
public static function getInstance()
{
if (empty(self::$me)) {
self::$me = new StatusChangeLogManager();
}
return self::$me;
}
public function addLog($type, $element, $userId, $oldStatus, $newStatus, $note)
{
$statusChangeLog = new StatusChangeLog();
$statusChangeLog->type = $type;
$statusChangeLog->element = $element;
$statusChangeLog->user_id = $userId;
$statusChangeLog->status_from = $oldStatus;
$statusChangeLog->status_to = $newStatus;
$statusChangeLog->created = date("Y-m-d H:i:s");
$statusChangeLog->data = $note;
$ok = $statusChangeLog->Save();
if (!$ok) {
LogManager::getInstance()->info($statusChangeLog->ErrorMsg());
return new IceResponse(IceResponse::ERROR, null);
}
return new IceResponse(IceResponse::SUCCESS, $statusChangeLog);
}
public function getLogs($type, $element)
{
$statusChangeLog = new StatusChangeLog();
$logsTemp = $statusChangeLog->Find("type = ? and element = ? order by created", array($type, $element));
$logs = array();
foreach ($logsTemp as $statusChangeLog) {
$t = array();
$t['time'] = $statusChangeLog->created;
$t['status_from'] = $statusChangeLog->status_from;
$t['status_to'] = $statusChangeLog->status_to;
$t['time'] = $statusChangeLog->created;
$userName = null;
if (!empty($statusChangeLog->user_id)) {
$lgUser = new User();
$lgUser->Load("id = ?", array($statusChangeLog->user_id));
if ($lgUser->id == $statusChangeLog->user_id) {
if (!empty($lgUser->employee)) {
$lgEmployee = new Employee();
$lgEmployee->Load("id = ?", array($lgUser->employee));
$userName = $lgEmployee->first_name." ".$lgEmployee->last_name;
} else {
$userName = $lgUser->userName;
}
}
}
if (!empty($userName)) {
$t['note'] = $statusChangeLog->data." (by: ".$userName.")";
} else {
$t['note'] = $statusChangeLog->data;
}
$logs[] = $t;
}
return new IceResponse(IceResponse::SUCCESS, $logs);
}
}

View File

@@ -0,0 +1,81 @@
<?php
/*
This file is part of Ice Framework.
Ice Framework is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Ice Framework is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Ice Framework. If not, see <http://www.gnu.org/licenses/>.
------------------------------------------------------------------
Original work Copyright (c) 2012 [Gamonoid Media Pvt. Ltd]
Developer: Thilina Hasantha (thilina.hasantha[at]gmail.com / facebook.com/thilinah)
*/
namespace Classes;
abstract class SubActionManager
{
public $user = null;
/* @var \Classes\BaseService $baseService*/
protected $baseService = null;
public $emailTemplates = null;
protected $emailSender = null;
public function setUser($user)
{
$this->user = $user;
}
public function setBaseService(BaseService $baseService)
{
$this->baseService = $baseService;
}
public function getCurrentProfileId()
{
return $this->baseService->getCurrentProfileId();
}
public function setEmailTemplates($emailTemplates)
{
$this->emailTemplates = $emailTemplates;
}
public function getEmailTemplate($name)
{
//Read module email templates
if ($this->emailTemplates == null) {
$this->emailTemplates = array();
if (is_dir(MODULE_PATH.'/emailTemplates/')) {
$ams = scandir(MODULE_PATH.'/emailTemplates/');
foreach ($ams as $am) {
if (!is_dir(MODULE_PATH.'/emailTemplates/'.$am) && $am != '.' && $am != '..') {
$this->emailTemplates[$am] = file_get_contents(MODULE_PATH.'/emailTemplates/'.$am);
}
}
}
}
return $this->emailTemplates[$name];
}
public function setEmailSender($emailSender)
{
$this->emailSender = $emailSender;
}
public function getUserFromProfileId($profileId)
{
return $this->baseService->getUserFromProfileId($profileId);
}
}

View File

@@ -0,0 +1,238 @@
<?php
namespace Classes;
use Classes\ModuleBuilder\ModuleBuilder;
class UIManager
{
private static $me = null;
protected $user;
protected $currentProfile;
protected $switchedProfile;
protected $currentProfileBlock = null;
protected $switchedProfileBlock = null;
protected $templates = array();
protected $quickAccessMenuItems = array();
private function __construct()
{
}
public static function getInstance()
{
if (empty(self::$me)) {
self::$me = new UIManager();
}
return self::$me;
}
private function getTemplate($name, $type)
{
if (isset($this->templates[$name])) {
return $this->templates[$name];
}
$this->templates[$name] = file_get_contents(APP_BASE_PATH."templates/".$type."/".$name.".html");
return $this->templates[$name];
}
public function populateTemplate($name, $type, $params)
{
$template = $this->getTemplate($name, $type);
foreach ($params as $key => $value) {
$template = str_replace("#_".$key."_#", $value, $template);
}
return LanguageManager::translateTnrText($template);
}
public function setCurrentUser($user)
{
$this->user = $user;
}
public function setHomeLink($homeLink)
{
$this->homeLink = $homeLink;
}
public function setProfiles($profileCurrent, $profileSwitched)
{
$this->currentProfile = $profileCurrent;
$this->switchedProfile = $profileSwitched;
if (!empty($profileCurrent) && !empty($profileSwitched)) {
$this->currentProfileBlock = array(
"profileImage"=>$profileCurrent->image,
"firstName"=>$profileCurrent->first_name,
"lastName"=>$profileCurrent->last_name
);
$this->switchedProfileBlock = array(
"profileImage"=>$profileSwitched->image,
"firstName"=>$profileSwitched->first_name,
"lastName"=>$profileSwitched->last_name
);
} elseif (!empty($profileCurrent)) {
$this->currentProfileBlock = array(
"profileImage"=>$profileCurrent->image,
"firstName"=>$profileCurrent->first_name,
"lastName"=>$profileCurrent->last_name
);
} elseif (!empty($profileSwitched)) {
$this->currentProfileBlock = array(
"profileImage"=>BASE_URL."images/user_male.png",
"firstName"=>$this->user->username,
"lastName"=>""
);
$this->switchedProfileBlock = array(
"profileImage"=>$profileSwitched->image,
"firstName"=>$profileSwitched->first_name,
"lastName"=>$profileSwitched->last_name
);
} else {
$this->currentProfileBlock = array(
"profileImage"=>BASE_URL."images/user_male.png",
"firstName"=>$this->user->username,
"lastName"=>""
);
}
}
public function getProfileBlocks()
{
$tempateProfileBlock = $this->populateTemplate('profile_info', 'app', $this->currentProfileBlock);
if (!empty($this->switchedProfileBlock)) {
$tempateProfileBlock
.= $this->populateTemplate('switched_profile_info', 'app', $this->switchedProfileBlock);
}
return $tempateProfileBlock;
}
public function getMenuBlocks()
{
$manuItems = array();
if (!empty($this->quickAccessMenuItems)) {
$itemsHtml = $this->getQuickAccessMenuItemsHTML();
if (!empty($itemsHtml)) {
$manuItems[] = new MenuItemTemplate('menuButtonQuick', array("ITEMS"=>$itemsHtml));
}
}
$manuItems[] = new MenuItemTemplate('menuButtonNotification', array());
if ($this->user->user_level == "Admin") {
$manuItems[] = new MenuItemTemplate('menuButtonSwitchProfile', array());
}
if (!empty($this->currentProfile)) {
$manuItems[] = new MenuItemTemplate('menuButtonProfile', array(
"profileImage"=>$this->currentProfile->image,
"firstName"=>$this->currentProfile->first_name,
"lastName"=>$this->currentProfile->last_name,
"homeLink"=>$this->homeLink,
"CLIENT_BASE_URL"=>CLIENT_BASE_URL
));
} else {
$manuItems[] = new MenuItemTemplate('menuButtonProfile', array(
"profileImage"=>BASE_URL."images/user_male.png",
"firstName"=>$this->user->username,
"lastName"=>"",
"homeLink"=>$this->homeLink,
"CLIENT_BASE_URL"=>CLIENT_BASE_URL
));
}
if ($this->user->user_level == "Admin") {
$other = '';
if (class_exists('\\Classes\\ProVersion')) {
$pro = new ProVersion();
if (method_exists($pro, 'getDetails')) {
$other = $pro->getDetails();
}
}
$manuItems[] = new MenuItemTemplate('menuButtonHelp', array(
"APP_NAME"=>APP_NAME,
"VERSION"=>VERSION,
"VERSION_DATE"=>VERSION_DATE,
"OTHER"=>$other
));
}
return $manuItems;
}
public function getMenuItemsHTML()
{
$menuItems = $this->getMenuBlocks();
$menuHtml = "";
foreach ($menuItems as $item) {
$menuHtml.=$item->getHtml();
}
return $menuHtml;
}
public function addQuickAccessMenuItem($name, $icon, $link, $userLevels = array())
{
$newName = LanguageManager::tran($name);
$this->quickAccessMenuItems[] = array($newName, $icon, $link, $userLevels);
}
public function getQuickAccessMenuItemsHTML()
{
$html = "";
$user = BaseService::getInstance()->getCurrentUser();
foreach ($this->quickAccessMenuItems as $item) {
if (empty($item[3]) || in_array($user->user_level, $item[3])) {
$html .= '<a href="'.$item[2].'"><i class="fa '.$item[1].'"></i> '.$item[0].'</a>';
}
}
return $html;
}
/**
* @param ModuleBuilder $moduleBuilder
* @return mixed|string
*/
public function renderModule($moduleBuilder)
{
$str = '<div class="span9">'
.'<ul class="nav nav-tabs" id="modTab" style="margin-bottom:0px;margin-left:5px;border-bottom: none;">'
.'__tabHeaders__</ul><div class="tab-content">__tabPages__</div></div><script>__tabJs__</script>';
$str = str_replace("__tabHeaders__", $moduleBuilder->getTabHeadersHTML(), $str);
$str = str_replace("__tabPages__", $moduleBuilder->getTabPagesHTML(), $str);
$str = str_replace("__tabJs__", $moduleBuilder->getModJsHTML(), $str);
return $str;
}
public function getCompanyLogoUrl()
{
$logoFileSet = false;
$logoFileName = CLIENT_BASE_PATH."data/logo.png";
$logoSettings = SettingsManager::getInstance()->getSetting("Company: Logo");
if (!empty($logoSettings)) {
$logoFileName = FileService::getInstance()->getFileUrl($logoSettings);
$logoFileSet = true;
}
if (!$logoFileSet && !file_exists($logoFileName)) {
return BASE_URL."images/logo.png";
}
return $logoFileName;
}
}