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,134 @@
<?php
/*
This file is part of iCE Hrm.
iCE Hrm 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 Hrm 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 Hrm. 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 Attendance\Admin\Api;
use Attendance\Common\Model\Attendance;
use Classes\BaseService;
use Classes\IceResponse;
use Classes\LanguageManager;
use Classes\SubActionManager;
use Utils\LogManager;
class AttendanceActionManager extends SubActionManager
{
public function savePunch($req)
{
$employee = $this->baseService->getElement('Employee', $req->employee, null, true);
$inDateTime = $req->in_time;
$inDateArr = explode(" ", $inDateTime);
$inDate = $inDateArr[0];
$outDateTime = $req->out_time;
$outDate = "";
if (!empty($outDateTime)) {
$outDateArr = explode(" ", $outDateTime);
$outDate = $outDateArr[0];
}
$note = $req->note;
//check if dates are differnet
if (!empty($outDate) && $inDate != $outDate) {
return new IceResponse(
IceResponse::ERROR,
LanguageManager::tran('Attendance entry should be within a single day')
);
}
//compare dates
if (!empty($outDateTime) && strtotime($outDateTime) <= strtotime($inDateTime)) {
return new IceResponse(IceResponse::ERROR, 'Punch-in time should be lesser than Punch-out time');
}
//Find all punches for the day
$attendance = new Attendance();
$attendanceList = $attendance->Find(
"employee = ? and DATE_FORMAT( in_time, '%Y-%m-%d' ) = ?",
array($employee->id,$inDate)
);
foreach ($attendanceList as $attendance) {
if (!empty($req->id) && $req->id == $attendance->id) {
continue;
}
if (empty($attendance->out_time) || $attendance->out_time == "0000-00-00 00:00:00") {
return new IceResponse(
IceResponse::ERROR,
"There is a non closed attendance entry for today.
Please mark punch-out time of the open entry before adding a new one"
);
} elseif (!empty($outDateTime)) {
if (strtotime($attendance->out_time) >= strtotime($outDateTime)
&& strtotime($attendance->in_time) <= strtotime($outDateTime)) {
//-1---0---1---0 || ---0--1---1---0
return new IceResponse(IceResponse::ERROR, "Time entry is overlapping with an existing one");
} elseif (strtotime($attendance->out_time) >= strtotime($inDateTime)
&& strtotime($attendance->in_time) <= strtotime($inDateTime)) {
//---0---1---0---1 || ---0--1---1---0
return new IceResponse(IceResponse::ERROR, "Time entry is overlapping with an existing one");
} elseif (strtotime($attendance->out_time) <= strtotime($outDateTime)
&& strtotime($attendance->in_time) >= strtotime($inDateTime)) {
//--1--0---0--1--
return new IceResponse(IceResponse::ERROR, "Time entry is overlapping with an existing one");
}
} else {
if (strtotime($attendance->out_time) >= strtotime($inDateTime)
&& strtotime($attendance->in_time) <= strtotime($inDateTime)) {
//---0---1---0
return new IceResponse(IceResponse::ERROR, "Time entry is overlapping with an existing one");
}
}
}
$attendance = new Attendance();
if (!empty($req->id)) {
$attendance->Load("id = ?", array($req->id));
}
$attendance->in_time = $inDateTime;
if (empty($outDateTime)) {
$attendance->out_time = null;
} else {
$attendance->out_time = $outDateTime;
}
$attendance->employee = $req->employee;
$attendance->note = $note;
$ok = $attendance->Save();
if (!$ok) {
LogManager::getInstance()->info($attendance->ErrorMsg());
return new IceResponse(IceResponse::ERROR, "Error occurred while saving attendance");
}
return new IceResponse(IceResponse::SUCCESS, $attendance);
}
public function getImages($req)
{
$attendance = BaseService::getInstance()->getElement(
'Attendance',
$req->id,
'{"employee":["Employee","id","first_name+last_name"]}'
);
return new IceResponse(IceResponse::SUCCESS, $attendance);
}
}

View File

@@ -0,0 +1,129 @@
<?php
namespace Attendance\Admin\Api;
use Attendance\Common\Model\Attendance;
use Attendance\Rest\AttendanceRestEndPoint;
use Classes\AbstractModuleManager;
use Classes\UIManager;
class AttendanceAdminManager extends AbstractModuleManager
{
public function initializeUserClasses()
{
}
public function initializeFieldMappings()
{
}
public function initializeDatabaseErrorMappings()
{
}
public function setupModuleClassDefinitions()
{
$this->addModelClass('Attendance');
$this->addModelClass('AttendanceStatus');
}
public function setupRestEndPoints()
{
\Classes\Macaw::get(REST_API_PATH.'attendance/(:num)', function ($pathParams) {
$restEndPoint = new AttendanceRestEndPoint();
$restEndPoint->process('get', $pathParams);
});
\Classes\Macaw::get(REST_API_PATH.'attendance', function ($pathParams) {
$restEndPoint = new AttendanceRestEndPoint();
$restEndPoint->process('listAll', $pathParams);
});
\Classes\Macaw::get(REST_API_PATH.'employee/(:num)/attendance', function ($pathParams) {
$restEndPoint = new AttendanceRestEndPoint();
$restEndPoint->process('listEmployeeAttendance', $pathParams);
});
\Classes\Macaw::post(REST_API_PATH.'attendance', function ($pathParams) {
$restEndPoint = new AttendanceRestEndPoint();
$restEndPoint->process('post', $pathParams);
});
\Classes\Macaw::delete(REST_API_PATH.'attendance/(:num)', function ($pathParams) {
$restEndPoint = new AttendanceRestEndPoint();
$restEndPoint->process('delete', $pathParams);
});
\Classes\Macaw::post(REST_API_PATH.'attendance/punch-in', function ($pathParams) {
$restEndPoint = new AttendanceRestEndPoint();
$restEndPoint->process('punchIn', $pathParams);
});
\Classes\Macaw::get(REST_API_PATH.'employee/(:num)/open-punch-in/(:any)', function ($employeeId, $date) {
$restEndPoint = new AttendanceRestEndPoint();
$restEndPoint->process('getOpenPunch', [$employeeId, $date]);
});
\Classes\Macaw::post(REST_API_PATH.'attendance/punch-out', function ($pathParams) {
$restEndPoint = new AttendanceRestEndPoint();
$restEndPoint->process('punchOut', $pathParams);
});
}
public function getDashboardItemData()
{
$data = array();
$attendance = new Attendance();
$data['numberOfAttendanceLastWeek']
= $attendance->Count("in_time > '".date("Y-m-d H:i:s", strtotime("-1 week"))."'");
if (empty($data['numberOfAttendanceLastWeek'])) {
$data['numberOfAttendanceLastWeek'] = 0;
}
return $data;
}
public function initQuickAccessMenu()
{
UIManager::getInstance()->addQuickAccessMenuItem(
"Clocked In Employees",
"fa-clock-o",
CLIENT_BASE_URL."?g=admin&n=attendance&m=admin_Employees#tabAttendanceStatus",
array("Admin","Manager")
);
}
public function initCalculationHooks()
{
$this->addCalculationHook(
'AttendanceUtil_getTimeWorkedHours',
'Total Hours from Attendance',
'\\Attendance\\Admin\\Api\\AttendanceUtil',
'getTimeWorkedHours'
);
$this->addCalculationHook(
'AttendanceUtil_getRegularWorkedHours',
'Total Regular Hours from Attendance',
'\\Attendance\\Admin\\Api\\AttendanceUtil',
'getRegularWorkedHours'
);
$this->addCalculationHook(
'AttendanceUtil_getOverTimeWorkedHours',
'Total Overtime Hours from Attendance',
'\\Attendance\\Admin\\Api\\AttendanceUtil',
'getOverTimeWorkedHours'
);
$this->addCalculationHook(
'AttendanceUtil_getWeeklyRegularWorkedHours',
'Total Weekly Regular Hours from Attendance',
'\\Attendance\\Admin\\Api\\AttendanceUtil',
'getWeeklyBasedRegularHours'
);
$this->addCalculationHook(
'AttendanceUtil_getWeeklyOverTimeWorkedHours',
'Total Weekly Overtime Hours from Attendance',
'\\Attendance\\Admin\\Api\\AttendanceUtil',
'getWeeklyBasedOvertimeHours'
);
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace Attendance\Admin\Api;
use Classes\AbstractModuleManager;
class AttendanceDashboardManager extends AbstractModuleManager
{
public function initializeUserClasses()
{
}
public function initializeFieldMappings()
{
}
public function initializeDatabaseErrorMappings()
{
}
public function setupModuleClassDefinitions()
{
$this->addModelClass('Attendance');
}
}

View File

@@ -0,0 +1,132 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/13/17
* Time: 8:07 AM
*/
namespace Attendance\Admin\Api;
use Attendance\Common\Model\Attendance;
use Classes\SettingsManager;
class AttendanceUtil
{
public function getAttendanceSummary($employeeId, $startDate, $endDate)
{
$startTime = $startDate." 00:00:00";
$endTime = $endDate." 23:59:59";
$attendance = new Attendance();
$atts = $attendance->Find(
"employee = ? and in_time >= ? and out_time <= ?",
array($employeeId, $startTime, $endTime)
);
$atCalClassName = SettingsManager::getInstance()->getSetting('Attendance: Overtime Calculation Class');
$atCalClassName = '\\Attendance\\Common\\Calculations\\'.$atCalClassName;
$atCal = new $atCalClassName();
$atSum = $atCal->getDataSeconds($atts, $startDate, true);
return $atSum;
}
public function getTimeWorkedHours($employeeId, $startDate, $endDate)
{
$atSum = $this->getAttendanceSummary($employeeId, $startDate, $endDate);
return round(($atSum['t']/60)/60, 2);
}
public function getRegularWorkedHours($employeeId, $startDate, $endDate)
{
$atSum = $this->getAttendanceSummary($employeeId, $startDate, $endDate);
return round(($atSum['r']/60)/60, 2);
}
public function getOverTimeWorkedHours($employeeId, $startDate, $endDate)
{
$atSum = $this->getAttendanceSummary($employeeId, $startDate, $endDate);
return round(($atSum['o']/60)/60, 2);
}
public function getWeeklyBasedRegularHours($employeeId, $startDate, $endDate)
{
$atSum = $this->getWeeklyBasedOvertimeSummary($employeeId, $startDate, $endDate);
return round(($atSum['r']/60)/60, 2);
}
public function getWeeklyBasedOvertimeHours($employeeId, $startDate, $endDate)
{
$atSum = $this->getWeeklyBasedOvertimeSummary($employeeId, $startDate, $endDate);
return round(($atSum['o']/60)/60, 2);
}
public function getWeeklyBasedOvertimeSummary($employeeId, $startDate, $endDate)
{
$attendance = new Attendance();
$atTimeByWeek = array();
//Find weeks starting from sunday and ending from saturday in day period
$weeks = $this->getWeeklyDays($startDate, $endDate);
foreach ($weeks as $k => $week) {
$startTime = $week[0]." 00:00:00";
$endTime = $week[count($week) - 1]." 23:59:59";
$atts = $attendance->Find(
"employee = ? and in_time >= ? and out_time <= ?",
array($employeeId, $startTime, $endTime)
);
foreach ($atts as $atEntry) {
if ($atEntry->out_time == "0000-00-00 00:00:00" || empty($atEntry->out_time)) {
continue;
}
if (!isset($atTimeByWeek[$k])) {
$atTimeByWeek[$k] = 0;
}
$diff = strtotime($atEntry->out_time) - strtotime($atEntry->in_time);
if ($diff < 0) {
$diff = 0;
}
$atTimeByWeek[$k] += $diff;
}
}
$overtimeStarts = SettingsManager::getInstance()->getSetting('Attendance: Overtime Start Hour');
$overtimeStarts = (is_numeric($overtimeStarts))?floatval($overtimeStarts) * 60 * 60 * 5 : 0;
$regTime = 0;
$overTime = 0;
foreach ($atTimeByWeek as $value) {
if ($value > $overtimeStarts) {
$regTime += $overtimeStarts;
$overTime = $value - $overtimeStarts;
} else {
$regTime += $value;
}
}
return array('r'=>$regTime,'o'=>$overTime);
}
private function getWeeklyDays($startDate, $endDate)
{
$start = new \DateTime($startDate);
$end = new \DateTime($endDate.' 23:59');
$interval = new \DateInterval('P1D');
$dateRange = new \DatePeriod($start, $interval, $end);
$weekNumber = 1;
$weeks = array();
/* @var \DateTime $date */
foreach ($dateRange as $date) {
$weeks[$weekNumber][] = $date->format('Y-m-d');
if ($date->format('w') == 6) {
$weekNumber++;
}
}
return $weeks;
}
}

View File

@@ -0,0 +1,168 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/13/17
* Time: 6:56 PM
*/
namespace Attendance\Common\Calculations;
use Classes\SettingsManager;
class BasicOvertimeCalculator
{
public function createAttendanceSummary($atts)
{
$atTimeByDay = array();
foreach ($atts as $atEntry) {
if ($atEntry->out_time == "0000-00-00 00:00:00" || empty($atEntry->out_time)) {
continue;
}
$atDate = date("Y-m-d", strtotime($atEntry->in_time));
if (!isset($atTimeByDay[$atDate])) {
$atTimeByDay[$atDate] = 0;
}
$diff = strtotime($atEntry->out_time) - strtotime($atEntry->in_time);
if ($diff < 0) {
$diff = 0;
}
$atTimeByDay[$atDate] += $diff;
}
return $atTimeByDay;
}
public function calculateOvertime($atTimeByDay)
{
$overtimeStarts = SettingsManager::getInstance()->getSetting('Attendance: Overtime Start Hour');
$doubletimeStarts = SettingsManager::getInstance()->getSetting('Attendance: Double time Start Hour');
$overtimeStarts = (is_numeric($overtimeStarts))?floatval($overtimeStarts)*60*60:0;
$doubletimeStarts = (is_numeric($doubletimeStarts))?floatval($doubletimeStarts)*60*60:0;
$atTimeByDayNew = array();
foreach ($atTimeByDay as $k => $v) {
$atTimeByDayNewEntry = array("t"=>$v,"r"=>0,"o"=>0,"d"=>0);
if ($overtimeStarts > 0 && $v > $overtimeStarts) {
$atTimeByDayNewEntry["r"] = $overtimeStarts;
if ($doubletimeStarts > 0 && $doubletimeStarts > $overtimeStarts) {
//calculate double time
if ($v > $doubletimeStarts) {
$atTimeByDayNewEntry['d'] = $v - $doubletimeStarts;
$atTimeByDayNewEntry['o'] = $doubletimeStarts - $overtimeStarts;
} else {
$atTimeByDayNewEntry['d'] = 0 ;
$atTimeByDayNewEntry['o'] = $v - $overtimeStarts;
}
} else {
//ignore double time
$atTimeByDayNewEntry['o'] = $v - $overtimeStarts;
}
} else {
//ignore overtime
$atTimeByDayNewEntry['r'] = $v;
}
$atTimeByDayNew[$k] = $atTimeByDayNewEntry;
}
return $atTimeByDayNew;
}
protected function removeAdditionalDays($atSummary, $actualStartDate)
{
$newAtSummary = array();
foreach ($atSummary as $k => $v) {
if (strtotime($k) >= strtotime($actualStartDate)) {
$newAtSummary[$k] = $v;
}
}
return $newAtSummary;
}
public function getData($atts, $actualStartDate, $aggregate = false)
{
$atSummary = $this->createAttendanceSummary($atts);
$overtime = $this->calculateOvertime($this->removeAdditionalDays($atSummary, $actualStartDate));
if ($aggregate) {
$overtime = $this->aggregateData($overtime);
return $this->convertToHoursAggregated($overtime);
} else {
return $this->convertToHours($overtime);
}
}
public function getDataSeconds($atts, $actualStartDate, $aggregate = false)
{
$atSummary = $this->createAttendanceSummary($atts);
$overtime = $this->calculateOvertime($this->removeAdditionalDays($atSummary, $actualStartDate));
if ($aggregate) {
$overtime = $this->aggregateData($overtime);
return $overtime;
} else {
return $overtime;
}
}
public function convertToHours($overtime)
{
foreach ($overtime as $k => $v) {
$overtime[$k]['t'] = $this->convertToHoursAndMinutes($overtime[$k]['t']);
$overtime[$k]['r'] = $this->convertToHoursAndMinutes($overtime[$k]['r']);
$overtime[$k]['o'] = $this->convertToHoursAndMinutes($overtime[$k]['o']);
$overtime[$k]['d'] = $this->convertToHoursAndMinutes($overtime[$k]['d']);
}
return $overtime;
}
public function convertToHoursAggregated($overtime)
{
$overtime['t'] = $this->convertToHoursAndMinutes($overtime['t']);
$overtime['r'] = $this->convertToHoursAndMinutes($overtime['r']);
$overtime['o'] = $this->convertToHoursAndMinutes($overtime['o']);
$overtime['d'] = $this->convertToHoursAndMinutes($overtime['d']);
return $overtime;
}
protected function aggregateData($overtime)
{
$ag = array("t"=>0,"r"=>0,"o"=>0,"d"=>0);
foreach ($overtime as $k => $v) {
$ag['t'] += $v['t'];
$ag['r'] += $v['r'];
$ag['o'] += $v['o'];
$ag['d'] += $v['d'];
}
return $ag;
}
public function convertToHoursAndMinutes($val)
{
$sec = $val % 60;
$minutesTot = ($val - $sec)/60;
$minutes = $minutesTot % 60;
$hours = ($minutesTot - $minutes)/60;
if ($hours < 10) {
$hours = "0".$hours;
}
if ($minutes < 10) {
$minutes = "0".$minutes;
}
return $hours.":".$minutes;
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace Attendance\Common\Calculations;
use Classes\SettingsManager;
class CaliforniaOvertimeCalculator extends BasicOvertimeCalculator
{
public function getData($atts, $actualStartDate, $aggregate = false)
{
if (count($atts) == 0) {
return array();
}
$atSummary = $this->createAttendanceSummary($atts);
$overtime = $this->calculateOvertime($atSummary);
$workWeekStartDate = SettingsManager::getInstance()->getSetting('Attendance: Work Week Start Day');
//TODO - just assume a work week from Sunday to Saturday
//Find first Sunday in array
$firstDate = null;
$prvDate = null;
$consecutiveWorkDays = 1;
foreach ($overtime as $k => $v) {
if ($firstDate == null) {
$dw = date("w", strtotime($k));
if ($dw == $workWeekStartDate) {
$firstDate = $k;
}
}
if ($firstDate != null) {
if ($prvDate != null && date('Y-m-d', strtotime('-1 day', strtotime($k))) == $prvDate) {
$consecutiveWorkDays++;
if ($consecutiveWorkDays == 7) {
//This is a double time day
$overtime[$k]['d'] = $overtime[$k]['d'] + $overtime[$k]['o'];
$overtime[$k]['o'] = 0;
}
}
//Resetting $consecutiveWorkDays at the start of the work week
if ($prvDate != null && date("w", strtotime($k)) == $workWeekStartDate) {
$consecutiveWorkDays = 1;
$prvDate = null;
}
$prvDate = $k;
}
}
$overtime = $this->removeAdditionalDays($overtime, $actualStartDate);
if ($aggregate) {
$overtime = $this->aggregateData($overtime);
return $this->convertToHoursAggregated($overtime);
} else {
return $this->convertToHours($overtime);
}
}
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/13/17
* Time: 8:04 AM
*/
namespace Attendance\Common\Model;
use Model\BaseModel;
class Attendance extends BaseModel
{
public $table = 'Attendance';
public function getAdminAccess()
{
return array('get','element','save','delete');
}
public function getManagerAccess()
{
return array('get','element','save','delete');
}
public function getUserAccess()
{
return array('get');
}
public function getUserOnlyMeAccess()
{
return array('element','save','delete');
}
}

View File

@@ -0,0 +1,139 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/13/17
* Time: 8:06 AM
*/
namespace Attendance\Common\Model;
use Classes\SettingsManager;
use Employees\Common\Model\Employee;
use Model\BaseModel;
class AttendanceStatus extends BaseModel
{
public $table = 'Attendance';
public function getRecentAttendanceEntries($limit)
{
$shift = intval(SettingsManager::getInstance()->getSetting("Attendance: Shift (Minutes)"));
$attendance = new Attendance();
$attendanceToday = $attendance->Find("1 = 1 order by in_time desc limit ".$limit, array());
$employees = array();
foreach ($attendanceToday as $atEntry) {
$entry = new \stdClass();
$entry->id = $atEntry->employee;
$dayArr = explode(" ", $atEntry->in_time);
$day = $dayArr[0];
if ($atEntry->out_time == "0000-00-00 00:00:00" || empty($atEntry->out_time)) {
if (strtotime($atEntry->in_time) < (time() + $shift * 60) && $day == date("Y-m-d")) {
$entry->status = "Clocked In";
$entry->statusId = 0;
$entry->color = 'green';
$employee = new Employee();
$employee->Load("id = ?", array($entry->id));
$entry->employee = $employee->first_name." ".$employee->last_name;
$employees[$entry->id] = $entry;
}
}
if (!isset($employees[$entry->id])) {
$employee = new Employee();
$employee->Load("id = ?", array($entry->id));
if ($day == date("Y-m-d")) {
$entry->status = "Clocked Out";
$entry->statusId = 1;
$entry->color = 'yellow';
} else {
$entry->status = "Not Clocked In";
$entry->statusId = 2;
$entry->color = 'gray';
}
$entry->employee = $employee->first_name." ".$employee->last_name;
$employees[$entry->id] = $entry;
}
}
return array_values($employees);
}
// @codingStandardsIgnoreStart
public function Find($whereOrderBy, $bindarr = false, $pkeysArr = false, $extra = array())
{
// @codingStandardsIgnoreEnd
$shift = intval(SettingsManager::getInstance()->getSetting("Attendance: Shift (Minutes)"));
$employee = new Employee();
$data = array();
$employees = $employee->Find("1=1");
$attendance = new Attendance();
$attendanceToday = $attendance->Find("date(in_time) = ?", array(date("Y-m-d")));
$attendanceData = array();
//Group by employee
foreach ($attendanceToday as $attendance) {
if (isset($attendanceData[$attendance->employee])) {
$attendanceData[$attendance->employee][] = $attendance;
} else {
$attendanceData[$attendance->employee] = array($attendance);
}
}
foreach ($employees as $employee) {
$entry = new \stdClass();
$entry->id = $employee->id;
$entry->employee = $employee->id;
if (isset($attendanceData[$employee->id])) {
$attendanceEntries = $attendanceData[$employee->id];
foreach ($attendanceEntries as $atEntry) {
if ($atEntry->out_time == "0000-00-00 00:00:00" || empty($atEntry->out_time)) {
if (strtotime($atEntry->in_time) < time() + $shift * 60) {
$entry->status = "Clocked In";
$entry->statusId = 0;
}
}
}
if (empty($entry->status)) {
$entry->status = "Clocked Out";
$entry->statusId = 1;
}
} else {
$entry->status = "Not Clocked In";
$entry->statusId = 2;
}
$data[] = $entry;
}
function cmp($a, $b)
{
return $a->statusId - $b->statusId;
}
usort($data, "cmp");
return $data;
}
public function getAdminAccess()
{
return array("get","element","save","delete");
}
public function getManagerAccess()
{
return array("get","element","save","delete");
}
public function getUserAccess()
{
return array("get");
}
public function getUserOnlyMeAccess()
{
return array("element","save","delete");
}
}

View File

@@ -0,0 +1,189 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/18/17
* Time: 5:05 AM
*/
namespace Attendance\User\Api;
use Attendance\Common\Model\Attendance;
use AttendanceSheets\Common\Model\EmployeeAttendanceSheet;
use Classes\BaseService;
use Classes\IceConstants;
use Classes\IceResponse;
use Classes\SettingsManager;
use Classes\SubActionManager;
use TimeSheets\Common\Model\EmployeeTimeSheet;
use Utils\LogManager;
class AttendanceActionManager extends SubActionManager
{
public function getPunch($req)
{
$date = $req->date;
$arr = explode(" ", $date);
$date = $arr[0];
$employee = $this->baseService->getElement('Employee', $this->getCurrentProfileId(), null, true);
//Find any open punch
$attendance = new Attendance();
$attendance->Load(
"employee = ? and DATE_FORMAT( in_time, '%Y-%m-%d' ) = ? and (out_time is NULL
or out_time = '0000-00-00 00:00:00')",
array($employee->id,$date)
);
if ($attendance->employee == $employee->id) {
//found an open punch
return new IceResponse(IceResponse::SUCCESS, $attendance);
} else {
return new IceResponse(IceResponse::SUCCESS, null);
}
}
public function savePunch($req)
{
$useServerTime = SettingsManager::getInstance()->getSetting('Attendance: Use Department Time Zone');
$currentEmployeeTimeZone = BaseService::getInstance()->getCurrentEmployeeTimeZone();
if ($useServerTime == '1' && !empty($currentEmployeeTimeZone)) {
date_default_timezone_set('Asia/Colombo');
$date = new \DateTime("now", new \DateTimeZone('Asia/Colombo'));
$date->setTimezone(new \DateTimeZone($currentEmployeeTimeZone));
$req->time = $date->format('Y-m-d H:i:s');
}
$req->date = $req->time;
//check if there is an open punch
/* @var \Attendance\Common\Model\Attendance */
$openPunch = $this->getPunch($req)->getData();
if (empty($openPunch)) {
$openPunch = new Attendance();
}
$dateTime = $req->date;
$arr = explode(" ", $dateTime);
$date = $arr[0];
$employee = $this->baseService->getElement('Employee', $this->getCurrentProfileId(), null, true);
//check if dates are differnet
$arr = explode(" ", $openPunch->in_time);
$inDate = $arr[0];
if (!empty($openPunch->in_time) && $inDate != $date) {
return new IceResponse(IceResponse::ERROR, "Attendance entry should be within a single day");
}
//compare dates
if (!empty($openPunch->in_time) && strtotime($dateTime) <= strtotime($openPunch->in_time)) {
return new IceResponse(IceResponse::ERROR, "Punch-in time should be lesser than Punch-out time");
}
//Find all punches for the day
$attendance = new Attendance();
$attendanceList = $attendance->Find(
"employee = ? and DATE_FORMAT( in_time, '%Y-%m-%d' ) = ?",
array($employee->id,$date)
);
foreach ($attendanceList as $attendance) {
if (!empty($openPunch->in_time)) {
if ($openPunch->id == $attendance->id) {
continue;
}
if (strtotime($attendance->out_time) >= strtotime($dateTime)
&& strtotime($attendance->in_time) <= strtotime($dateTime)
) {
//-1---0---1---0 || ---0--1---1---0
return new IceResponse(IceResponse::ERROR, "Time entry is overlapping with an existing one");
} elseif (strtotime($attendance->out_time) >= strtotime($openPunch->in_time)
&& strtotime($attendance->in_time) <= strtotime($openPunch->in_time)
) {
//---0---1---0---1 || ---0--1---1---0
return new IceResponse(IceResponse::ERROR, "Time entry is overlapping with an existing one");
} elseif (strtotime($attendance->out_time) <= strtotime($dateTime)
&& strtotime($attendance->in_time) >= strtotime($openPunch->in_time)
) {
//--1--0---0--1--
return new IceResponse(
IceResponse::ERROR,
"Time entry is overlapping with an existing one ".$attendance->id
);
}
} else {
if (strtotime($attendance->out_time) >= strtotime($dateTime)
&& strtotime($attendance->in_time) <= strtotime($dateTime)
) {
//---0---1---0
return new IceResponse(IceResponse::ERROR, "Time entry is overlapping with an existing one");
}
}
}
if (!empty($openPunch->in_time)) {
$openPunch->out_time = $dateTime;
$openPunch->note = $req->note;
$openPunch->image_out = $req->image;
$this->baseService->audit(IceConstants::AUDIT_ACTION, "Punch Out \ time:".$openPunch->out_time);
} else {
$openPunch->in_time = $dateTime;
//$openPunch->out_time = '0000-00-00 00:00:00';
$openPunch->note = $req->note;
$openPunch->image_in = $req->image;
$openPunch->employee = $employee->id;
$this->baseService->audit(IceConstants::AUDIT_ACTION, "Punch In \ time:".$openPunch->in_time);
}
$ok = $openPunch->Save();
if (!$ok) {
LogManager::getInstance()->info($openPunch->ErrorMsg());
return new IceResponse(IceResponse::ERROR, "Error occured while saving attendance");
}
return new IceResponse(IceResponse::SUCCESS, $openPunch);
}
public function createPreviousAttendnaceSheet($req)
{
$employee = $this->baseService->getElement('Employee', $this->getCurrentProfileId(), null, true);
$timeSheet = new EmployeeAttendanceSheet();
$timeSheet->Load("id = ?", array($req->id));
if ($timeSheet->id != $req->id) {
return new IceResponse(IceResponse::ERROR, "Attendance Sheet not found");
}
if ($timeSheet->employee != $employee->id) {
return new IceResponse(IceResponse::ERROR, "You don't have permissions to add this Attendance Sheet");
}
$end = date("Y-m-d", strtotime("last Saturday", strtotime($timeSheet->date_start)));
$start = date("Y-m-d", strtotime("last Sunday", strtotime($end)));
$tempTimeSheet = new EmployeeTimeSheet();
$tempTimeSheet->Load("employee = ? and date_start = ?", array($employee->id, $start));
if ($employee->id == $tempTimeSheet->employee) {
return new IceResponse(IceResponse::ERROR, "Attendance Sheet already exists");
}
$newTimeSheet = new EmployeeTimeSheet();
$newTimeSheet->employee = $employee->id;
$newTimeSheet->date_start = $start;
$newTimeSheet->date_end = $end;
$newTimeSheet->status = "Pending";
$ok = $newTimeSheet->Save();
if (!$ok) {
LogManager::getInstance()->info("Error creating time sheet : ".$newTimeSheet->ErrorMsg());
return new IceResponse(IceResponse::ERROR, "Error creating Attendance Sheet");
}
return new IceResponse(IceResponse::SUCCESS, "");
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Attendance\User\Api;
use Classes\AbstractModuleManager;
class AttendanceModulesManager extends AbstractModuleManager
{
public function initializeUserClasses()
{
if (defined('MODULE_TYPE') && MODULE_TYPE != 'admin') {
$this->addUserClass("Attendance");
}
}
public function initializeFieldMappings()
{
}
public function initializeDatabaseErrorMappings()
{
}
public function setupModuleClassDefinitions()
{
}
}

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;
}
}

View File

@@ -0,0 +1,50 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 7:48 AM
*/
namespace Company\Admin\Api;
use Classes\AbstractModuleManager;
use Company\Common\Model\CompanyStructure;
class CompanyAdminManager extends AbstractModuleManager
{
public function initializeUserClasses()
{
}
public function initializeFieldMappings()
{
}
public function initializeDatabaseErrorMappings()
{
$this->addDatabaseErrorMapping(
"CONSTRAINT `Fk_Employee_CompanyStructures` FOREIGN KEY (`department`)
REFERENCES `CompanyStructures` (`id`)",
"Can not delete a company structure while employees are assigned to it"
);
$this->addDatabaseErrorMapping(
"CONSTRAINT `Fk_CompanyStructures_Own` FOREIGN KEY (`parent`) REFERENCES ",
"Can not delete a parent structure"
);
}
public function setupModuleClassDefinitions()
{
$this->addModelClass('CompanyStructure');
$this->addModelClass('Timezone');
}
public function getDashboardItemData()
{
$data = array();
$company = new CompanyStructure();
$data['numberOfCompanyStuctures'] = $company->Count("1 = 1");
return $data;
}
}

View File

@@ -0,0 +1,104 @@
<?php
namespace Company\Common\Model;
use Classes\IceResponse;
use Employees\Common\Model\Employee;
use Model\BaseModel;
class CompanyStructure extends BaseModel
{
public $table = 'CompanyStructures';
public function getAdminAccess()
{
return array("get","element","save","delete");
}
public function getManagerAccess()
{
return array("get","element","save","delete");
}
public function getUserAccess()
{
return array("get","element");
}
public function validateSave($obj)
{
if ($obj->id == $obj->parent && !empty($obj->parent)) {
return new IceResponse(
IceResponse::ERROR,
"A Company structure unit can not be the parent of the same unit"
);
}
$heads = json_decode($obj->heads);
foreach ($heads as $head) {
$employee = new Employee();
$employee->Load('id = ?', array($head));
if (!empty($obj->id) && $employee->department != $obj->id) {
$companyStructure = new CompanyStructure();
$companyStructure->Load("id = ?", array($employee->department));
return new IceResponse(
IceResponse::ERROR,
"An employee who is not attached to a company structure can not be the
head of the company structure. ".
"Please remove ".$employee->first_name.' '.$employee->last_name
." from list of heads as this person is attached to ".
$companyStructure->title
);
}
}
return new IceResponse(IceResponse::SUCCESS, "");
}
public static function getAllChildCompanyStructures($companyStructureId)
{
$structures = array();
$companyStructure = new CompanyStructure();
$companyStructure->Load("id = ?", array($companyStructureId));
if ($companyStructure->id != $companyStructureId || empty($companyStructure->id)) {
return new IceResponse(IceResponse::ERROR, array());
}
self::getChildCompanyStructures($companyStructure, $structures);
$structures[$companyStructure->id] = $companyStructure;
return new IceResponse(IceResponse::SUCCESS, array_values($structures));
}
private static function getChildCompanyStructures($companyStructure, &$structures)
{
$child = new CompanyStructure();
$children = $child->Find("parent = ?", array($companyStructure->id));
if (!empty($children)) {
foreach ($children as $c) {
if (isset($structures[$c->id])) {
continue;
}
$structures[$c->id] = $c;
self::getChildCompanyStructures($c, $structures);
}
}
}
public static function isHeadOfCompanyStructure($companyStructureId, $profileId)
{
$companyStructure = new CompanyStructure();
$companyStructure->Load("id = ?", array($companyStructureId));
if (isset($companyStructure->heads) && !empty($companyStructure->heads)) {
$heads = json_decode($companyStructure->heads);
if (is_array($heads) && !empty($heads) && in_array($profileId, $heads)) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace Company\Common\Model;
use Model\BaseModel;
class Timezone extends BaseModel
{
public $table = 'Timezones';
public function getAdminAccess()
{
return array("get","element","save","delete");
}
public function getManagerAccess()
{
return array("get","element","save","delete");
}
public function getUserAccess()
{
return array("get","element");
}
}

View File

@@ -0,0 +1,62 @@
<?php
namespace Dashboard\Admin\Api;
use Attendance\Common\Model\Attendance;
use Candidates\Common\Model\Candidate;
use Classes\IceResponse;
use Classes\SubActionManager;
use Company\Common\Model\CompanyStructure;
use Employees\Common\Model\Employee;
use JobPositions\Common\Model\Job;
use Leaves\Common\Model\EmployeeLeave;
use Projects\Common\Model\Project;
use TimeSheets\Common\Model\EmployeeTimeEntry;
use Training\Common\Model\Course;
use Users\Common\Model\User;
class DashboardActionManager extends SubActionManager
{
public function getInitData($req)
{
$data = array();
$employees = new Employee();
$data['numberOfEmployees'] = $employees->Count("1 = 1");
$company = new CompanyStructure();
$data['numberOfCompanyStuctures'] = $company->Count("1 = 1");
$user = new User();
$data['numberOfUsers'] = $user->Count("1 = 1");
$project = new Project();
$data['numberOfProjects'] = $project->Count("status = 'Active'");
$attendance = new Attendance();
$data['numberOfAttendanceLastWeek'] = $attendance->Count(
"in_time > '".date("Y-m-d H:i:s", strtotime("-1 week"))."'"
);
if (empty($data['numberOfAttendanceLastWeek'])) {
$data['numberOfAttendanceLastWeek'] = 0;
}
$empLeave = new EmployeeLeave();
$data['numberOfLeaves'] = $empLeave->Count("date_start > '".date("Y-m-d")."'");
$timeEntry = new EmployeeTimeEntry();
$data['numberOfAttendanceLastWeek'] = $timeEntry->Count(
"in_time > '".date("Y-m-d H:i:s", strtotime("-1 week"))."'"
);
$candidate = new Candidate();
$data['numberOfCandidates'] = $candidate->Count("1 = 1");
$job = new Job();
$data['numberOfJobs'] = $job->Count("status = 'Active'");
$course = new Course();
$data['numberOfCourses'] = $course->Count("1 = 1");
return new IceResponse(IceResponse::SUCCESS, $data);
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace Dashboard\Admin\Api;
use Classes\AbstractModuleManager;
class DashboardAdminManager extends AbstractModuleManager
{
public function initializeUserClasses()
{
}
public function initializeFieldMappings()
{
}
public function initializeDatabaseErrorMappings()
{
}
public function setupModuleClassDefinitions()
{
}
}

View File

@@ -0,0 +1,95 @@
<?php
namespace Dashboard\User\Api;
use Attendance\Common\Model\Attendance;
use Candidates\Common\Model\Candidate;
use Classes\IceResponse;
use Classes\SubActionManager;
use Employees\Common\Model\Employee;
use JobPositions\Common\Model\Job;
use Leaves\Common\Model\EmployeeLeave;
use Leaves\User\Api\LeavesActionManager;
use Projects\Common\Model\EmployeeProject;
use TimeSheets\Common\Model\EmployeeTimeEntry;
use TimeSheets\Common\Model\EmployeeTimeSheet;
use Training\Common\Model\Course;
class DashboardActionManager extends SubActionManager
{
public function getPendingLeaves($req)
{
$lam = new LeavesActionManager();
$leavePeriod = $lam->getCurrentLeavePeriod(date("Y-m-d H:i:s"), date("Y-m-d H:i:s"));
$leave = new EmployeeLeave();
$pendingLeaves = $leave->Find("status = ? and employee = ?", array("Pending", $this->getCurrentProfileId()));
return new IceResponse(IceResponse::SUCCESS, count($pendingLeaves));
}
public function getInitData($req)
{
$data = array();
$emp = new Employee();
$data['numberOfEmployees'] = $emp->Count(
"status = 'Active' and supervisor = ?",
array($this->getCurrentProfileId())
);
$data['lastTimeSheetHours'] = $this->getLastTimeSheetHours($req)->getData();
$data['activeProjects'] = $this->getEmployeeActiveProjects($req)->getData();
$data['pendingLeaves'] = $this->getPendingLeaves($req)->getData();
$candidate = new Candidate();
$data['numberOfCandidates'] = $candidate->Count("1 = 1");
$job = new Job();
$data['numberOfJobs'] = $job->Count("status = 'Active'");
$attendance = new Attendance();
$data['numberOfAttendanceLastWeek'] = $attendance->Count(
"in_time > '".date("Y-m-d H:i:s", strtotime("-1 week"))."'"
);
$course = new Course();
$data['numberOfCourses'] = $course->Count("1 = 1");
return new IceResponse(IceResponse::SUCCESS, $data);
}
public function getLastTimeSheetHours($req)
{
$timeSheet = new EmployeeTimeSheet();
$timeSheet->Load("employee = ? order by date_end desc limit 1", array($this->getCurrentProfileId()));
if (empty($timeSheet->employee)) {
return new IceResponse(IceResponse::SUCCESS, "0:00");
}
$timeSheetEntry = new EmployeeTimeEntry();
$list = $timeSheetEntry->Find("timesheet = ?", array($timeSheet->id));
$seconds = 0;
foreach ($list as $entry) {
$seconds += (strtotime($entry->date_end) - strtotime($entry->date_start));
}
$minutes = (int)($seconds/60);
$rem = $minutes % 60;
$hours = ($minutes - $rem)/60;
if ($rem < 10) {
$rem = "0".$rem;
}
return new IceResponse(IceResponse::SUCCESS, $hours.":".$rem);
}
public function getEmployeeActiveProjects($req)
{
$project = new EmployeeProject();
$projects = $project->Find("employee = ? and status =?", array($this->getCurrentProfileId(),'Current'));
return new IceResponse(IceResponse::SUCCESS, count($projects));
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace Dashboard\User\Api;
use Classes\AbstractModuleManager;
class DashboardModulesManager extends AbstractModuleManager
{
public function initializeUserClasses()
{
}
public function initializeFieldMappings()
{
}
public function initializeDatabaseErrorMappings()
{
}
public function setupModuleClassDefinitions()
{
}
}

View File

@@ -0,0 +1,283 @@
<?php
namespace Data\Admin\Api;
use Classes\BaseService;
use Classes\IceResponse;
use Data\Common\Model\DataImport;
use FieldNames\Common\Model\CustomField;
use Utils\LogManager;
abstract class AbstractDataImporter implements DataImporter
{
protected $dataImport = null;
protected $headerMapping = array();
protected $primaryKeyColumn = 0;
protected $rowObjects = array();
protected $attachedObjects = array();
protected $objectKeys;
protected $customFields;
protected $columnsCompeted = array();
protected $relatedColumns = array();
public function getResult()
{
return $this->rowObjects;
}
public function getHeaderMapping()
{
return $this->headerMapping;
}
public function processHeader($data)
{
$columns = $this->dataImport->columns;
$headers = json_decode($columns);
$counter = 0;
foreach ($headers as $column) {
$this->headerMapping[] = $column;
if ($column->idField == "Yes") {
$this->primaryKeyColumn = $counter;
}
//Update related columns
if (($column->type == "Reference" || $column->type == "Attached") && $column->isKeyField == "Yes") {
$this->relatedColumns[$counter] = array();
for ($i = 0; $i< count($headers); $i++) {
$columnNew = $headers[$i];
if ($columnNew->id != $column->id &&
$columnNew->dependOn == $column->dependOn && $column->dependOn != "NULL") {
$this->relatedColumns[$counter][$i] = $columnNew;
}
}
}
$counter++;
}
$modelObject = $this->getModelObject();
$obj = new $modelObject();
$this->objectKeys = $obj->getObjectKeys();
$this->updateCustomFields();
}
public function setDataImportId($dataImportId)
{
$this->dataImport = new DataImport();
$this->dataImport->Load("id =?", array($dataImportId));
}
public function updateCustomFields()
{
$customField = new CustomField();
$customFields = $customField->Find("type = ?", array($this->getModelObject()));
$this->customFields = array();
foreach ($customFields as $cf) {
$this->customFields[$cf->name] = $cf;
}
}
public function addCustomField($column)
{
$customField = new CustomField();
$customField->type = $this->getModelObject();
$customField->name = $column->name;
$customField->display = "Form";
$customField->field_type = "text";
$customField->field_label = $column->title;
$customField->field_validation = "none";
$customField->display_order = 0;
$customField->Save();
}
public function markCellCompleted($row, $col)
{
if (!isset($this->columnsCompeted[$row])) {
$this->columnsCompeted[$row] = array();
}
$this->columnsCompeted[$row][$col] = true;
}
public function isCellCompleted($row, $col)
{
if (!isset($this->columnsCompeted[$row])) {
return false;
} else {
if (!isset($this->columnsCompeted[$row][$col])) {
return false;
}
return true;
}
}
public function processData($row, $column, $data, $allData)
{
LogManager::getInstance()->debug("processData:".json_encode($data));
if ($this->isCellCompleted($row, $column)) {
LogManager::getInstance()->debug("Already Competed");
return new IceResponse(IceResponse::SUCCESS, "Already Competed");
}
$headerColumn = $this->headerMapping[$column];
//Load row object if its empty
if (!isset($this->rowObjects[$row])) {
$modelObj = $this->getModelObject();
$this->rowObjects[$row] = new $modelObj();
if ($headerColumn->idField == "Yes") {
LogManager::getInstance()->debug("[processData] Load : $headerColumn->name = $data");
$this->rowObjects[$row]->Load("$headerColumn->name = ?", array($data));
}
}
//Check for non existing column names
if (!isset($this->objectKeys[$headerColumn->name])) {
if (!isset($this->customFields[$headerColumn->name])) {
$this->addCustomField($headerColumn);
$this->updateCustomFields();
}
}
if ($headerColumn->type == "Normal") {
$this->rowObjects[$row]->{$headerColumn->name} = $data;
} elseif ($headerColumn->type == "Reference" || $headerColumn->type == "Attached") {
if ($headerColumn->isKeyField == "Yes") {
$hcClass = BaseService::getInstance()->getFullQualifiedModelClassName($headerColumn->dependOn);
$hcField = $headerColumn->dependOnField;
/* @var \Model\BaseModel $hcObject */
$hcObject = new $hcClass();
if ($headerColumn->type == "Attached" && !empty($this->rowObjects[$row]->id)) {
$hcObject->Load("$hcField = ? and employee = ?", array($data,$this->rowObjects[$row]->id));
} else {
$hcObject->Load("$hcField = ?", array($data));
}
$hcObject->{$hcField} = $data;
foreach ($this->relatedColumns[$column] as $key => $val) {
$tempValName = $val->name;
if (strstr($val->name, "/")) {
$tempValName = explode("/", $val->name)[1];
}
$hcObject->{$tempValName} = $allData[$key];
$this->markCellCompleted($row, $key);
}
if ($headerColumn->type == "Reference") {
$hcObject->Save();
} else {
if (!isset($this->attachedObjects[$row])) {
$this->attachedObjects[$row] = array();
}
$this->attachedObjects[$row][] = $hcObject;
}
$this->rowObjects[$row]->{$headerColumn->name} = $hcObject->id;
}
}
$this->markCellCompleted($row, $column);
return new IceResponse(IceResponse::SUCCESS, $this->rowObjects[$row]);
}
public function processDataRow($row, $data)
{
$result = array();
LogManager::getInstance()->debug("processDataRow:".json_encode($data));
$counter = 0;
foreach ($data as $cell) {
$this->processData($row, $counter, $cell, $data);
$counter++;
}
LogManager::getInstance()->debug("Row Object :" . print_r($this->rowObjects[$row], true));
$this->rowObjects[$row] = $this->fixBeforeSave($this->rowObjects[$row], $data);
if (!$this->isDuplicate($this->rowObjects[$row])) {
$ok = $this->rowObjects[$row]->Save();
if (!$ok) {
LogManager::getInstance()->error(
"Row Object Error Saving Employee :" . $this->rowObjects[$row]->ErrorMsg()
);
$result['Error'] = "Row Object Error Saving Employee :" . $this->rowObjects[$row]->ErrorMsg();
} else {
$result['MainId'] = $this->rowObjects[$row]->id;
$class = $this->getModelObject();
$ele = new $class();
$result['CustomFields'] = array();
$customFields = $ele->getCustomFields($this->rowObjects[$row]);
foreach ($this->rowObjects[$row] as $k => $v) {
if (isset($customFields[$k])) {
BaseService::getInstance()->customFieldManager
->addCustomField($class, $this->rowObjects[$row]->id, $k, $v);
$result['CustomFields'][] = array($class, $this->rowObjects[$row]->id, $k, $v);
}
}
if (!empty($this->attachedObjects[$row])) {
/* @var \Model\BaseModel $aObj */
foreach ($this->attachedObjects[$row] as $aObj) {
$aObj->employee = $this->rowObjects[$row]->id;
$aObj->Save();
$result['attachedObjects'][] = $aObj;
}
}
}
} else {
$result['Error'] = "Duplicate Object Found";
}
return $result;
}
abstract public function getModelObject();
public function isDuplicate($obj)
{
return false;
}
abstract public function fixBeforeSave($object, $data);
public function process($data, $dataImportId)
{
$data = str_replace("\r", "\n", $data);
$data = str_replace("\n\n", "\n", $data);
$lines = str_getcsv($data, "\n");
$headerProcessed = false;
$counter = 0;
LogManager::getInstance()->info("Line Count:".count($lines));
$res = array();
foreach ($lines as $line) {
$cells = str_getcsv($line, ",");
if ($headerProcessed === false) {
$this->setDataImportId($dataImportId);
$this->processHeader($cells);
$headerProcessed = true;
} else {
$result = $this->processDataRow($counter, $cells);
$res[] = array($cells,$result);
}
$counter++;
}
return $res;
}
public function getLastStatus()
{
return IceResponse::SUCCESS;
}
}

View File

@@ -0,0 +1,60 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 8:02 AM
*/
namespace Data\Admin\Api;
use Classes\FileService;
use Classes\IceResponse;
use Classes\SubActionManager;
use Data\Common\Model\DataImport;
use Data\Common\Model\DataImportFile;
use Utils\LogManager;
class DataActionManager extends SubActionManager
{
public function processDataFile($req)
{
$id = $req->id;
$dataFile = new DataImportFile();
$dataFile->Load("id = ?", array($id));
if (empty($dataFile->id)) {
return new IceResponse(IceResponse::ERROR, null);
}
$url = FileService::getInstance()->getFileUrl($dataFile->file);
if (strstr($url, CLIENT_BASE_URL) !== false) {
$url = str_replace(CLIENT_BASE_URL, CLIENT_BASE_PATH, $url);
}
LogManager::getInstance()->info("File Path:".$url);
$data = file_get_contents($url);
$dataImport = new DataImport();
$dataImport->Load("id =?", array($dataFile->data_import_definition));
if (empty($dataImport->id)) {
return new IceResponse(IceResponse::ERROR, null);
}
$processClass = '\\Data\Admin\Import\\'.$dataImport->dataType;
$processObj = new $processClass();
$res = $processObj->process($data, $dataImport->id);
if ($processObj->getLastStatus() === IceResponse::SUCCESS) {
$dataFile->status = "Processed";
}
$dataFile->details = json_encode($res, JSON_PRETTY_PRINT);
$dataFile->Save();
return new IceResponse($processObj->getLastStatus(), $processObj->getResult());
}
private function processHeader($dataImportId, $data)
{
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Data\Admin\Api;
use Classes\AbstractModuleManager;
class DataAdminManager extends AbstractModuleManager
{
public function initializeUserClasses()
{
}
public function initializeFieldMappings()
{
$this->addFileFieldMapping('DataImportFile', 'file', 'name');
}
public function initializeDatabaseErrorMappings()
{
}
public function setupModuleClassDefinitions()
{
$this->addModelClass('DataImport');
$this->addModelClass('DataImportFile');
}
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 10/3/17
* Time: 5:54 PM
*/
namespace Data\Admin\Api;
interface DataImporter
{
public function getResult();
public function process($data, $dataImporterId);
}

View File

@@ -0,0 +1,36 @@
<?php
namespace Data\Admin\Import;
use Attendance\Common\Model\Attendance;
use Data\Admin\Api\AbstractDataImporter;
class AttendanceDataImporter extends AbstractDataImporter
{
protected $processed = array();
public function getModelObject()
{
return "\\Attendance\\Common\\Model\\Attendance";
}
public function fixBeforeSave($object, $data)
{
return $object;
}
public function isDuplicate($obj)
{
$old = new Attendance();
$data = $old->Find(
"employee = ? and in_time = ? and out_time = ?",
array($obj->employee, $obj->in_time, $obj->out_time)
);
if (count($data)>0) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace Data\Admin\Import;
use Data\Admin\Api\AbstractDataImporter;
class EmployeeDataImporter extends AbstractDataImporter
{
protected $processed = array();
public function getModelObject()
{
return "\\Employees\\Common\\Model\\Employee";
}
public function fixBeforeSave($object, $data)
{
if (empty($object->status)) {
$object->status = "Active";
}
return $object;
}
}

View File

@@ -0,0 +1,318 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 10/3/17
* Time: 5:39 PM
*/
namespace Data\Admin\Import;
use Classes\IceResponse;
use Company\Common\Model\CompanyStructure;
use Data\Admin\Api\DataImporter;
use Payroll\Common\Model\Deduction;
use Payroll\Common\Model\DeductionGroup;
use Payroll\Common\Model\Payroll;
use Payroll\Common\Model\PayrollColumn;
use Payroll\Common\Model\PayslipTemplate;
use Salary\Common\Model\SalaryComponent;
use Salary\Common\Model\SalaryComponentType;
use Utils\LogManager;
class PayrollDataImporter implements DataImporter
{
protected $model;
protected $lastStatus = IceResponse::ERROR;
public function getResult()
{
return $this->model;
}
public function process($data, $dataImporterId)
{
$compStructure = new CompanyStructure();
$compStructure->Load("1 = 1 limit 1", array());
if (empty($compStructure->id)) {
$this->lastStatus = IceResponse::ERROR;
return "No company structures exists";
}
$this->model = json_decode($data);
$deductionGroup = $this->createDeductionGroup($this->model);
if (!$deductionGroup) {
$this->lastStatus = IceResponse::ERROR;
return "Deduction group already exists";
}
$salaryComponentTypeIdMap = $this->addSalaryComponentTypes($this->model);
$salaryComponentIdMap = $this->addSalaryComponents($this->model, $salaryComponentTypeIdMap);
$payrollColumnIdMap = $this->addPayrollColumns($this->model, $deductionGroup->id, $salaryComponentIdMap);
$deductionIdMap = $this->addDeductions(
$this->model,
$deductionGroup->id,
$salaryComponentTypeIdMap,
$salaryComponentIdMap,
$payrollColumnIdMap
);
$this->refinePayrollColumns($payrollColumnIdMap, $deductionIdMap);
$payslipTemplate = $this->addPayslipTemplate($this->model, $payrollColumnIdMap);
$this->addPayroll(
$this->model,
$payrollColumnIdMap,
$deductionGroup->id,
$payslipTemplate->id,
$compStructure->id
);
$this->lastStatus = IceResponse::SUCCESS;
return $this->model;
}
protected function addPayroll($model, $payrollColumnIdMap, $deductionGroupId, $payslipId, $departmentId)
{
$samplePr = $model->samplePayroll;
$payroll = new Payroll();
$payroll->name = $samplePr->name;
$payroll->pay_period = $samplePr->pay_period;
$payroll->date_start = $samplePr->date_start;
$payroll->date_end = $samplePr->date_end;
$payroll->columns = $this->replaceJsonIds(
$samplePr->columns,
$payrollColumnIdMap
);
$payroll->status = $samplePr->status;
$payroll->deduction_group = $deductionGroupId;
$payroll->payslipTemplate = $payslipId;
$payroll->department = $departmentId;
$ok = $payroll->Save();
if (!$ok) {
LogManager::getInstance()->error($payroll->ErrorMsg());
}
}
protected function addPayslipTemplate($model, $payrollColumnIdMap)
{
$pst = $model->payslipTemplate;
$payslipTemplate = new PayslipTemplate();
$payslipTemplate->name = $pst->name;
$data = json_decode($pst->data, true);
$newData = [];
foreach ($data as $row) {
if ($row['type'] === 'Payroll Column') {
$row['payrollColumn'] = $payrollColumnIdMap[$row['payrollColumn']];
}
$newData[] = $row;
}
$payslipTemplate->data = json_encode($newData);
$payslipTemplate->status = $pst->status;
$payslipTemplate->created = $pst->created;
$payslipTemplate->updated = $pst->updated;
$payslipTemplate->Save();
return $payslipTemplate;
}
protected function refinePayrollColumns($payrollColumnIdMap, $deductionIdMap)
{
$payrollColumn = new PayrollColumn();
$columns = $payrollColumn->Find('id in ('.implode(',', array_values($payrollColumnIdMap)).')', array());
foreach ($columns as $column) {
$column->deductions = $this->replaceJsonIds(
$column->deductions,
$deductionIdMap
);
$column->add_columns = $this->replaceJsonIds(
$column->add_columns,
$payrollColumnIdMap
);
$column->sub_columns = $this->replaceJsonIds(
$column->sub_columns,
$payrollColumnIdMap
);
$column->sub_columns = $this->replaceJsonIdsForCalculations(
$column->calculation_columns,
$payrollColumnIdMap
);
$column->Save();
}
}
protected function addPayrollColumns($model, $deductionGroupId, $salaryComponentIdMap)
{
$payrollColumnIdMap = [];
$payrollColumns = $model->columns;
foreach ($payrollColumns as $payrollColumn) {
$column = new PayrollColumn();
$column->name = $payrollColumn->name;
$column->calculation_hook = $payrollColumn->calculation_hook;
$column->salary_components = $this->replaceJsonIds(
$payrollColumn->salary_components,
$salaryComponentIdMap
);
$column->deductions = $payrollColumn->deductions; // need to map
$column->add_columns = $payrollColumn->add_columns; // need to map
$column->sub_columns = $payrollColumn->sub_columns; // need to map
$column->colorder = $payrollColumn->colorder;
$column->editable = $payrollColumn->editable;
$column->enabled = $payrollColumn->enabled;
$column->default_value = $payrollColumn->default_value;
$column->calculation_columns = $payrollColumn->calculation_columns; // need to map
$column->calculation_function = $payrollColumn->calculation_function;
$column->deduction_group = $deductionGroupId;
$column->Save();
$payrollColumnIdMap[$payrollColumn->id] = $column->id;
}
return $payrollColumnIdMap;
}
protected function addDeductions(
$model,
$deductionGroupId,
$salaryComponentTypeIdMap,
$salaryComponentIdMap,
$payrollColumnIdMap
) {
$deductionIdMap = [];
$deductions = $model->deductions;
foreach ($deductions as $deduction) {
$dbDeduction = new Deduction();
$dbDeduction->name = $deduction->name;
$dbDeduction->componentType = $this->replaceJsonIds(
$deduction->componentType,
$salaryComponentTypeIdMap
);
$dbDeduction->component = $this->replaceJsonIds(
$deduction->component,
$salaryComponentIdMap
);
$dbDeduction->payrollColumn = $payrollColumnIdMap[$deduction->payrollColumn];
$dbDeduction->rangeAmounts = $deduction->rangeAmounts;
$dbDeduction->deduction_group = $deductionGroupId;
$dbDeduction->Save();
$deductionIdMap[$deduction->id] = $dbDeduction->id;
}
return $deductionIdMap;
}
protected function createDeductionGroup($model)
{
$deductionGroup = new DeductionGroup();
$deductionGroup->Load("name = ?", array($model->name));
if (!empty($deductionGroup->id)) {
return false;
}
$deductionGroup->name = $model->name;
$deductionGroup->description = $model->description;
$ok = $deductionGroup->Save();
if (!$ok) {
return false;
}
return $deductionGroup;
}
/**
* @param $salaryComponentTypeIdMap
*/
protected function addSalaryComponentTypes($model)
{
$salaryComponentTypeIdMap = [];
$salaryComponentTypes = $model->salaryComponentTypes;
foreach ($salaryComponentTypes as $salaryComponentType) {
$tempSct = new SalaryComponentType();
$tempSct->Load(
"code = ? and name = ?",
array($salaryComponentType->code, $salaryComponentType->name)
);
if (!empty($tempSct->id)) {
$salaryComponentTypeIdMap[$salaryComponentType->id] = $tempSct->id;
continue;
}
$tempSct = new SalaryComponentType();
$tempSct->code = $salaryComponentType->code;
$tempSct->name = $salaryComponentType->name;
$tempSct->Save();
$salaryComponentTypeIdMap[$salaryComponentType->id] = $tempSct->id;
}
return $salaryComponentTypeIdMap;
}
protected function addSalaryComponents($model, $salaryComponentTypeIdMap)
{
$salaryComponentIdMap = [];
$salaryComponents = $model->salaryComponents;
foreach ($salaryComponents as $salaryComponent) {
$tempSct = new SalaryComponent();
$tempSct->Load(
"componentType = ? and name = ?",
array(
$salaryComponentTypeIdMap[$salaryComponent->componentType],
$salaryComponent->name
)
);
if (!empty($tempSct->id)) {
$salaryComponentIdMap[$salaryComponent->id] = $tempSct->id;
continue;
}
$tempSct = new SalaryComponent();
$tempSct->name = $salaryComponent->name;
$tempSct->componentType = $salaryComponentTypeIdMap[$salaryComponent->componentType];
$tempSct->details = $salaryComponent->details;
$tempSct->Save();
$salaryComponentIdMap[$salaryComponent->id] = $tempSct->id;
}
return $salaryComponentIdMap;
}
private function replaceJsonIds($ids, $idMap)
{
$newIds = [];
$data = json_decode($ids, true);
foreach ($data as $id) {
$newIds[] = $idMap[$id];
}
return json_encode($newIds);
}
private function replaceJsonIdsForCalculations($calculations, $idMap)
{
$newCalculations = [];
$data = json_decode($calculations, true);
foreach ($data as $cal) {
$cal['column'] = $idMap[$cal['column']];
$newCalculations[] = $cal;
}
return json_encode($newCalculations);
}
public function getLastStatus()
{
return $this->lastStatus;
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace Data\Common\Model;
use Model\BaseModel;
class DataImport extends BaseModel
{
public $table = 'DataImport';
public function getAdminAccess()
{
return array("get","element","save","delete");
}
public function getUserAccess()
{
return array("get","element");
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace Data\Common\Model;
use Classes\IceResponse;
use Model\BaseModel;
class DataImportFile extends BaseModel
{
public $table = 'DataImportFiles';
public function getAdminAccess()
{
return array("get","element","save","delete");
}
public function getUserAccess()
{
return array("get","element");
}
public function executePreSaveActions($obj)
{
if (empty($obj->status)) {
$obj->status = "Not Processed";
}
return new IceResponse(IceResponse::SUCCESS, $obj);
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace Dependents\Common\Model;
use Model\BaseModel;
class EmployeeDependent extends BaseModel
{
public $table = 'EmployeeDependents';
public function getAdminAccess()
{
return array("get","element","save","delete");
}
public function getManagerAccess()
{
return array("get","element","save","delete");
}
public function getUserAccess()
{
return array("get");
}
public function getUserOnlyMeAccess()
{
return array("element","save","delete");
}
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 9:43 AM
*/
namespace Dependents\User\Api;
use Classes\AbstractModuleManager;
class DependentsModulesManager extends AbstractModuleManager
{
public function initializeUserClasses()
{
if (defined('MODULE_TYPE') && MODULE_TYPE != 'admin') {
$this->addUserClass("EmployeeDependent");
}
}
public function initializeFieldMappings()
{
}
public function initializeDatabaseErrorMappings()
{
}
public function setupModuleClassDefinitions()
{
$this->addModelClass('EmployeeDependent');
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace EmergencyContacts\Common\Model;
use Model\BaseModel;
class EmergencyContact extends BaseModel
{
public $table = 'EmergencyContacts';
public function getAdminAccess()
{
return array("get","element","save","delete");
}
public function getManagerAccess()
{
return array("get","element","save","delete");
}
public function getUserAccess()
{
return array("get");
}
public function getUserOnlyMeAccess()
{
return array("element","save","delete");
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace EmergencyContacts\User\Api;
use Classes\AbstractModuleManager;
class EmergencyContactModulesManager extends AbstractModuleManager
{
public function initializeUserClasses()
{
if (defined('MODULE_TYPE') && MODULE_TYPE != 'admin') {
$this->addUserClass("EmergencyContact");
}
}
public function initializeFieldMappings()
{
}
public function initializeDatabaseErrorMappings()
{
}
public function setupModuleClassDefinitions()
{
$this->addModelClass('EmergencyContact');
}
}

View File

@@ -0,0 +1,197 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/27/17
* Time: 5:23 PM
*/
namespace Employees\Admin\Api;
use Attendance\Common\Model\Attendance;
use Classes\BaseService;
use Classes\IceResponse;
use Classes\SubActionManager;
use Dependents\Common\Model\EmployeeDependent;
use Documents\Common\Model\EmployeeDocument;
use EmergencyContacts\Common\Model\EmergencyContact;
use Employees\Common\Model\ArchivedEmployee;
use Employees\Common\Model\Employee;
use Projects\Common\Model\EmployeeProject;
use Qualifications\Common\Model\EmployeeCertification;
use Qualifications\Common\Model\EmployeeEducation;
use Qualifications\Common\Model\EmployeeLanguage;
use Qualifications\Common\Model\EmployeeSkill;
use Salary\Common\Model\EmployeeSalary;
use TimeSheets\Common\Model\EmployeeTimeEntry;
use TimeSheets\Common\Model\EmployeeTimeSheet;
use Travel\Common\Model\EmployeeTravelRecord;
class EmployeesActionManager extends SubActionManager
{
public function terminateEmployee($req)
{
$employee = new Employee();
$employee->Load("id = ?", array($req->id));
if (empty($employee->id)) {
return new IceResponse(IceResponse::ERROR, "Employee Not Found");
}
$employee->termination_date = date('Y-m-d H:i:s');
$employee->status = 'Terminated';
$ok = $employee->Save();
if (!$ok) {
return new IceResponse(IceResponse::ERROR, "Error occurred while terminating employee");
}
return new IceResponse(IceResponse::SUCCESS, $employee);
//$user = BaseService::getInstance()->getUserFromProfileId($employee->id);
}
public function activateEmployee($req)
{
$employee = new Employee();
$employee->Load("id = ?", array($req->id));
if (empty($employee->id)) {
return new IceResponse(IceResponse::ERROR, "Employee Not Found");
}
$employee->termination_date = null;
$employee->status = 'Active';
$ok = $employee->Save();
if (!$ok) {
return new IceResponse(IceResponse::ERROR, "Error occurred while activating employee");
}
return new IceResponse(IceResponse::SUCCESS, $employee);
//$user = BaseService::getInstance()->getUserFromProfileId($employee->id);
}
public function deleteEmployee($req)
{
$employee = new Employee();
$employee->Load("id = ?", array($req->id));
if (empty($employee->id)) {
return new IceResponse(IceResponse::ERROR, "Employee Not Found");
}
$archived = new ArchivedEmployee();
$archived->ref_id = $employee->id;
$archived->employee_id = $employee->employee_id;
$archived->first_name = $employee->first_name;
$archived->last_name = $employee->last_name;
$archived->gender = $employee->gender;
$archived->ssn_num = $employee->ssn_num;
$archived->nic_num = $employee->nic_num;
$archived->other_id = $employee->other_id;
$archived->work_email = $employee->work_email;
$archived->joined_date = $employee->joined_date;
$archived->confirmation_date = $employee->confirmation_date;
$archived->supervisor = $employee->supervisor;
$archived->department = $employee->department;
$archived->termination_date = $employee->termination_date;
$archived->notes = $employee->notes;
$mapping = '{"nationality":["Nationality","id","name"],'
.'"employment_status":["EmploymentStatus","id","name"],"job_title":["JobTitle","id","name"],'
.'"pay_grade":["PayGrade","id","name"],"country":["Country","code","name"],'
.'"province":["Province","id","name"],"department":["CompanyStructure","id","title"],'
.'"supervisor":["Employee","id","first_name+last_name"]}';
$employeeEnriched = BaseService::getInstance()->getElement('Employee', $employee->id, $mapping, true);
$employeeEnriched = BaseService::getInstance()->cleanUpAdoDB($employeeEnriched);
$data = new \stdClass();
$data->enrichedEmployee = $employeeEnriched;
$data->timesheets = $this->getEmployeeData($employee->id, new EmployeeTimeSheet());
$data->timesheetEntries = $this->getEmployeeData($employee->id, new EmployeeTimeEntry());
$data->attendance = $this->getEmployeeData($employee->id, new Attendance());
$data->documents = $this->getEmployeeData($employee->id, new EmployeeDocument());
$data->travelRecords = $this->getEmployeeData($employee->id, new EmployeeTravelRecord());
$data->qualificationSkills = $this->getEmployeeData($employee->id, new EmployeeSkill());
$data->qualificationEducation = $this->getEmployeeData($employee->id, new EmployeeEducation());
$data->qualificationCertifications = $this->getEmployeeData($employee->id, new EmployeeCertification());
$data->qualificationLanguages = $this->getEmployeeData($employee->id, new EmployeeLanguage());
$data->salary = $this->getEmployeeData($employee->id, new EmployeeSalary());
$data->dependants = $this->getEmployeeData($employee->id, new EmployeeDependent());
$data->emergencyContacts = $this->getEmployeeData($employee->id, new EmergencyContact());
$data->projects = $this->getEmployeeData($employee->id, new EmployeeProject());
$archived->data = json_encode($data, JSON_PRETTY_PRINT);
$ok = $archived->Save();
if (!$ok) {
return new IceResponse(IceResponse::ERROR, "Error occurred while archiving employee");
}
$ok = $employee->Delete();
if (!$ok) {
return new IceResponse(IceResponse::ERROR, "Error occurred while deleting employee");
}
return new IceResponse(IceResponse::SUCCESS, $archived);
}
public function downloadArchivedEmployee($req)
{
if ($this->baseService->currentUser->user_level != 'Admin') {
echo "Error: Permission denied";
exit();
}
$employee = new ArchivedEmployee();
$employee->Load("id = ?", array($req->id));
if (empty($employee->id)) {
return new IceResponse(IceResponse::ERROR, "Employee Not Found");
}
$employee->data = json_decode($employee->data);
$employee = $this->baseService->cleanUpAdoDB($employee);
$str = json_encode($employee, JSON_PRETTY_PRINT);
$filename = uniqid();
$file = fopen("/tmp/".$filename, "w");
fwrite($file, $str);
fclose($file);
$downloadFileName = "employee_".$employee->id."_"
.str_replace(" ", "_", $employee->first_name)."_"
.str_replace(" ", "_", $employee->last_name).".txt";
header("Pragma: public"); // required
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Description: File Transfer");
header("Content-Type: image/jpg");
header('Content-Disposition: attachment; filename="'.$downloadFileName.'"');
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize("/tmp/".$filename));
readfile("/tmp/".$filename);
exit();
}
private function getEmployeeData($id, $obj)
{
$data = array();
$objs = $obj->Find("employee = ?", array($id));
foreach ($objs as $entry) {
$data[] = BaseService::getInstance()->cleanUpAdoDB($entry);
}
return $data;
}
}

View File

@@ -0,0 +1,101 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 10:43 AM
*/
namespace Employees\Admin\Api;
use Classes\AbstractModuleManager;
use Classes\UIManager;
use Employees\Common\Model\Employee;
use Employees\Rest\EmployeeRestEndPoint;
class EmployeesAdminManager extends AbstractModuleManager
{
public function initializeUserClasses()
{
}
public function initializeFieldMappings()
{
}
public function setupRestEndPoints()
{
\Classes\Macaw::get(REST_API_PATH.'employees/me', function () {
$empRestEndPoint = new EmployeeRestEndPoint();
$empRestEndPoint->process('get', 'me');
});
\Classes\Macaw::get(REST_API_PATH.'employees/(:num)', function ($pathParams) {
$empRestEndPoint = new EmployeeRestEndPoint();
$empRestEndPoint->process('get', $pathParams);
});
\Classes\Macaw::get(REST_API_PATH.'employees', function () {
$empRestEndPoint = new EmployeeRestEndPoint();
$empRestEndPoint->process('listAll');
});
\Classes\Macaw::post(REST_API_PATH.'employees', function () {
$empRestEndPoint = new EmployeeRestEndPoint();
$empRestEndPoint->process('post');
});
\Classes\Macaw::put(REST_API_PATH.'employees/(:num)', function ($pathParams) {
$empRestEndPoint = new EmployeeRestEndPoint();
$empRestEndPoint->process('put', $pathParams);
});
\Classes\Macaw::delete(REST_API_PATH.'employees/(:num)', function ($pathParams) {
$empRestEndPoint = new EmployeeRestEndPoint();
$empRestEndPoint->process('delete', $pathParams);
});
}
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");
}
public function setupModuleClassDefinitions()
{
$this->addModelClass('Employee');
$this->addModelClass('EmploymentStatus');
$this->addModelClass('EmployeeApproval');
$this->addModelClass('ArchivedEmployee');
}
public function getDashboardItemData()
{
$data = array();
$emp = new Employee();
$data['numberOfEmployees'] = $emp->Count("1 = 1");
return $data;
}
public function initQuickAccessMenu()
{
UIManager::getInstance()->addQuickAccessMenuItem(
"View Employees",
"fa-users",
CLIENT_BASE_URL."?g=admin&n=employees&m=admin_Employees",
array("Admin","Manager")
);
UIManager::getInstance()->addQuickAccessMenuItem(
"Add a New Employee",
"fa-edit",
CLIENT_BASE_URL."?g=admin&n=employees&m=admin_Employees&action=new",
array("Admin")
);
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace Employees\Common\Model;
use Model\BaseModel;
class ArchivedEmployee extends BaseModel
{
public function getAdminAccess()
{
return array("get","element","save","delete");
}
public function getManagerAccess()
{
return array("get","element","save");
}
public function getUserAccess()
{
return array("get");
}
public function getUserOnlyMeAccess()
{
return array("element","save");
}
public function getUserOnlyMeAccessField()
{
return "id";
}
public $table = 'ArchivedEmployees';
}

View File

@@ -0,0 +1,217 @@
<?php
namespace Employees\Common\Model;
use Classes\BaseService;
use Classes\FileService;
use Classes\IceResponse;
use Model\BaseModel;
class Employee extends BaseModel
{
public $oldObj = null;
public $oldObjOrig = null;
public $historyUpdateList = array();
public $historyFieldsToTrack = array(
"employee_id"=>"employee_id",
"first_name"=>"first_name",
"middle_name"=>"middle_name",
"last_name"=>"last_name",
"nationality"=>"nationality_Name",
"birthday"=>"birthday",
"gender"=>"gender",
"marital_status"=>"marital_status",
"ssn_num"=>"ssn_num",
"nic_num"=>"nic_num",
"other_id"=>"other_id",
"employment_status"=>"employment_status_Name",
"job_title"=>"job_title_Name",
"pay_grade"=>"pay_grade_Name",
"work_station_id"=>"work_station_id",
"address1"=>"address1",
"address2"=>"address2",
"city"=>"city_Name",
"country"=>"country_Name",
"province"=>"province_Name",
"postal_code"=>"postal_code",
"home_phone"=>"home_phone",
"mobile_phone"=>"mobile_phone",
"work_phone"=>"work_phone",
"work_email"=>"work_email",
"private_email"=>"private_email",
"joined_date"=>"joined_date",
"confirmation_date"=>"confirmation_date",
"supervisor"=>"supervisor_Name",
"indirect_supervisors"=>"indirect_supervisors",
"department"=>"department_Name"
);
public function getAdminAccess()
{
return array("get","element","save","delete");
}
public function getManagerAccess()
{
return array("get","element","save");
}
public function getUserAccess()
{
return array("get");
}
public function getUserOnlyMeAccess()
{
return array("element","save");
}
public function getUserOnlyMeAccessField()
{
return "id";
}
private function initHistory($obj)
{
$oldObjOrig = new Employee();
$oldObjOrig->Load("id = ?", array($obj->id));
$this->oldObjOrig = $oldObjOrig;
$mapping = '{"nationality":["Nationality","id","name"],'
.'"employment_status":["EmploymentStatus","id","name"],"job_title":["JobTitle","id","name"],'
.'"pay_grade":["PayGrade","id","name"],"country":["Country","code","name"],'
.'"province":["Province","id","name"],"department":["CompanyStructure","id","title"],'
.'"supervisor":["Employee","id","first_name+last_name"]}';
$this->oldObj = BaseService::getInstance()->getElement('Employee', $obj->id, $mapping, true);
}
private function saveHistory($obj)
{
$oldObj = $this->oldObj;
$oldObjOrig = $this->oldObjOrig;
$mapping = '{"nationality":["Nationality","id","name"],'
.'"employment_status":["EmploymentStatus","id","name"],"job_title":["JobTitle","id","name"],'
.'"pay_grade":["PayGrade","id","name"],"country":["Country","code","name"],'
.'"province":["Province","id","name"],"department":["CompanyStructure","id","title"],'
.'"supervisor":["Employee","id","first_name+last_name"]}';
$objEnriched = BaseService::getInstance()->getElement('Employee', $obj->id, $mapping, true);
foreach ($this->historyFieldsToTrack as $k => $v) {
if (empty($oldObjOrig->$k) && $obj->$k = '[]') {
continue;
}
if (empty($obj->$k) && $oldObjOrig->$k == '0000-00-00') {
continue;
}
if ($oldObjOrig->$k != $obj->$k) {
$enrichNewVal = '';
$enrichOldVal = '';
if ($k == 'indirect_supervisors') {
if (!empty($obj->$k) && $obj->$k != '[]') {
$newIndeirectSupervisorIds = json_decode($obj->$k);
foreach ($newIndeirectSupervisorIds as $id) {
$item = BaseService::getInstance()->getItemFromCache("Employee", $id);
if ($enrichNewVal != "") {
$enrichNewVal .= ", ";
}
$enrichNewVal .= $item->first_name." ".$item->last_name;
}
}
if (!empty($oldObjOrig->$k) && $oldObjOrig->$k != '[]') {
$oldIndeirectSupervisorIds = json_decode($oldObjOrig->$k);
foreach ($oldIndeirectSupervisorIds as $id) {
$item = BaseService::getInstance()->getItemFromCache("Employee", $id);
if ($enrichOldVal != "") {
$enrichOldVal .= ", ";
}
$enrichOldVal .= $item->first_name." ".$item->last_name;
}
}
} else {
$enrichOldVal = $oldObj->$v;
$enrichNewVal = $objEnriched->$v;
}
$this->historyUpdateList[] = array($obj->id,$k,$enrichOldVal,$enrichNewVal);
}
}
while (count($this->historyUpdateList)) {
$ele = array_pop($this->historyUpdateList);
BaseService::getInstance()->addHistoryItem("Employee", "Employee", $ele[0], $ele[1], $ele[2], $ele[3]);
}
}
public function executePreSaveActions($obj)
{
if (empty($obj->status)) {
$obj->status = 'Active';
}
return new IceResponse(IceResponse::SUCCESS, $obj);
}
public function executePreUpdateActions($obj)
{
$this->initHistory($obj);
return new IceResponse(IceResponse::SUCCESS, $obj);
}
public function executePostUpdateActions($obj)
{
$this->saveHistory($obj);
}
public function postProcessGetData($obj)
{
$obj = FileService::getInstance()->updateSmallProfileImage($obj);
return $obj;
}
public function getVirtualFields()
{
return array(
"image"
);
}
public function getActiveEmployees()
{
$employee = new Employee();
$list = $employee->Find("status = ?", array('Active'));
return $list;
}
public function getActiveSubordinateEmployees()
{
$employee = new Employee();
if (BaseService::getInstance()->currentUser->user_level != 'Admin') {
$cemp = BaseService::getInstance()->getCurrentProfileId();
$list = $employee->Find("status = ? and supervisor = ?", array('Active', $cemp));
} else {
$list = $employee->Find("status = ?", array('Active'));
}
return $list;
}
public static function cleanEmployeeData($obj)
{
unset($obj->keysToIgnore);
unset($obj->historyFieldsToTrack);
unset($obj->historyUpdateList);
unset($obj->oldObjOrig);
unset($obj->oldObj);
return $obj;
}
public $table = 'Employees';
}

View File

@@ -0,0 +1,32 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 10:41 AM
*/
namespace Employees\Common\Model;
use Model\BaseModel;
class EmployeeApproval extends BaseModel
{
public $table = 'EmployeeApprovals';
public function getAdminAccess()
{
return array("get","element","save","delete");
}
public function getManagerAccess()
{
return array("get","element","save");
}
public function getUserAccess()
{
return array();
}
}

View File

@@ -0,0 +1,32 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 10:40 AM
*/
namespace Employees\Common\Model;
use Model\BaseModel;
class EmploymentStatus extends BaseModel
{
public $table = 'EmploymentStatus';
public function getAdminAccess()
{
return array("get","element","save","delete");
}
public function getManagerAccess()
{
return array("get","element","save");
}
public function getUserAccess()
{
return array();
}
}

View File

@@ -0,0 +1,140 @@
<?php
namespace Employees\Rest;
use Classes\BaseService;
use Classes\Data\Query\DataQuery;
use Classes\IceResponse;
use Classes\PermissionManager;
use Classes\RestEndPoint;
use Employees\Common\Model\Employee;
use Users\Common\Model\User;
class EmployeeRestEndPoint extends RestEndPoint
{
const ELEMENT_NAME = 'Employee';
public function getModelObject($id)
{
$obj = new Employee();
$obj->Load("id = ?", array($id));
return $obj;
}
public function listAll(User $user)
{
$query = new DataQuery('Employee');
$limit = self::DEFAULT_LIMIT;
if (isset($_GET['limit']) && intval($_GET['limit']) > 0) {
$limit = intval($_GET['limit']);
}
$query->setLength($limit);
if ($user->user_level !== 'Admin') {
$query->setIsSubOrdinates(true);
}
return $this->listByQuery($query);
}
public function get(User $user, $parameter)
{
if (empty($parameter)) {
return new IceResponse(IceResponse::ERROR, "Employee not found", 404);
}
if ($parameter === 'me') {
$parameter = BaseService::getInstance()->getCurrentProfileId();
}
if ($user->user_level !== 'Admin' && !PermissionManager::manipulationAllowed(
BaseService::getInstance()->getCurrentProfileId(),
$this->getModelObject($parameter)
)
) {
return new IceResponse(IceResponse::ERROR, "Permission denied", 403);
}
$mapping = [
"nationality" => ["Nationality","id","name"],
"ethnicity" => ["Ethnicity","id","name"],
"immigration_status" => ["ImmigrationStatus","id","name"],
"employment_status" => ["EmploymentStatus","id","name"],
"job_title" => ["JobTitle","id","name"],
"pay_grade" => ["PayGrade","id","name"],
"country" => ["Country","code","name"],
"province" => ["Province","id","name"],
"department" => ["CompanyStructure","id","title"],
"supervisor" => [self::ELEMENT_NAME,"id","first_name+last_name"],
];
$emp = BaseService::getInstance()->getElement(
self::ELEMENT_NAME,
$parameter,
json_encode($mapping),
true
);
$emp = $this->enrichElement($emp, $mapping);
if (!empty($emp)) {
$emp = $this->cleanObject($emp);
$emp = $this->removeNullFields($emp);
return new IceResponse(IceResponse::SUCCESS, $emp);
}
return new IceResponse(IceResponse::ERROR, "Employee not found", 404);
}
public function post(User $user)
{
if ($user->user_level !== 'Admin') {
return new IceResponse(IceResponse::ERROR, "Permission denied", 403);
}
$body = $this->getRequestBody();
$response = BaseService::getInstance()->addElement(self::ELEMENT_NAME, $body);
if ($response->getStatus() === IceResponse::SUCCESS) {
$response = $this->get($user, $response->getData()->id);
$response->setCode(201);
return $response;
}
return new IceResponse(IceResponse::ERROR, $response->getData(), 400);
}
public function put(User $user, $parameter)
{
if ($user->user_level !== 'Admin' &&
!PermissionManager::manipulationAllowed(
BaseService::getInstance()->getCurrentProfileId(),
$this->getModelObject($parameter)
)
) {
return new IceResponse(IceResponse::ERROR, "Permission denied", 403);
}
$body = $this->getRequestBody();
$body['id'] = $parameter;
$response = BaseService::getInstance()->addElement(self::ELEMENT_NAME, $body);
if ($response->getStatus() === IceResponse::SUCCESS) {
return $this->get($user, $response->getData()->id);
}
return new IceResponse(IceResponse::ERROR, 'Error modifying employee', 400);
}
public function delete(User $user, $parameter)
{
if ($user->user_level !== 'Admin') {
return new IceResponse(IceResponse::ERROR, "Permission denied", 403);
}
$response = BaseService::getInstance()->deleteElement(
self::ELEMENT_NAME,
$parameter
);
if ($response->getStatus() === IceResponse::SUCCESS) {
return new IceResponse(IceResponse::SUCCESS, ['id' => $parameter], 200);
}
return new IceResponse(IceResponse::ERROR, $response->getData(), 400);
}
}

View File

@@ -0,0 +1,150 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 10:52 AM
*/
namespace Employees\User\Api;
use Classes\BaseService;
use Classes\FileService;
use Classes\IceResponse;
use Classes\SettingsManager;
use Classes\SubActionManager;
use Company\Common\Model\CompanyStructure;
use Employees\Common\Model\Employee;
use Users\Common\Model\User;
class EmployeesActionManager extends SubActionManager
{
public function get($req)
{
$profileId = $this->getCurrentProfileId();
$cemp = $profileId;
$obj = new Employee();
$cempObj = new Employee();
$cempObj->Load("id = ?", array($cemp));
if ($obj->getUserOnlyMeAccessField() == 'id' &&
SettingsManager::getInstance()->getSetting('System: Company Structure Managers Enabled') == 1 &&
CompanyStructure::isHeadOfCompanyStructure($cempObj->department, $cemp)) {
$subordinates = $obj->Find("supervisor = ?", array($cemp));
if (empty($subordinates)) {
$subordinates = array();
}
$childCompaniesIds = array();
if (SettingsManager::getInstance()->getSetting('System: Child Company Structure Managers Enabled') == '1') {
$childCompaniesResp = CompanyStructure::getAllChildCompanyStructures($cempObj->department);
$childCompanies = $childCompaniesResp->getObject();
foreach ($childCompanies as $cc) {
$childCompaniesIds[] = $cc->id;
}
} else {
$childCompaniesIds[] = $cempObj->department;
}
if (!empty($childCompaniesIds)) {
$childStructureSubordinates
= $obj->Find(
"department in (" . implode(',', $childCompaniesIds) . ") and id != ?",
array($cemp)
);
$subordinates = array_merge($subordinates, $childStructureSubordinates);
}
foreach ($subordinates as $subordinate) {
if ($subordinate->id == $req->id) {
$id = $req->id;
break;
}
}
} else {
$subordinate = new Employee();
$subordinatesCount = $subordinate->Count("supervisor = ? and id = ?", array($profileId, $req->id));
if ($this->user->user_level == 'Admin' || $subordinatesCount > 0) {
$id = $req->id;
}
}
if (empty($id)) {
$id = $profileId;
}
$employee = $this->baseService->getElement('Employee', $id, $req->map, true);
$subordinate = new Employee();
$subordinates = $subordinate->Find("supervisor = ?", array($employee->id));
$employee->subordinates = $subordinates;
$fs = FileService::getInstance();
$employee = $fs->updateProfileImage($employee);
if (!empty($employee->birthday)) {
$employee->birthday = date("F jS, Y", strtotime($employee->birthday));
}
if (!empty($employee->driving_license_exp_date)) {
$employee->driving_license_exp_date = date("F jS, Y", strtotime($employee->driving_license_exp_date));
}
if (!empty($employee->joined_date)) {
$employee->joined_date = date("F jS, Y", strtotime($employee->joined_date));
}
//Read custom fields
try {
$employee = BaseService::getInstance()->customFieldManager->enrichObjectCustomFields('Employee', $employee);
} catch (\Exception $e) {
}
if (empty($employee->id)) {
return new IceResponse(IceResponse::ERROR, $employee);
}
return new IceResponse(
IceResponse::SUCCESS,
array($employee,$this->getCurrentProfileId(),$this->user->employee)
);
}
public function deleteProfileImage($req)
{
$profileId = $this->getCurrentProfileId();
$subordinate = new Employee();
$subordinatesCount = $subordinate->Count("supervisor = ? and id = ?", array($profileId, $req->id));
if ($this->user->user_level == 'Admin' || $this->user->employee == $req->id || $subordinatesCount == 1) {
$fs = FileService::getInstance();
$res = $fs->deleteProfileImage($req->id);
return new IceResponse(IceResponse::SUCCESS, $res);
}
return new IceResponse(IceResponse::ERROR, "Not allowed to delete profile image");
}
public function changePassword($req)
{
if ($this->getCurrentProfileId() != $this->user->employee || empty($this->user->employee)) {
return new IceResponse(IceResponse::ERROR, "You are not allowed to change passwords of other employees");
}
$user = new User();
$user->Load("id = ?", array($this->user->id));
if (empty($user->id)) {
return new IceResponse(IceResponse::ERROR, "Error occurred while changing password");
}
$user->password = md5($req->pwd);
$ok = $user->Save();
if (!$ok) {
return new IceResponse(IceResponse::ERROR, $user->ErrorMsg());
}
return new IceResponse(IceResponse::SUCCESS, $user);
}
}

View File

@@ -0,0 +1,31 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 10:45 AM
*/
namespace Employees\User\Api;
use Classes\AbstractModuleManager;
class EmployeesModulesManager extends AbstractModuleManager
{
public function initializeUserClasses()
{
}
public function initializeFieldMappings()
{
}
public function initializeDatabaseErrorMappings()
{
}
public function setupModuleClassDefinitions()
{
}
}

View File

@@ -0,0 +1,45 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 12:06 PM
*/
namespace Expenses\Admin\Api;
use Classes\Approval\ApproveAdminActionManager;
class ExpensesActionManager extends ApproveAdminActionManager
{
public function getModelClass()
{
return "EmployeeExpense";
}
public function getItemName()
{
return "Expense";
}
public function getModuleName()
{
return "Expense Management";
}
public function getModuleTabUrl()
{
return "g=modules&n=expenses&m=module_Finance";
}
public function getModuleSubordinateTabUrl()
{
return "g=modules&n=expenses&m=module_Finance#tabSubordinateEmployeeExpense";
}
public function getModuleApprovalTabUrl()
{
return "g=modules&n=expenses&m=module_Finance#tabEmployeeExpenseApproval";
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace Expenses\Admin\Api;
use Classes\AbstractModuleManager;
class ExpensesAdminManager extends AbstractModuleManager
{
public function initializeUserClasses()
{
if (defined('MODULE_TYPE') && MODULE_TYPE != 'admin') {
$this->addUserClass("EmployeeExpense");
}
}
public function initializeFieldMappings()
{
$this->addFileFieldMapping('EmployeeExpense', 'attachment1', 'name');
$this->addFileFieldMapping('EmployeeExpense', 'attachment2', 'name');
$this->addFileFieldMapping('EmployeeExpense', 'attachment3', 'name');
}
public function initializeDatabaseErrorMappings()
{
}
public function setupModuleClassDefinitions()
{
$this->addModelClass('ExpensesCategory');
$this->addModelClass('ExpensesPaymentMethod');
$this->addModelClass('EmployeeExpense');
$this->addModelClass('EmployeeExpenseApproval');
}
public function initCalculationHooks()
{
$this->addCalculationHook(
'ExpensePayrollUtils_getApprovedExpensesTotal',
'Total Approved Expenses',
ExpensePayrollUtils::class,
'getApprovedExpensesTotal'
);
}
}

View File

@@ -0,0 +1,71 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 12:10 PM
*/
namespace Expenses\Common\Model;
use Classes\SettingsManager;
use Model\ApproveModel;
class EmployeeExpense extends ApproveModel
{
public $table = 'EmployeeExpenses';
public $notificationModuleName = "Expense Management";
public $notificationUnitName = "Expense";
public $notificationUnitPrefix = "An";
public $notificationUnitAdminUrl = "g=modules&n=expenses&m=module_Finance#tabSubordinateEmployeeExpense";
public $preApproveSettingName = "Expense: Pre-Approve Expenses";
public function isMultiLevelApprovalsEnabled()
{
return (SettingsManager::getInstance()->getSetting('Expense: Enable Multi Level Approvals') == '1');
}
public function getAdminAccess()
{
return array("get","element","save","delete");
}
public function getManagerAccess()
{
return array("get","element","save","delete");
}
public function getUserAccess()
{
return array("get");
}
public function getUserOnlyMeAccess()
{
return array("element","save","delete");
}
public function fieldsNeedToBeApproved()
{
return array(
"amount",
"category",
"payment_method",
"currency"
);
}
public function getType()
{
return 'EmployeeExpense';
}
public function allowIndirectMapping()
{
if (SettingsManager::getInstance()->getSetting('Expense: Allow Indirect Admins to Approve') == '1') {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,19 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 12:12 PM
*/
namespace Expenses\Common\Model;
class EmployeeExpenseApproval extends EmployeeExpense
{
// @codingStandardsIgnoreStart
public function Find($whereOrderBy, $bindarr = false, $pkeysArr = false, $extra = array())
{
// @codingStandardsIgnoreEnd
return $this->findApprovals(new EmployeeExpense(), $whereOrderBy, $bindarr, $pkeysArr, $extra);
}
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 12:08 PM
*/
namespace Expenses\Common\Model;
use Model\BaseModel;
class ExpensesCategory extends BaseModel
{
public $table = 'ExpensesCategories';
public function getAdminAccess()
{
return array("get","element","save","delete");
}
public function getManagerAccess()
{
return array("get","element","save","delete");
}
public function getUserAccess()
{
return array("get");
}
public function getUserOnlyMeAccess()
{
return array("get","element");
}
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 12:10 PM
*/
namespace Expenses\Common\Model;
use Model\BaseModel;
class ExpensesPaymentMethod extends BaseModel
{
public $table = 'ExpensesPaymentMethods';
public function getAdminAccess()
{
return array("get","element","save","delete");
}
public function getManagerAccess()
{
return array("get","element","save","delete");
}
public function getUserAccess()
{
return array("get");
}
public function getUserOnlyMeAccess()
{
return array("get","element");
}
}

View File

@@ -0,0 +1,35 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 12:20 PM
*/
namespace Expenses\User\Api;
use Classes\Approval\ApproveModuleActionManager;
class ExpensesActionManager extends ApproveModuleActionManager
{
public function getModelClass()
{
return "EmployeeExpense";
}
public function getItemName()
{
return "Expense";
}
public function getModuleName()
{
return "Expense Management";
}
public function getModuleTabUrl()
{
return "g=modules&n=expenses&m=module_Finance#tabSubordinateEmployeeExpense";
}
}

View File

@@ -0,0 +1,31 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 12:21 PM
*/
namespace Expenses\User\Api;
use Classes\AbstractModuleManager;
class ExpensesModulesManager extends AbstractModuleManager
{
public function initializeUserClasses()
{
}
public function initializeFieldMappings()
{
}
public function initializeDatabaseErrorMappings()
{
}
public function setupModuleClassDefinitions()
{
}
}

View File

@@ -0,0 +1,32 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 12:29 PM
*/
namespace FieldNames\Admin\Api;
use Classes\AbstractModuleManager;
class FieldNamesAdminManager extends AbstractModuleManager
{
public function initializeUserClasses()
{
}
public function initializeFieldMappings()
{
}
public function initializeDatabaseErrorMappings()
{
}
public function setupModuleClassDefinitions()
{
$this->addModelClass('FieldNameMapping');
$this->addModelClass('CustomField');
}
}

View File

@@ -0,0 +1,64 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 12:27 PM
*/
namespace FieldNames\Common\Model;
use Classes\BaseService;
use Classes\IceResponse;
use Model\BaseModel;
class CustomField extends BaseModel
{
public $table = 'CustomFields';
public function getAdminAccess()
{
return array("get","element","save","delete");
}
public function getUserAccess()
{
return array();
}
public function getAnonymousAccess()
{
return array("get","element");
}
public function validateSave($obj)
{
$type = BaseService::getInstance()->getFullQualifiedModelClassName($obj->type);
$baseObject = new $type();
$fields = $baseObject->getObjectKeys();
if (isset($fields[$obj->name])) {
return new IceResponse(IceResponse::ERROR, "Column name already exists by default");
}
$cf = new CustomField();
if (empty($obj->id)) {
$cf->Load("type = ? and name = ?", array($obj->type, $obj->name));
if ($cf->name == $obj->name) {
return new IceResponse(
IceResponse::ERROR,
"Another custom field with same name has already been added"
);
}
} else {
$cf->Load("type = ? and name = ? and id <> ?", array($obj->type, $obj->name, $obj->id));
if ($cf->name == $obj->name) {
return new IceResponse(
IceResponse::ERROR,
"Another custom field with same name has already been added"
);
}
}
return new IceResponse(IceResponse::SUCCESS, "");
}
}

View File

@@ -0,0 +1,31 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 12:28 PM
*/
namespace FieldNames\Common\Model;
use Model\BaseModel;
class FieldNameMapping extends BaseModel
{
public $table = 'FieldNameMappings';
public function getAdminAccess()
{
return array("get","element","save","delete");
}
public function getUserAccess()
{
return array();
}
public function getAnonymousAccess()
{
return array("get","element");
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 12:54 PM
*/
namespace Jobs\Admin\Api;
use Classes\AbstractModuleManager;
class JobsAdminManager extends AbstractModuleManager
{
public function initializeUserClasses()
{
}
public function initializeFieldMappings()
{
}
public function initializeDatabaseErrorMappings()
{
}
public function setupModuleClassDefinitions()
{
$this->addModelClass('JobTitle');
$this->addModelClass('PayGrade');
}
}

View File

@@ -0,0 +1,26 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 12:52 PM
*/
namespace Jobs\Common\Model;
use Model\BaseModel;
class JobTitle extends BaseModel
{
public $table = 'JobTitles';
public function getAdminAccess()
{
return array("get","element","save","delete");
}
public function getUserAccess()
{
return array();
}
}

View File

@@ -0,0 +1,26 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 12:53 PM
*/
namespace Jobs\Common\Model;
use Model\BaseModel;
class PayGrade extends BaseModel
{
public $table = 'PayGrades';
public function getAdminAccess()
{
return array("get","element","save","delete");
}
public function getUserAccess()
{
return array();
}
}

View File

@@ -0,0 +1,33 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 2:55 PM
*/
namespace Loans\Admin\Api;
use Classes\AbstractModuleManager;
class LoansAdminManager extends AbstractModuleManager
{
public function initializeUserClasses()
{
}
public function initializeFieldMappings()
{
}
public function initializeDatabaseErrorMappings()
{
}
public function setupModuleClassDefinitions()
{
$this->addModelClass('CompanyLoan');
}
}

View File

@@ -0,0 +1,26 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 2:53 PM
*/
namespace Loans\Common\Model;
use Model\BaseModel;
class CompanyLoan extends BaseModel
{
public $table = 'CompanyLoans';
public function getAdminAccess()
{
return array("get","element","save","delete");
}
public function getUserAccess()
{
return array();
}
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* Created by PhpStorm.
* User: Thilina
* Date: 8/19/17
* Time: 2:56 PM
*/
namespace Loans\Common\Model;
use Model\BaseModel;
class EmployeeCompanyLoan extends BaseModel
{
public $table = 'EmployeeCompanyLoans';
public function getAdminAccess()
{
return array("get","element","save","delete");
}
public function getManagerAccess()
{
return array("get","element","save","delete");
}
public function getUserAccess()
{
return array("get");
}
public function getUserOnlyMeAccess()
{
return array("get","element");
}
}

Some files were not shown because too many files have changed in this diff Show More