TimeTrex/classes/modules/core/StationFactory.class.php

2766 lines
87 KiB
PHP
Raw Normal View History

2022-12-13 07:10:06 +01:00
<?php
/*********************************************************************************
*
* TimeTrex is a Workforce Management program developed by
* TimeTrex Software Inc. Copyright (C) 2003 - 2021 TimeTrex Software Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by
* the Free Software Foundation with the addition of the following permission
* added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
* WORK IN WHICH THE COPYRIGHT IS OWNED BY TIMETREX, TIMETREX DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program 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 Affero General Public License for more
* details.
*
*
* You should have received a copy of the GNU Affero General Public License along
* with this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
*
* You can contact TimeTrex headquarters at Unit 22 - 2475 Dobbin Rd. Suite
* #292 West Kelowna, BC V4T 2E9, Canada or at email address info@timetrex.com.
*
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Powered by TimeTrex" logo. If the display of the logo is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Powered by TimeTrex".
*
********************************************************************************/
include_once( 'Net/IPv4.php' );
include_once( 'Net/IPv6.php' );
/**
* @package Core
*/
class StationFactory extends Factory {
protected $table = 'station';
protected $pk_sequence_name = 'station_id_seq'; //PK Sequence name
public $station_id_validator_regex = '/^[a-zA-Z0-9-\*]{1,100}$/i'; //Need to allow: '-' due to UUID (iOS) and for phone numbers, '*' as its a wildcard. We *DONT* need to allow '.', ',' as those are in the Source field only.
protected $company_obj = null;
protected $json_columns = [ 'punch_tag_id' ];
/**
* @param $name
* @param null $parent
* @return array|null
*/
function _getFactoryOptions( $name, $parent = null ) {
//Attempt to get the edition of the currently logged in users company, so we can better tailor the columns to them.
$product_edition_id = Misc::getCurrentCompanyProductEdition();
$retval = null;
switch ( $name ) {
case 'status':
$retval = [
10 => TTi18n::gettext( 'DISABLED' ),
20 => TTi18n::gettext( 'ENABLED' ),
];
break;
case 'type':
$retval = [
10 => TTi18n::gettext( 'PC' ),
];
if ( $product_edition_id >= 15 ) {
$retval[20] = TTi18n::gettext( 'PHONE' );
$retval[25] = TTi18n::gettext( 'WirelessWeb (WAP)' );
$retval[26] = TTi18n::gettext( 'Mobile Web Browser' ); //Controls mobile device web browser from quick punch.
$retval[28] = TTi18n::gettext( 'Mobile App (iOS/Android)' ); //Controls Mobile application
$retval[30] = TTi18n::gettext( 'iButton' );
$retval[40] = TTi18n::gettext( 'Barcode' );
$retval[50] = TTi18n::gettext( 'FingerPrint' );
if ( PRODUCTION == false ) {
$retval[60] = TTi18n::gettext( 'Desktop PC' ); //Single user mode desktop app.
$retval[61] = TTi18n::gettext( 'Kiosk: Desktop PC' );
//$retval[70] = TTi18n::gettext('Kiosk: Web Browser'); //PhoneGap app on WebBrowser KIOSK
//$retval[71] = TTi18n::gettext('Web Browser App'); //PhoneGap app on WebBrowser
}
$retval[65] = TTi18n::gettext( 'Kiosk: Mobile App (iOS/Android)' ); //Mobile app in Kiosk Mode
$retval[100] = TTi18n::gettext( 'TimeClock: TT-A8' );
$retval[150] = TTi18n::gettext( 'TimeClock: TT-US100' );
//$retval[200] = TTi18n::gettext('TimeClock: ACTAtek');
}
break;
case 'station_reserved_word':
$retval = [ 'any', '*' ];
break;
case 'source_reserved_word':
$retval = [ 'any', '*' ];
break;
case 'branch_selection_type':
$retval = [
10 => TTi18n::gettext( 'All Branches' ),
20 => TTi18n::gettext( 'Only Selected Branches' ),
30 => TTi18n::gettext( 'All Except Selected Branches' ),
];
break;
case 'department_selection_type':
$retval = [
10 => TTi18n::gettext( 'All Departments' ),
20 => TTi18n::gettext( 'Only Selected Departments' ),
30 => TTi18n::gettext( 'All Except Selected Departments' ),
];
break;
case 'group_selection_type':
$retval = [
10 => TTi18n::gettext( 'All Groups' ),
20 => TTi18n::gettext( 'Only Selected Groups' ),
30 => TTi18n::gettext( 'All Except Selected Groups' ),
];
break;
case 'poll_frequency':
$retval = [
60 => TTi18n::gettext( '1 Minute' ),
120 => TTi18n::gettext( '2 Minutes' ),
300 => TTi18n::gettext( '5 Minutes' ),
600 => TTi18n::gettext( '10 Minutes' ),
900 => TTi18n::gettext( '15 Minutes' ),
1800 => TTi18n::gettext( '30 Minutes' ),
3600 => TTi18n::gettext( '1 Hour' ),
7200 => TTi18n::gettext( '2 Hours' ),
10800 => TTi18n::gettext( '3 Hours' ),
21600 => TTi18n::gettext( '6 Hours' ),
43200 => TTi18n::gettext( '12 Hours' ),
86400 => TTi18n::gettext( '24 Hours' ),
172800 => TTi18n::gettext( '48 Hours' ),
259200 => TTi18n::gettext( '72 Hours' ),
604800 => TTi18n::gettext( '1 Week' ),
];
break;
case 'partial_push_frequency':
case 'push_frequency':
$retval = [
60 => TTi18n::gettext( '1 Minute' ),
120 => TTi18n::gettext( '2 Minutes' ),
300 => TTi18n::gettext( '5 Minutes' ),
600 => TTi18n::gettext( '10 Minutes' ),
900 => TTi18n::gettext( '15 Minutes' ),
1800 => TTi18n::gettext( '30 Minutes' ),
3600 => TTi18n::gettext( '1 Hour' ),
7200 => TTi18n::gettext( '2 Hours' ),
10800 => TTi18n::gettext( '3 Hours' ),
21600 => TTi18n::gettext( '6 Hours' ),
43200 => TTi18n::gettext( '12 Hours' ),
86400 => TTi18n::gettext( '24 Hours' ),
172800 => TTi18n::gettext( '48 Hours' ),
259200 => TTi18n::gettext( '72 Hours' ),
604800 => TTi18n::gettext( '1 Week' ),
];
break;
case 'time_clock_command':
$retval = [
'test_connection' => TTi18n::gettext( 'Test Connection' ),
'set_date' => TTi18n::gettext( 'Set Date' ),
'download' => TTi18n::gettext( 'Download Data' ),
'upload' => TTi18n::gettext( 'Upload Data' ),
'update_config' => TTi18n::gettext( 'Update Configuration' ),
'delete_data' => TTi18n::gettext( 'Delete all Data' ),
'reset_last_punch_time_stamp' => TTi18n::gettext( 'Reset Last Punch Time' ),
'clear_last_punch_time_stamp' => TTi18n::gettext( 'Clear Last Punch Time' ),
'restart' => TTi18n::gettext( 'Restart' ),
'firmware' => TTi18n::gettext( 'Update Firmware (CAUTION)' ),
];
break;
case 'mode_flag':
Debug::Text( 'Mode Flag Type ID: ' . $parent, __FILE__, __LINE__, __METHOD__, 10 );
if ( $parent == '' ) {
$parent = 0;
}
switch ( (int)$parent ) { //Params should be the station type_id.
case 28: //Mobile App
$retval[$parent] = [
1 => TTi18n::gettext( '-- Default --' ),
//2 => TTi18n::gettext('Punch Mode: Quick Punch'), //Enabled by default.
//4 => TTi18n::gettext('Punch Mode: QRCode'),
//8 => TTi18n::gettext('Punch Mode: QRCode+Face Detection'),
//16 => TTi18n::gettext('Punch Mode: Face Recognition'),
//32 => TTi18n::gettext('Punch Mode: Face Recognition+QRCode'),
//64 => TTi18n::gettext('Punch Mode: Barcode'),
//128 => TTi18n::gettext('Punch Mode: iButton'),
//256
//512
1024 => TTi18n::gettext( 'Disable: Punch' ),
2048 => TTi18n::gettext( 'Disable: GPS' ),
4096 => TTi18n::gettext( 'Enable: Punch Images' ),
//8192 => TTi18n::gettext('Enable: Screensaver'),
16384 => TTi18n::gettext( 'Enable: Auto-Login' ),
//32768 => TTi18n::gettext('Enable: WIFI Detection - Punch'),
//65536 => TTi18n::gettext('Enable: WIFI Detection - Alert'),
131072 => TTi18n::gettext( 'QRCodes: Allow Multiple' ), //For single-employee mode scanning.
262144 => TTi18n::gettext( 'QRCodes: Allow MACROs' ), //For single-employee mode scanning.
1048576 => TTi18n::gettext( 'Disable: Time Synchronization' ),
2097152 => TTi18n::gettext( 'Enable: Pre-Punch Message' ),
4194304 => TTi18n::gettext( 'Enable: Post-Punch Message' ),
8388608 => TTi18n::gettext( 'Enable: Exception Notice' ), //Shows warning or lock-out notice when an exception is triggered that has it enabled.
1073741824 => TTi18n::gettext( 'Enable: Diagnostic Logs' ),
];
break;
case 61: //PC Station in KIOSK mode.
case 65: //Mobile App in KIOSK mode.
$retval[$parent] = [
1 => TTi18n::gettext( '-- Default --' ),
2 => TTi18n::gettext( 'Punch Mode: Quick Punch' ),
4 => TTi18n::gettext( 'Punch Mode: QRCode' ),
//8 => TTi18n::gettext('Punch Mode: QRCode+Face Detection'), //Disabled in v4.0 of app, to simplify things.
16 => TTi18n::gettext( 'Punch Mode: Facial Recognition' ),
//32 => TTi18n::gettext('Punch Mode: Facial Recognition+QRCode'), //Disabled in v4.0 of app, to simplify things.
//64 => TTi18n::gettext('Punch Mode: Quick Punch+Facial Recognition'),
//128
//256
//512
//1024 -- Disable Punch on Single Employee mode.
2048 => TTi18n::gettext( 'Disable: GPS' ),
4096 => TTi18n::gettext( 'Enable: Punch Images' ),
8192 => TTi18n::gettext( 'Disable: Screensaver' ),
16384 => TTi18n::gettext( 'Disable: Default Transfer On' ), //This is not synchronized with mobile app, its handled server side currently.
32768 => TTi18n::gettext( 'Disable: Punch Confirmation' ), //This could be converted to two settings to determine the timeout on the punch confirm/punch success screens instead.
//65536
131072 => TTi18n::gettext( 'QRCodes: Allow Multiple' ),
262144 => TTi18n::gettext( 'QRCodes: Allow MACROs' ),
1048576 => TTi18n::gettext( 'Disable: Time Synchronization' ),
2097152 => TTi18n::gettext( 'Enable: Pre-Punch Message' ),
4194304 => TTi18n::gettext( 'Enable: Post-Punch Message' ),
8388608 => TTi18n::gettext( 'Enable: Exception Notice' ), //Shows warning or lock-out notice when an exception is triggered that has it enabled.
1073741824 => TTi18n::gettext( 'Enable: Diagnostic Logs' ),
];
break;
case 100: //TimeClock
case 150: //TimeClock
default:
$retval[$parent] = [
1 => TTi18n::gettext( '-- Default --' ),
2 => TTi18n::gettext( 'Must Select In/Out Status' ),
//4 => TTi18n::gettext('Enable Work Code (Mode 1)'),
//8 => TTi18n::gettext('Enable Work Code (Mode 2)'),
4 => TTi18n::gettext( 'Disable Out Status' ),
8 => TTi18n::gettext( 'Enable: Breaks' ),
16 => TTi18n::gettext( 'Enable: Lunches' ),
32 => TTi18n::gettext( 'Enable: Branch' ),
64 => TTi18n::gettext( 'Enable: Department' ),
32768 => TTi18n::gettext( 'Authentication: Fingerprint & Password' ),
65536 => TTi18n::gettext( 'Authentication: Fingerprint & Proximity Card' ),
131072 => TTi18n::gettext( 'Authentication: PIN & Fingerprint' ),
262144 => TTi18n::gettext( 'Authentication: Proximity Card & Password' ),
1048576 => TTi18n::gettext( 'Enable: External Proximity Card Reader' ),
2097152 => TTi18n::gettext( 'Enable: Pre-Punch Message' ),
4194304 => TTi18n::gettext( 'Enable: Post-Punch Message' ),
1073741824 => TTi18n::gettext( 'Enable: Diagnostic Logs' ),
];
if ( $product_edition_id >= TT_PRODUCT_CORPORATE ) {
$retval[$parent][128] = TTi18n::gettext( 'Enable: Job' );
$retval[$parent][256] = TTi18n::gettext( 'Enable: Task' );
$retval[$parent][512] = TTi18n::gettext( 'Enable: Quantity' );
$retval[$parent][1024] = TTi18n::gettext( 'Enable: Bad Quantity' );
}
break;
}
ksort( $retval[$parent] );
//Handle cases where parent isn't defined properly.
if ( $parent == 0 ) {
$retval = $retval[$parent];
}
break;
case 'default_mode_flag':
Debug::Text( 'Mode Flag Type ID: ' . $parent, __FILE__, __LINE__, __METHOD__, 10 );
if ( $parent == '' ) {
$parent = 0;
}
switch ( (int)$parent ) { //Params should be the station type_id.
case 28: //Mobile App
$retval[$parent] = [];
break;
//case 61: //PC Station in KIOSK mode.
case 65: //Mobile App in KIOSK mode.
$retval[$parent] = [
2 => TTi18n::gettext( 'Punch Mode: Quick Punch' ),
4 => TTi18n::gettext( 'Punch Mode: QRCode' ),
16 => TTi18n::gettext( 'Punch Mode: Facial Recognition' ),
];
break;
case 100: //TimeClock
case 150: //TimeClock
default:
$retval[$parent] = [];
break;
}
ksort( $retval[$parent] );
//Handle cases where parent isn't defined properly.
if ( $parent == 0 ) {
$retval = $retval[$parent];
}
break;
case 'face_recognition_match_threshold':
$retval = [
'-1000-0' => TTi18n::gettext( '-- Default --' ),
'-1001-99.1' => TTi18n::gettext( '1 (Least Accurate, Easiest)' ),
'-1002-99.2' => TTi18n::gettext( '2' ),
'-1003-99.3' => TTi18n::gettext( '3' ),
'-1004-99.4' => TTi18n::gettext( '4' ),
'-1005-99.5' => TTi18n::gettext( '5' ),
'-1006-99.6' => TTi18n::gettext( '6 (Recommended)' ),
'-1007-99.7' => TTi18n::gettext( '7' ),
'-1008-99.8' => TTi18n::gettext( '8' ),
'-1009-99.9' => TTi18n::gettext( '9' ),
'-1010-100' => TTi18n::gettext( '10 (Most Accurate, Hardest)' ),
];
break;
case 'face_recognition_required_matches':
$retval = [
'-1000-0' => TTi18n::gettext( '-- Default --' ),
'-1001-1' => TTi18n::gettext( '1 (Least Accurate, Fastest)' ), //Takes around 0.1 seconds to obtain.
'-1002-2' => TTi18n::gettext( '2' ),
'-1003-3' => TTi18n::gettext( '3 (Recommended)' ), //Takes around 0.5 seconds to obtain.
'-1004-4' => TTi18n::gettext( '4' ),
'-1005-5' => TTi18n::gettext( '5' ),
'-1006-6' => TTi18n::gettext( '6' ),
'-1007-7' => TTi18n::gettext( '7' ),
'-1008-8' => TTi18n::gettext( '8' ),
'-1009-9' => TTi18n::gettext( '9' ),
'-1010-10' => TTi18n::gettext( '10' ), //Takes around 1.5 seconds to obtain.
'-1011-11' => TTi18n::gettext( '11' ),
'-1012-12' => TTi18n::gettext( '12' ),
'-1013-13' => TTi18n::gettext( '13' ),
'-1014-14' => TTi18n::gettext( '14' ),
'-1015-15' => TTi18n::gettext( '15' ),
'-1016-16' => TTi18n::gettext( '16' ),
'-1017-17' => TTi18n::gettext( '17' ),
'-1018-18' => TTi18n::gettext( '18' ),
'-1019-19' => TTi18n::gettext( '19' ),
'-1020-20' => TTi18n::gettext( '20 (Most Accurate, Slowest)' ), //Takes around 3 seconds to obtain.
];
break;
case 'columns':
$retval = [
'-1010-status' => TTi18n::gettext( 'Status' ),
'-1020-type' => TTi18n::gettext( 'Type' ),
'-1030-source' => TTi18n::gettext( 'Source' ),
'-1140-station_id' => TTi18n::gettext( 'Station' ),
'-1150-description' => TTi18n::gettext( 'Description' ),
'-1160-time_zone' => TTi18n::gettext( 'Time Zone' ),
//'-1170-branch_selection_type' => TTi18n::gettext( 'Branch Selection Type' ),
//'-1180-department_selection_type' => TTi18n::gettext( 'Department Selection Type' ),
//'-1190-group_selection_type' => TTi18n::gettext( 'Group Selection Type' ),
'-1200-last_punch_time_stamp' => TTi18n::gettext( 'Last Punch' ),
'-1210-last_poll_date' => TTi18n::gettext( 'Last Data Synchronization' ),
'-2000-created_by' => TTi18n::gettext( 'Created By' ),
'-2010-created_date' => TTi18n::gettext( 'Created Date' ),
'-2020-updated_by' => TTi18n::gettext( 'Updated By' ),
'-2030-updated_date' => TTi18n::gettext( 'Updated Date' ),
];
break;
case 'list_columns':
$retval = Misc::arrayIntersectByKey( $this->getOptions( 'default_display_columns' ), Misc::trimSortPrefix( $this->getOptions( 'columns' ) ) );
break;
case 'default_display_columns': //Columns that are displayed by default.
$retval = [
'status',
'type',
'source',
'station_id',
'description',
];
break;
case 'unique_columns': //Columns that are unique, and disabled for mass editing.
$retval = [
'station_id',
];
break;
}
return $retval;
}
/**
* @param $data
* @return array
*/
function _getVariableToFunctionMap( $data ) {
$variable_function_map = [
'id' => 'ID',
'company_id' => 'Company',
'status_id' => 'Status',
'status' => false,
'type_id' => 'Type',
'type' => false,
'station_id' => 'Station',
'source' => 'Source',
'description' => 'Description',
'branch_id' => 'DefaultBranch',
'department_id' => 'DefaultDepartment',
'job_id' => 'DefaultJob',
'job_item_id' => 'DefaultJobItem',
'punch_tag_id' => 'DefaultPunchTag',
'time_zone' => 'TimeZone',
'user_group_selection_type_id' => 'GroupSelectionType',
'group_selection_type' => false,
'group' => false,
'branch_selection_type_id' => 'BranchSelectionType',
'branch_selection_type' => false,
'branch' => false,
'department_selection_type_id' => 'DepartmentSelectionType',
'department_selection_type' => false,
'department' => false,
'include_user' => false,
'exclude_user' => false,
'port' => 'Port',
'user_name' => 'UserName',
'password' => 'Password',
'poll_frequency' => 'PollFrequency',
'push_frequency' => 'PushFrequency',
'partial_push_frequency' => 'PartialPushFrequency',
'enable_auto_punch_status' => 'EnableAutoPunchStatus',
'mode_flag' => 'ModeFlag',
'default_mode_flag' => 'DefaultModeFlag',
'work_code_definition' => 'WorkCodeDefinition',
'last_punch_time_stamp' => 'LastPunchTimeStamp',
'last_poll_date' => 'LastPollDate',
'last_poll_status_message' => 'LastPollStatusMessage',
'last_push_date' => 'LastPushDate',
'last_push_status_message' => 'LastPushStatusMessage',
'last_partial_push_date' => 'LastPartialPushDate',
'last_partial_push_status_message' => 'LastPartialPushStatusMessage',
'user_value_1' => 'UserValue1',
'user_value_2' => 'UserValue2',
'user_value_3' => 'UserValue3',
'user_value_4' => 'UserValue4',
'user_value_5' => 'UserValue5',
'allowed_date' => 'AllowedDate',
'deleted' => 'Deleted',
];
return $variable_function_map;
}
/**
* @return bool
*/
function getCompanyObject() {
return $this->getGenericObject( 'CompanyListFactory', $this->getCompany(), 'company_obj' );
}
/**
* @return mixed
*/
function getCompany() {
return $this->getGenericDataValue( 'company_id' );
}
/**
* @param string $value UUID
* @return bool
*/
function setCompany( $value ) {
$value = TTUUID::castUUID( $value );
return $this->setGenericDataValue( 'company_id', $value );
}
/**
* @return bool|int
*/
function getStatus() {
return $this->getGenericDataValue( 'status_id' );
}
/**
* @param $value
* @return bool
*/
function setStatus( $value ) {
$value = (int)trim( $value );
return $this->setGenericDataValue( 'status_id', $value );
}
/**
* @return bool|int
*/
function getType() {
return $this->getGenericDataValue( 'type_id' );
}
/**
* @param $value
* @return bool
*/
function setType( $value ) {
$value = trim( $value ); //Don't cast to (int) above the Option::getByValue() call, otherwise string types will fail on the TimeTrex Client Application.
//This needs to be stay as TimeTrex Client application still uses names rather than IDs.
$key = Option::getByValue( $value, $this->getOptions( 'type' ) );
if ( $key !== false ) {
$value = $key;
}
$value = (int)$value;
return $this->setGenericDataValue( 'type_id', $value );
}
/**
* @param $station
* @return bool
*/
function isUniqueStation( $station ) {
$ph = [
'company_id' => $this->getCompany(),
'station' => (string)$station,
];
$query = 'select id from ' . $this->table . ' where company_id = ? AND station_id = ? AND deleted=0';
$id = $this->db->GetOne( $query, $ph );
Debug::Arr( $id, 'Unique Station: ' . $station, __FILE__, __LINE__, __METHOD__, 10 );
if ( $id === false ) {
return true;
} else {
if ( $id == $this->getId() ) {
return true;
}
}
return false;
}
/**
* @return bool|string
*/
function getStation() {
return (string)$this->getGenericDataValue( 'station_id' ); //Should not be cast to INT!
}
/**
* @param string $value UUID
* @return bool
*/
function setStation( $value = null ) {
$value = trim( $value );
if ( empty( $value ) ) {
$value = $this->genStationID();
}
return $this->setGenericDataValue( 'station_id', $value );
}
/**
* @return bool|mixed
*/
function getSource() {
return $this->getGenericDataValue( 'source' );
}
/**
* @param $value
* @return bool
*/
function setSource( $value ) {
$value = trim( $value );
return $this->setGenericDataValue( 'source', $value );
}
/**
* @return bool|mixed
*/
function getDescription() {
return $this->getGenericDataValue( 'description' );
}
/**
* @param $value
* @return bool
*/
function setDescription( $value ) {
$value = trim( $value );
return $this->setGenericDataValue( 'description', $value );
}
/**
* @return bool|mixed
*/
function getDefaultBranch() {
return $this->getGenericDataValue( 'branch_id' );
}
/**
* @param string $value UUID
* @return bool
*/
function setDefaultBranch( $value ) {
$value = TTUUID::castUUID( $value );
return $this->setGenericDataValue( 'branch_id', $value );
}
/**
* @return bool|mixed
*/
function getDefaultDepartment() {
return $this->getGenericDataValue( 'department_id' );
}
/**
* @param string $value UUID
* @return bool
*/
function setDefaultDepartment( $value ) {
$value = TTUUID::castUUID( $value );
return $this->setGenericDataValue( 'department_id', $value );
}
/**
* @return bool|mixed
*/
function getDefaultJob() {
return $this->getGenericDataValue( 'job_id' );
}
/**
* @param string $value UUID
* @return bool
*/
function setDefaultJob( $value ) {
$value = TTUUID::castUUID( $value );
Debug::Text( 'Default Job ID: ' . $value, __FILE__, __LINE__, __METHOD__, 10 );
if ( getTTProductEdition() <= TT_PRODUCT_PROFESSIONAL ) {
$value = TTUUID::getZeroID();
}
return $this->setGenericDataValue( 'job_id', $value );
}
/**
* @return bool|mixed
*/
function getDefaultJobItem() {
return $this->getGenericDataValue( 'job_item_id' );
}
/**
* @param string $value UUID
* @return bool
*/
function setDefaultJobItem( $value ) {
$value = TTUUID::castUUID( $value );
Debug::Text( 'Default Job Item ID: ' . $value, __FILE__, __LINE__, __METHOD__, 10 );
if ( getTTProductEdition() <= TT_PRODUCT_PROFESSIONAL ) {
$value = TTUUID::getZeroID();
}
return $this->setGenericDataValue( 'job_item_id', $value );
}
/**
* @return array|bool
*/
function getDefaultPunchTag() {
//Always return an array.
$this->decodeJSONColumn( 'punch_tag_id' );
$value = $this->getGenericDataValue( 'punch_tag_id' );
if ( $value == false ) {
return [];
}
return $value;
}
/**
* @param array|string $value UUID
* @return bool
*/
function setDefaultPunchTag( $value ) {
if ( getTTProductEdition() <= TT_PRODUCT_PROFESSIONAL ) {
$value = null;
}
if ( $value == TTUUID::getZeroID() || empty( $value ) ) {
$value = null;
}
if ( !is_array( $value ) && TTUUID::isUUID( $value ) ) {
$value = [ $value ];
}
return $this->setGenericDataValue( 'punch_tag_id', $value );
}
/**
* @return bool|mixed
*/
function getTimeZone() {
return $this->getGenericDataValue( 'time_zone' );
}
/**
* @param $value
* @return bool
*/
function setTimeZone( $value ) {
$value = Misc::trimSortPrefix( trim( $value ) );
return $this->setGenericDataValue( 'time_zone', $value );
}
/**
* @return bool|int
*/
function getGroupSelectionType() {
return $this->getGenericDataValue( 'user_group_selection_type_id' );
}
/**
* @param $value
* @return bool
*/
function setGroupSelectionType( $value ) {
$value = (int)trim( $value );
return $this->setGenericDataValue( 'user_group_selection_type_id', $value );
}
/**
* @return array|bool
*/
function getGroup() {
$lf = TTnew( 'StationUserGroupListFactory' ); /** @var StationUserGroupListFactory $lf */
$lf->getByStationId( $this->getId() );
$list = [];
foreach ( $lf as $obj ) {
$list[] = $obj->getGroup();
}
if ( empty( $list ) == false ) {
return $list;
}
return false;
}
/**
* @param string $ids UUID
* @return bool
*/
function setGroup( $ids ) {
if ( $ids == '' ) {
$ids = []; //This is for the API, it sends FALSE when no branches are selected, so this will delete all branches.
}
if ( !is_array( $ids ) && TTUUID::isUUID( $ids ) ) {
$ids = [ $ids ];
}
Debug::text( 'Setting IDs...', __FILE__, __LINE__, __METHOD__, 10 );
if ( is_array( $ids ) ) {
$tmp_ids = [];
if ( !$this->isNew() ) {
//If needed, delete mappings first.
$lf_a = TTnew( 'StationUserGroupListFactory' ); /** @var StationUserGroupListFactory $lf_a */
$lf_a->getByStationId( $this->getId() );
foreach ( $lf_a as $obj ) {
$id = $obj->getGroup();
Debug::text( 'Group ID: ' . $obj->getGroup() . ' ID: ' . $id, __FILE__, __LINE__, __METHOD__, 10 );
//Delete users that are not selected.
if ( !in_array( $id, $ids ) ) {
Debug::text( 'Deleting: ' . $id, __FILE__, __LINE__, __METHOD__, 10 );
$obj->Delete();
} else {
//Save ID's that need to be updated.
Debug::text( 'NOT Deleting : ' . $id, __FILE__, __LINE__, __METHOD__, 10 );
$tmp_ids[] = $id;
}
}
unset( $id, $obj );
}
//Insert new mappings.
$lf_b = TTnew( 'UserGroupListFactory' ); /** @var UserGroupListFactory $lf_b */
foreach ( $ids as $id ) {
if ( $id !== false && ( TTUUID::isUUID( $id ) && ( $id == TTUUID::getNotExistID() || $id != TTUUID::getZeroID() ) ) && !in_array( $id, $tmp_ids ) ) {
$f = TTnew( 'StationUserGroupFactory' ); /** @var StationUserGroupFactory $f */
$f->setStation( $this->getId() );
$f->setGroup( $id );
$obj = $lf_b->getById( $id )->getCurrent();
if ( $this->Validator->isTrue( 'group',
$f->isValid(),
TTi18n::gettext( 'Selected Group is invalid' ) . ' (' . $obj->getName() . ')' ) ) {
$f->save();
}
}
}
return true;
}
Debug::text( 'No IDs to set.', __FILE__, __LINE__, __METHOD__, 10 );
return false;
}
/**
* @return bool|int
*/
function getBranchSelectionType() {
return $this->getGenericDataValue( 'branch_selection_type_id' );
}
/**
* @param $value
* @return bool
*/
function setBranchSelectionType( $value ) {
$value = (int)trim( $value );
return $this->setGenericDataValue( 'branch_selection_type_id', $value );
}
/**
* @return array|bool
*/
function getBranch() {
$lf = TTnew( 'StationBranchListFactory' ); /** @var StationBranchListFactory $lf */
$lf->getByStationId( $this->getId() );
$list = [];
foreach ( $lf as $obj ) {
$list[] = $obj->getBranch();
}
if ( empty( $list ) == false ) {
return $list;
}
return false;
}
/**
* @param string $ids UUID
* @return bool
*/
function setBranch( $ids ) {
if ( $ids == '' ) {
$ids = []; //This is for the API, it sends FALSE when no branches are selected, so this will delete all branches.
}
if ( !is_array( $ids ) && TTUUID::isUUID( $ids ) ) {
$ids = [ $ids ];
}
//Debug::text('Setting IDs...', __FILE__, __LINE__, __METHOD__, 10);
//Debug::Arr($ids, 'IDs: ', __FILE__, __LINE__, __METHOD__, 10);
if ( is_array( $ids ) ) {
$tmp_ids = [];
if ( !$this->isNew() ) {
//If needed, delete mappings first.
$lf_a = TTnew( 'StationBranchListFactory' ); /** @var StationBranchListFactory $lf_a */
$lf_a->getByStationId( $this->getId() );
foreach ( $lf_a as $obj ) {
$id = $obj->getBranch();
//Debug::text('Branch ID: '. $obj->getBranch() .' ID: '. $id, __FILE__, __LINE__, __METHOD__, 10);
//Delete users that are not selected.
if ( !in_array( $id, $ids ) ) {
Debug::text( 'Deleting: ' . $id, __FILE__, __LINE__, __METHOD__, 10 );
$obj->Delete();
} else {
//Save ID's that need to be updated.
Debug::text( 'NOT Deleting : ' . $id, __FILE__, __LINE__, __METHOD__, 10 );
$tmp_ids[] = $id;
}
}
unset( $id, $obj );
}
//Insert new mappings.
$lf_b = TTnew( 'BranchListFactory' ); /** @var BranchListFactory $lf_b */
foreach ( $ids as $id ) {
if ( $id !== false && ( TTUUID::isUUID( $id ) && $id != TTUUID::getNotExistID() && $id != TTUUID::getZeroID() ) && !in_array( $id, $tmp_ids ) ) {
$f = TTnew( 'StationBranchFactory' ); /** @var StationBranchFactory $f */
$f->setStation( $this->getId() );
$f->setBranch( $id );
$obj = $lf_b->getById( $id )->getCurrent();
if ( $this->Validator->isTrue( 'branch',
$f->isValid(),
TTi18n::gettext( 'Selected Branch is invalid' ) . ' (' . $obj->getName() . ')' ) ) {
$f->save();
}
}
}
return true;
}
Debug::text( 'No IDs to set.', __FILE__, __LINE__, __METHOD__, 10 );
return false;
}
/**
* @return bool|int
*/
function getDepartmentSelectionType() {
return $this->getGenericDataValue( 'department_selection_type_id' );
}
/**
* @param $value
* @return bool
*/
function setDepartmentSelectionType( $value ) {
$value = (int)trim( $value );
return $this->setGenericDataValue( 'department_selection_type_id', $value );
}
/**
* @return array|bool
*/
function getDepartment() {
$lf = TTnew( 'StationDepartmentListFactory' ); /** @var StationDepartmentListFactory $lf */
$lf->getByStationId( $this->getId() );
$list = [];
foreach ( $lf as $obj ) {
$list[] = $obj->getDepartment();
}
if ( empty( $list ) == false ) {
return $list;
}
return false;
}
/**
* @param string $ids UUID
* @return bool
*/
function setDepartment( $ids ) {
if ( $ids == '' ) {
$ids = []; //This is for the API, it sends FALSE when no branches are selected, so this will delete all branches.
}
if ( !is_array( $ids ) && TTUUID::isUUID( $ids ) ) {
$ids = [ $ids ];
}
//Debug::text('Setting IDs...', __FILE__, __LINE__, __METHOD__, 10);
if ( is_array( $ids ) ) {
$tmp_ids = [];
if ( !$this->isNew() ) {
//If needed, delete mappings first.
$lf_a = TTnew( 'StationDepartmentListFactory' ); /** @var StationDepartmentListFactory $lf_a */
$lf_a->getByStationId( $this->getId() );
foreach ( $lf_a as $obj ) {
$id = $obj->getDepartment();
//Debug::text('Department ID: '. $obj->getDepartment() .' ID: '. $id, __FILE__, __LINE__, __METHOD__, 10);
//Delete users that are not selected.
if ( !in_array( $id, $ids ) ) {
Debug::text( 'Deleting: ' . $id, __FILE__, __LINE__, __METHOD__, 10 );
$obj->Delete();
} else {
//Save ID's that need to be updated.
Debug::text( 'NOT Deleting : ' . $id, __FILE__, __LINE__, __METHOD__, 10 );
$tmp_ids[] = $id;
}
}
unset( $id, $obj );
}
//Insert new mappings.
$lf_b = TTnew( 'DepartmentListFactory' ); /** @var DepartmentListFactory $lf_b */
foreach ( $ids as $id ) {
if ( $id !== false && ( TTUUID::isUUID( $id ) && $id != TTUUID::getNotExistID() && $id != TTUUID::getZeroID() ) && !in_array( $id, $tmp_ids ) ) {
$f = TTnew( 'StationDepartmentFactory' ); /** @var StationDepartmentFactory $f */
$f->setStation( $this->getId() );
$f->setDepartment( $id );
$obj = $lf_b->getById( $id )->getCurrent();
if ( $this->Validator->isTrue( 'department',
$f->isValid(),
TTi18n::gettext( 'Selected Department is invalid' ) . ' (' . $obj->getName() . ')' ) ) {
$f->save();
}
}
}
return true;
}
Debug::text( 'No IDs to set.', __FILE__, __LINE__, __METHOD__, 10 );
return false;
}
/**
* @return array|bool
*/
function getIncludeUser() {
$lf = TTnew( 'StationIncludeUserListFactory' ); /** @var StationIncludeUserListFactory $lf */
$lf->getByStationId( $this->getId() );
$list = [];
foreach ( $lf as $obj ) {
$list[] = $obj->getIncludeUser();
}
if ( empty( $list ) == false ) {
return $list;
}
return false;
}
/**
* @param string $ids UUID
* @return bool
*/
function setIncludeUser( $ids ) {
if ( $ids == '' ) {
$ids = []; //This is for the API, it sends FALSE when no branches are selected, so this will delete all branches.
}
if ( !is_array( $ids ) && TTUUID::isUUID( $ids ) ) {
$ids = [ $ids ];
}
Debug::text( 'Setting IDs...', __FILE__, __LINE__, __METHOD__, 10 );
if ( is_array( $ids ) ) {
$tmp_ids = [];
if ( !$this->isNew() ) {
//If needed, delete mappings first.
$lf_a = TTnew( 'StationIncludeUserListFactory' ); /** @var StationIncludeUserListFactory $lf_a */
$lf_a->getByStationId( $this->getId() );
foreach ( $lf_a as $obj ) {
$id = $obj->getIncludeUser();
Debug::text( 'IncludeUser ID: ' . $obj->getIncludeUser() . ' ID: ' . $id, __FILE__, __LINE__, __METHOD__, 10 );
//Delete users that are not selected.
if ( !in_array( $id, $ids ) ) {
Debug::text( 'Deleting: ' . $id, __FILE__, __LINE__, __METHOD__, 10 );
$obj->Delete();
} else {
//Save ID's that need to be updated.
Debug::text( 'NOT Deleting : ' . $id, __FILE__, __LINE__, __METHOD__, 10 );
$tmp_ids[] = $id;
}
}
unset( $id, $obj );
}
//Insert new mappings.
$lf_b = TTnew( 'UserListFactory' ); /** @var UserListFactory $lf_b */
foreach ( $ids as $id ) {
if ( $id !== false && ( TTUUID::isUUID( $id ) && $id != TTUUID::getNotExistID() && $id != TTUUID::getZeroID() ) && !in_array( $id, $tmp_ids ) ) {
$f = TTnew( 'StationIncludeUserFactory' ); /** @var StationIncludeUserFactory $f */
$f->setStation( $this->getId() );
$f->setIncludeUser( $id );
$obj = $lf_b->getById( $id )->getCurrent();
if ( $this->Validator->isTrue( 'include_user',
$f->isValid(),
TTi18n::gettext( 'Selected Employee is invalid' ) . ' (' . $obj->getFullName() . ')' ) ) {
$f->save();
}
}
}
return true;
}
Debug::text( 'No IDs to set.', __FILE__, __LINE__, __METHOD__, 10 );
return false;
}
/**
* @return array|bool
*/
function getExcludeUser() {
$lf = TTnew( 'StationExcludeUserListFactory' ); /** @var StationExcludeUserListFactory $lf */
$lf->getByStationId( $this->getId() );
$list = [];
foreach ( $lf as $obj ) {
$list[] = $obj->getExcludeUser();
}
if ( empty( $list ) == false ) {
return $list;
}
return false;
}
/**
* @param string $ids UUID
* @return bool
*/
function setExcludeUser( $ids ) {
if ( $ids == '' ) {
$ids = []; //This is for the API, it sends FALSE when no branches are selected, so this will delete all branches.
}
if ( !is_array( $ids ) && TTUUID::isUUID( $ids ) ) {
$ids = [ $ids ];
}
Debug::text( 'Setting IDs...', __FILE__, __LINE__, __METHOD__, 10 );
if ( is_array( $ids ) ) {
$tmp_ids = [];
if ( !$this->isNew() ) {
//If needed, delete mappings first.
$lf_a = TTnew( 'StationExcludeUserListFactory' ); /** @var StationExcludeUserListFactory $lf_a */
$lf_a->getByStationId( $this->getId() );
foreach ( $lf_a as $obj ) {
$id = $obj->getExcludeUser();
Debug::text( 'ExcludeUser ID: ' . $obj->getExcludeUser() . ' ID: ' . $id, __FILE__, __LINE__, __METHOD__, 10 );
//Delete users that are not selected.
if ( !in_array( $id, $ids ) ) {
Debug::text( 'Deleting: ' . $id, __FILE__, __LINE__, __METHOD__, 10 );
$obj->Delete();
} else {
//Save ID's that need to be updated.
Debug::text( 'NOT Deleting : ' . $id, __FILE__, __LINE__, __METHOD__, 10 );
$tmp_ids[] = $id;
}
}
unset( $id, $obj );
}
//Insert new mappings.
$lf_b = TTnew( 'UserListFactory' ); /** @var UserListFactory $lf_b */
foreach ( $ids as $id ) {
if ( $id !== false && ( TTUUID::isUUID( $id ) && $id != TTUUID::getNotExistID() && $id != TTUUID::getZeroID() ) && !in_array( $id, $tmp_ids ) ) {
$f = TTnew( 'StationExcludeUserFactory' ); /** @var StationExcludeUserFactory $f */
$f->setStation( $this->getId() );
$f->setExcludeUser( $id );
$obj = $lf_b->getById( $id )->getCurrent();
if ( $this->Validator->isTrue( 'exclude_user',
$f->isValid(),
TTi18n::gettext( 'Selected Employee is invalid' ) . ' (' . $obj->getFullName() . ')' ) ) {
$f->save();
}
}
}
return true;
}
Debug::text( 'No IDs to set.', __FILE__, __LINE__, __METHOD__, 10 );
return false;
}
/*
TimeClock specific fields
*/
/**
* @return bool|mixed
*/
function getPort() {
return $this->getGenericDataValue( 'port' );
}
/**
* @param $value
* @return bool
*/
function setPort( $value ) {
$value = trim( $value );
return $this->setGenericDataValue( 'port', $value );
}
/**
* @return bool|mixed
*/
function getUserName() {
return $this->getGenericDataValue( 'user_name' );
}
/**
* @param $value
* @return bool
*/
function setUserName( $value ) {
$value = trim( $value );
return $this->setGenericDataValue( 'user_name', $value );
}
/**
* @return bool|mixed
*/
function getPassword() {
return $this->getGenericDataValue( 'password' );
}
/**
* @param $value
* @return bool
*/
function setPassword( $value ) {
$value = trim( $value );
return $this->setGenericDataValue( 'password', $value );
}
/**
* @return bool|mixed
*/
function getPollFrequency() {
return $this->getGenericDataValue( 'poll_frequency' );
}
/**
* @param $value
* @return bool
*/
function setPollFrequency( $value ) {
$value = trim( $value );
return $this->setGenericDataValue( 'poll_frequency', $value );
}
/**
* @return bool|mixed
*/
function getPushFrequency() {
return $this->getGenericDataValue( 'push_frequency' );
}
/**
* @param $value
* @return bool
*/
function setPushFrequency( $value ) {
$value = trim( $value );
return $this->setGenericDataValue( 'push_frequency', $value );
}
/**
* @return bool|mixed
*/
function getPartialPushFrequency() {
return $this->getGenericDataValue( 'partial_push_frequency' );
}
/**
* @param $value
* @return bool
*/
function setPartialPushFrequency( $value ) {
$value = trim( $value );
return $this->setGenericDataValue( 'partial_push_frequency', $value );
}
/**
* @return bool
*/
function getEnableAutoPunchStatus() {
return $this->fromBool( $this->getGenericDataValue( 'enable_auto_punch_status' ) );
}
/**
* @param $value
* @return bool
*/
function setEnableAutoPunchStatus( $value ) {
return $this->setGenericDataValue( 'enable_auto_punch_status', $this->toBool( $value ) );
}
/**
* @return array|bool
*/
function getModeFlag() {
$value = $this->getGenericDataValue( 'mode_flag' );
if ( $value !== false ) {
return Option::getArrayByBitMask( $value, $this->getOptions( 'mode_flag', $this->getType() ) );
}
return false;
}
/**
* @param $arr
* @return bool
*/
function setModeFlag( $arr ) {
$value = Option::getBitMaskByArray( $arr, $this->getOptions( 'mode_flag', $this->getType() ) );
return $this->setGenericDataValue( 'mode_flag', $value );
}
/**
* @return bool|int
*/
function getDefaultModeFlag() {
return $this->getGenericDataValue( 'default_mode_flag' );
}
/**
* @param $value
* @return bool
*/
function setDefaultModeFlag( $value ) {
$value = (int)$value;
return $this->setGenericDataValue( 'default_mode_flag', $value );
}
/**
* @param $work_code
* @return array
*/
function parseWorkCode( $work_code ) {
$definition = $this->getWorkCodeDefinition();
$work_code = str_pad( $work_code, 9, 0, STR_PAD_LEFT );
$retarr = [ 'branch_id' => 0, 'department_id' => 0, 'job_id' => 0, 'job_item_id' => 0 ];
$start_digit = 0;
if ( isset( $definition['branch'] ) && TTUUID::isUUID( $definition['branch'] ) && $definition['branch'] != TTUUID::getZeroID() && $definition['branch'] != TTUUID::getNotExistID() ) {
$retarr['branch_id'] = (int)substr( $work_code, $start_digit, $definition['branch'] );
$start_digit += $definition['branch'];
}
if ( isset( $definition['department'] ) && TTUUID::isUUID( $definition['department'] ) && $definition['department'] != TTUUID::getZeroID() && $definition['department'] != TTUUID::getNotExistID() ) {
$retarr['department_id'] = (int)substr( $work_code, $start_digit, $definition['department'] );
$start_digit += $definition['department'];
}
if ( isset( $definition['job'] ) && TTUUID::isUUID( $definition['job'] ) && $definition['job'] != TTUUID::getZeroID() && $definition['job'] != TTUUID::getNotExistID() ) {
$retarr['job_id'] = (int)substr( $work_code, $start_digit, $definition['job'] );
$start_digit += $definition['job'];
}
if ( isset( $definition['job_item'] ) && TTUUID::isUUID( $definition['job_item'] ) && $definition['job_item'] != TTUUID::getZeroID() && $definition['job_item'] != TTUUID::getNotExistID() ) {
$retarr['job_item_id'] = (int)substr( $work_code, $start_digit, $definition['job_item'] );
//$start_digit += $definition['job_item'];
}
Debug::Arr( $retarr, 'Parsed Work Code: ', __FILE__, __LINE__, __METHOD__, 10 );
return $retarr;
}
/**
* Update JUST station last_poll_date AND last_punch_time_stamp without affecting updated_date, and without creating an EDIT entry in the system_log.
* @param string $id UUID
* @param int $last_poll_date
* @param int $last_punch_date
* @return bool
*/
function updateLastPollDateAndLastPunchTimeStamp( $id, $last_poll_date = 0, $last_punch_date = 0 ) {
if ( $id == '' ) {
return false;
}
$slf = TTnew( 'StationListFactory' ); /** @var StationListFactory $slf */
$slf->getById( $id );
if ( $slf->getRecordCount() == 1 ) {
$ph = [
'last_poll_date' => $last_poll_date,
'last_punch_date' => $this->db->BindTimeStamp( $last_punch_date ),
'id' => $id,
];
$query = 'UPDATE ' . $this->getTable() . ' set last_poll_date = ?, last_punch_time_stamp = ? where id = ?';
$this->ExecuteSQL( $query, $ph );
return true;
}
return false;
}
/**
* Update JUST station last_poll_date without affecting updated_date, and without creating an EDIT entry in the system_log.
* @param string $id UUID
* @param int $last_poll_date
* @return bool
*/
function updateLastPollDate( $id, $last_poll_date = 0 ) {
if ( $id == '' ) {
return false;
}
$slf = TTnew( 'StationListFactory' ); /** @var StationListFactory $slf */
$slf->getById( $id );
if ( $slf->getRecordCount() == 1 ) {
$ph = [
'last_poll_date' => $last_poll_date,
'id' => $id,
];
$query = 'UPDATE ' . $this->getTable() . ' set last_poll_date = ? where id = ?';
$this->ExecuteSQL( $query, $ph );
return true;
}
return false;
}
/**
* Update JUST station last_push_date without affecting updated_date, and without creating an EDIT entry in the system_log.
* @param string $id UUID
* @param int $last_push_date
* @return bool
*/
function updateLastPushDate( $id, $last_push_date = 0 ) {
if ( $id == '' ) {
return false;
}
$slf = TTnew( 'StationListFactory' ); /** @var StationListFactory $slf */
$slf->getById( $id );
if ( $slf->getRecordCount() == 1 ) {
$ph = [
'last_push_date' => $last_push_date,
'id' => $id,
];
$query = 'UPDATE ' . $this->getTable() . ' set last_push_date = ? where id = ?';
$this->ExecuteSQL( $query, $ph );
return true;
}
return false;
}
/**
* Update JUST station last_partial_push_date without affecting updated_date, and without creating an EDIT entry in the system_log.
* @param string $id UUID
* @param int $last_partial_push_date
* @return bool
*/
function updateLastPartialPushDate( $id, $last_partial_push_date = 0 ) {
if ( $id == '' ) {
return false;
}
$slf = TTnew( 'StationListFactory' ); /** @var StationListFactory $slf */
$slf->getById( $id );
if ( $slf->getRecordCount() == 1 ) {
$ph = [
'last_partial_push_date' => $last_partial_push_date,
'id' => $id,
];
$query = 'UPDATE ' . $this->getTable() . ' set last_partial_push_date = ? where id = ?';
$this->ExecuteSQL( $query, $ph );
return true;
}
return false;
}
/**
* @param bool $raw
* @return bool|int
*/
function getLastPunchTimeStamp( $raw = false ) {
$value = $this->getGenericDataValue( 'last_punch_time_stamp' );
if ( $value !== false ) {
if ( $raw === true ) {
return $value;
} else {
return TTDate::strtotime( $value );
}
}
return false;
}
/**
* @param int $value EPOCH
* @return bool
*/
function setLastPunchTimeStamp( $value = null ) {
$value = ( !is_int( $value ) && $value !== null ) ? trim( $value ) : $value;//Dont trim integer values, as it changes them to strings.
if ( $value == null ) {
$value = TTDate::getTime();
}
return $this->setGenericDataValue( 'last_punch_time_stamp', $value );
}
/**
* @return bool|mixed
*/
function getLastPollDate() {
return $this->getGenericDataValue( 'last_poll_date' );
}
/**
* @param int $value EPOCH
* @return bool
*/
function setLastPollDate( $value = null ) {
$value = ( !is_int( $value ) && $value !== null ) ? trim( $value ) : $value;//Dont trim integer values, as it changes them to strings.
if ( $value == null ) {
$value = TTDate::getTime();
}
return $this->setGenericDataValue( 'last_poll_date', $value );
}
/**
* @return bool|mixed
*/
function getLastPollStatusMessage() {
return $this->getGenericDataValue( 'last_poll_status_message' );
}
/**
* @param $value
* @return bool
*/
function setLastPollStatusMessage( $value ) {
$value = trim( $value );
return $this->setGenericDataValue( 'last_poll_status_message', $value );
}
/**
* @return bool|mixed
*/
function getLastPushDate() {
return $this->getGenericDataValue( 'last_push_date' );
}
/**
* @param int $value EPOCH
* @return bool
*/
function setLastPushDate( $value = null ) {
$value = ( !is_int( $value ) && $value !== null ) ? trim( $value ) : $value;//Dont trim integer values, as it changes them to strings.
if ( $value == null ) {
$value = TTDate::getTime();
}
return $this->setGenericDataValue( 'last_push_date', $value );
}
/**
* @return bool|mixed
*/
function getLastPushStatusMessage() {
return $this->getGenericDataValue( 'last_push_status_message' );
}
/**
* @param $value
* @return bool
*/
function setLastPushStatusMessage( $value ) {
$value = trim( $value );
return $this->setGenericDataValue( 'last_push_status_message', $value );
}
/**
* @return bool|mixed
*/
function getLastPartialPushDate() {
return $this->getGenericDataValue( 'last_partial_push_date' );
}
/**
* @param int $value EPOCH
* @return bool
*/
function setLastPartialPushDate( $value = null ) {
$value = ( !is_int( $value ) && $value !== null ) ? trim( $value ) : $value;//Dont trim integer values, as it changes them to strings.
if ( $value == null ) {
$value = TTDate::getTime();
}
return $this->setGenericDataValue( 'last_partial_push_date', $value );
}
/**
* @return bool|mixed
*/
function getLastPartialPushStatusMessage() {
return $this->getGenericDataValue( 'last_partial_push_status_message' );
}
/**
* @param $value
* @return bool
*/
function setLastPartialPushStatusMessage( $value ) {
$value = trim( $value );
return $this->setGenericDataValue( 'last_partial_push_status_message', $value );
}
/**
* @return string
*/
function getUserValue1() {
return $this->getGenericDataValue( 'user_value_1' );
}
/**
* @param $value
* @return bool
*/
function setUserValue1( $value ) {
$value = trim( $value );
return $this->setGenericDataValue( 'user_value_1', $value );
}
/**
* @return string
*/
function getUserValue2() {
return $this->getGenericDataValue( 'user_value_2' );
}
/**
* @param $value
* @return bool
*/
function setUserValue2( $value ) {
$value = trim( $value );
return $this->setGenericDataValue( 'user_value_2', $value );
}
/**
* @return string
*/
function getUserValue3() {
return $this->getGenericDataValue( 'user_value_3' );
}
/**
* @param $value
* @return bool
*/
function setUserValue3( $value ) {
$value = trim( $value );
return $this->setGenericDataValue( 'user_value_3', $value );
}
/**
* @return string
*/
function getUserValue4() {
return $this->getGenericDataValue( 'user_value_4' );
}
/**
* @param $value
* @return bool
*/
function setUserValue4( $value ) {
$value = trim( $value );
return $this->setGenericDataValue( 'user_value_4', $value );
}
/**
* @return string
*/
function getUserValue5() {
return $this->getGenericDataValue( 'user_value_5' );
}
/**
* @param $value
* @return bool
*/
function setUserValue5( $value ) {
$value = trim( $value );
return $this->setGenericDataValue( 'user_value_5', $value );
}
/**
* @return string
*/
private function genStationID() {
return md5( uniqid( dechex( mt_rand() ), true ) );
}
/**
* @return bool
*/
function setCookie() {
if ( $this->getStation() ) {
setcookie( 'StationID', $this->getStation(), ( time() + 157680000 ), Environment::getCookieBaseURL() );
return true;
}
return false;
}
/**
* @return bool
*/
function destroyCookie() {
setcookie( 'StationID', '', ( time() + 9999999 ), Environment::getCookieBaseURL() );
return true;
}
/**
* Update JUST station allowed_date without affecting updated_date, and without creating an EDIT entry in the system_log.
* @param string $id UUID
* @param string $user_id UUID
* @return bool
*/
function updateAllowedDate( $id, $user_id ) {
if ( $id == '' ) {
return false;
}
if ( $user_id == '' ) {
return false;
}
if ( TTUUID::isUUID( $id ) == true ) { //Don't bother looking up the station record again as this is only called from one place and we can fairly confident the record already exists.
Debug::text( ' Updating Allowed Date for Station: ID: ' . $id . ' User ID: ' . $user_id, __FILE__, __LINE__, __METHOD__, 10 );
$ph = [
'allowed_date' => TTDate::getTime(),
'id' => $id,
];
//If many users are punching in/out at the same time and it happens to be associated with a wildcard station, there would be lock contention on that record.
// Since allowed_date is not critically important, skip updating it if the row is already locked.
//$query = 'UPDATE ' . $this->getTable() . ' set allowed_date = ? where id = ?';
$query = 'UPDATE ' . $this->getTable() . ' as b set allowed_date = ? WHERE EXISTS ( SELECT null FROM '. $this->getTable() .' as a where b.id = a.id and b.id = ? FOR UPDATE OF A SKIP LOCKED )';
$this->ExecuteSQL( $query, $ph );
//Debug::Query( $query, $ph, __FILE__, __LINE__, __METHOD__, 10 );
TTLog::addEntry( $id, 200, TTi18n::getText( 'Access from station Allowed' ), $user_id, $this->getTable() ); //Allow
return true;
}
return false;
}
/**
* @return bool|mixed
*/
function getAllowedDate() {
return $this->getGenericDataValue( 'allowed_date' );
}
/**
* @param int $value EPOCH
* @return bool
*/
function setAllowedDate( $value = null ) {
$value = ( !is_int( $value ) && $value !== null ) ? trim( $value ) : $value;//Dont trim integer values, as it changes them to strings.
if ( $value == null ) {
$value = TTDate::getTime();
}
return $this->setGenericDataValue( 'allowed_date', $value );
}
/**
* @param $source
* @param string $current_station_id UUID
* @return bool
*/
function checkSource( $source, $current_station_id ) {
$source = trim( $source );
$remote_addr = Misc::getRemoteIPAddress();
if ( in_array( $this->getType(), [ 10, 25, 26, 28 ] )
&& (
preg_match( '/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}(\/[0-9]{1,2})*/', $source ) //IPv4
||
preg_match( '/(((?=(?>.*?(::))(?!.+\3)))\3?|([\dA-F]{1,4}(\3|:(?!$)|$)|\2))(?4){5}((?4){2}|((2[0-4]|1\d|[1-9])?\d|25[0-5])(\.(?7)){3})*/i', $source ) //IPv6
)
) {
Debug::text( 'Source is an IP address!', __FILE__, __LINE__, __METHOD__, 10 );
} else if ( in_array( $this->getType(), [ 10, 25, 26, 28, 100 ] ) && !in_array( strtolower( $this->getSource() ), $this->getOptions( 'station_reserved_word' ) ) ) {
//Do hostname lookups for TTA8 timeclocks as well.
Debug::text( 'Source is NOT an IP address, do hostname lookup: ' . $source, __FILE__, __LINE__, __METHOD__, 10 );
$hostname_lookup = $this->getCache( 'station_source_dns_' . $this->getCompany() . $source );
if ( $hostname_lookup === false ) {
$hostname_lookup = gethostbyname( $source );
$this->saveCache( $hostname_lookup, 'station_source_dns_' . $this->getCompany() . $source );
}
if ( $hostname_lookup == $source ) {
Debug::text( 'Hostname lookup failed!', __FILE__, __LINE__, __METHOD__, 10 );
} else {
Debug::text( 'Hostname lookup succeeded: ' . $hostname_lookup, __FILE__, __LINE__, __METHOD__, 10 );
$source = $hostname_lookup;
}
unset( $hostname_lookup );
} else {
Debug::text( 'Source is not internet related', __FILE__, __LINE__, __METHOD__, 10 );
}
Debug::text( 'Source: ' . $source . ' Remote IP: ' . $remote_addr, __FILE__, __LINE__, __METHOD__, 10 );
if ( (
$current_station_id == $this->getStation()
|| in_array( strtolower( $this->getStation() ), $this->getOptions( 'station_reserved_word' ) )
)
&&
(
in_array( strtolower( $this->getSource() ), $this->getOptions( 'source_reserved_word' ) )
||
( $source == $remote_addr )
||
( $current_station_id == $this->getSource() )
||
( Net_IPv4::validateIP( $remote_addr ) && Net_IPv4::ipInNetwork( $remote_addr, $source ) )
||
( Net_IPv6::checkIPv6( $remote_addr ) && strpos( $source, '/' ) !== false && Net_IPv6::isInNetmask( $remote_addr, $source ) ) //isInNetMask requires a netmask to be specified, otherwise it always returns TRUE.
||
in_array( $this->getType(), [ 100, 110, 120, 200 ] )
)
) {
Debug::text( 'Returning TRUE', __FILE__, __LINE__, __METHOD__, 10 );
return true;
}
Debug::text( 'Returning FALSE', __FILE__, __LINE__, __METHOD__, 10 );
return false;
}
/**
* @param string $user_id UUID
* @param string $current_station_id UUID
* @param string $id UUID
* @param bool $update_allowed_date
* @return bool
*/
function isAllowed( $user_id = null, $current_station_id = null, $id = null, $update_allowed_date = true ) {
if ( $user_id == null || $user_id == '' ) {
global $current_user;
$user_id = $current_user->getId();
}
//Debug::text('User ID: '. $user_id, __FILE__, __LINE__, __METHOD__, 10);
if ( $current_station_id == null || $current_station_id == '' ) {
global $current_station;
$current_station_id = $current_station->getStation();
}
//Debug::text('Station ID: '. $current_station_id, __FILE__, __LINE__, __METHOD__, 10);
//Debug::text('Status: '. $this->getStatus(), __FILE__, __LINE__, __METHOD__, 10);
if ( $this->getStatus() != 20 ) { //Enabled
return false;
}
$retval = false;
Debug::text( 'User ID: ' . $user_id . ' Station ID: ' . $current_station_id . ' ID: '. $id .' Status: ' . $this->getStatus() . ' Current Station: ' . $this->getStation(), __FILE__, __LINE__, __METHOD__, 10 );
//Handle IP Addresses/Hostnames
if ( in_array( $this->getType(), [ 10, 25, 26, 28 ] )
&& !in_array( strtolower( $this->getSource() ), $this->getOptions( 'source_reserved_word' ) ) ) {
if ( strpos( $this->getSource(), ',' ) !== false ) {
//Found list
$source = explode( ',', $this->getSource() );
} else {
//Found single entry
$source[] = $this->getSource();
}
if ( is_array( $source ) ) {
foreach ( $source as $tmp_source ) {
if ( $this->checkSource( $tmp_source, $current_station_id ) == true ) {
$retval = true;
break;
}
}
unset( $tmp_source );
}
} else {
$source = $this->getSource();
$retval = $this->checkSource( $source, $current_station_id );
}
//Debug::text('Retval: '. (int)$retval, __FILE__, __LINE__, __METHOD__, 10);
//Debug::text('Current Station ID: '. $current_station_id .' Station ID: '. $this->getStation(), __FILE__, __LINE__, __METHOD__, 10);
if ( $retval === true ) {
Debug::text( 'Station IS allowed! ', __FILE__, __LINE__, __METHOD__, 10 );
//Set last allowed date, so we can track active/inactive stations.
if ( $id != null && $id != '' && $update_allowed_date == true ) {
$this->updateAllowedDate( $id, $user_id );
}
return true;
}
Debug::text( 'Station IS NOT allowed! ', __FILE__, __LINE__, __METHOD__, 10 );
return false;
}
/**
* A fast way to check many stations if the user is allowed. 10 = PC
* @param string $user_id UUID
* @param string $station_id UUID
* @param int $type
* @param bool $update_allowed_date
* @return bool
* @parem bool $update_allowed_date Updates the station allowed date, which should only be done when a punch is saved.
*/
function checkAllowed( $user_id = null, $station_id = null, $type = 10, $update_allowed_date = true, $return_station_id = false ) {
if ( $user_id == null || $user_id == '' ) {
global $current_user;
$user_id = $current_user->getId();
}
Debug::text( 'User ID: ' . $user_id, __FILE__, __LINE__, __METHOD__, 10 );
if ( $station_id == null || $station_id == '' ) {
global $current_station;
if ( is_object( $current_station ) ) {
$station_id = $current_station->getStation();
} else if ( $this->getId() != '' ) {
$station_id = $this->getId();
} else {
Debug::text( 'Unable to get Station Object! Station ID: ' . $station_id, __FILE__, __LINE__, __METHOD__, 10 );
return false;
}
}
$slf = TTnew( 'StationListFactory' ); /** @var StationListFactory $slf */
$slf->getByUserIdAndStatusAndType( $user_id, 20, $type, $station_id ); //Station ID just helps order more specific stations to the top of the list.
Debug::text( 'Station ID: ' . $station_id . ' Type: ' . $type . ' Found Stations: ' . $slf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10 );
if ( $slf->getRecordCount() > 0 ) {
foreach ( $slf as $station ) { /** @var StationFactory $station */
Debug::text( 'Checking Station ID: ' . $station->getId(), __FILE__, __LINE__, __METHOD__, 10 );
if ( $station->isAllowed( $user_id, $station_id, $station->getId(), $update_allowed_date ) === true ) {
Debug::text( 'Station IS allowed! ' . $station_id . ' - ID: ' . $station->getId() . ' Return Station ID: ' . (int)$return_station_id, __FILE__, __LINE__, __METHOD__, 10 );
if ( $return_station_id == true ) {
return $station->getId();
} else {
return true;
}
}
}
}
return false;
}
/**
* @param string $station_id UUID
* @param string $company_id UUID
* @param int $type_id
* @param string $description
* @param Permission $permission_obj
* @param UserFactory $user_obj
* @return bool|object|StationFactory|StationListFactory|string
* @throws DBError
* @throws GeneralError
*/
static function getOrCreateStation( $station_id, $company_id, $type_id = 10, $description = null, $permission_obj = null, $user_obj = null ) {
Debug::text( 'Checking for Station ID: ' . $station_id . ' Company ID: ' . $company_id . ' Type: ' . $type_id, __FILE__, __LINE__, __METHOD__, 10 );
$slf = new StationListFactory();
$slf->getByStationIdandCompanyId( $station_id, $company_id );
if ( $slf->getRecordCount() == 1 ) {
//Handle disabled station here, but only for KIOSK type stations.
//As non-kiosk stations still need to be able to revert back to the wildcard ANY station and check that for access. Where KIOSK stations will not do that.
if ( $slf->getCurrent()->getStatus() == 10 && in_array( $slf->getCurrent()->getType(), [ 61, 65 ] ) ) { //Disabled
Debug::text( 'aStation is disabled...' . $station_id, __FILE__, __LINE__, __METHOD__, 10 );
$slf->Validator->isTrue( 'status_id',
false,
TTi18n::gettext( 'Waiting for Administrator approval to activate this device' ) );
return $slf;
} else if ( $slf->getCurrent()->getStatus() == 10 && in_array( $slf->getCurrent()->getType(), [ 28 ] ) ) {
//Check isAllowed for any wildcard stations first...
if ( $slf->getCurrent()->checkAllowed( $user_obj->getId(), $station_id, $type_id ) == true ) {
$retval = $slf->getCurrent()->getStation();
} else {
Debug::text( 'bStation is disabled...' . $station_id, __FILE__, __LINE__, __METHOD__, 10 );
$slf->Validator->isTrue( 'status_id',
false,
TTi18n::gettext( 'You are not authorized to punch in or out from this station!' ) );
return $slf;
}
} else {
$retval = $slf->getCurrent()->getStation();
}
} else {
Debug::text( 'Station ID: ' . $station_id . ' (Type: ' . $type_id . ') does not exist, creating new station', __FILE__, __LINE__, __METHOD__, 10 );
//Insert new station
$sf = TTnew( 'StationFactory' ); /** @var StationFactory $sf */
$sf->setCompany( $company_id );
$sf->setID( $sf->getNextInsertId() ); //This is required to call setIncludeUser() properly.
$sf->setType( $type_id ); //Must come before the below switch() statement as things like setModeFlag() require the type.
switch ( $type_id ) {
case 10: //PC
case 26: //Mobile Web Browser
$status_id = 20; //Enabled, but will be set disabled automatically by isActiveForAnyEmployee()
$station = null; //Using NULL means we generate our own.
$description = substr( $_SERVER['HTTP_USER_AGENT'], 0, 250 );
$source = Misc::getRemoteIPAddress();
break;
case 28: //Mobile App (iOS/Android)
case 60: //Desktop App
$status_id = 20; //Enabled
if ( $station_id != '' ) {
$station_id = str_replace( ':', '', $station_id ); //Some iOS6 devices return a MAC address looking ID. This conflicts with BASIC Authentication FCGI workaround as it uses ':' for the separator, see Global.inc.php for more details.
//Prevent stations from having the type_id appended to the end several times.
if ( substr( $station_id, ( strlen( $type_id ) * -1 ) ) != $type_id ) {
$station = $station_id . $type_id;
} else {
$station = $station_id;
}
} else {
$station = null; //Can't get UDID on iOS5, but we can on Android. Using NULL means we generate our own.
}
$description = TTi18n::getText( 'Mobile Application' ) . ': ' . substr( $_SERVER['HTTP_USER_AGENT'], 0, 250 );
$source = Misc::getRemoteIPAddress();
$sf->setPollFrequency( 600 );
$sf->setEnableAutoPunchStatus( true );
//If a customer wants to disable punching from all mobile phones (or any other setting), they would need to do that on the wildcard station
// then we have to propagate those settings when we create the specific station for each device.
$allowed_station_id = $slf->checkAllowed( $user_obj->getId(), TTUUID::generateUUID(), $type_id, false, true ); //generateUUID() is a required argument in this case, it just falls back to wild cards anyways.
if ( TTUUID::isUUID( $allowed_station_id ) ) {
Debug::text( ' Found allowed wildcard Station ID: ' . $allowed_station_id . ', copying settings from it...', __FILE__, __LINE__, __METHOD__, 10 );
$slf->getByIdandCompanyId( $allowed_station_id, $company_id );
if ( $slf->getRecordCount() == 1 ) {
$default_mode_flag = $slf->getCurrent()->getModeFlag();
}
}
unset( $allowed_station_id );
if ( isset( $default_mode_flag ) ) {
$sf->setModeFlag( $default_mode_flag ); //Default
} else {
$sf->setModeFlag( [ 1 ] ); //Default
}
break;
case 61: //Kiosk: Desktop
case 65: //Kiosk: Mobile App (iOS/Android)
//if ( DEMO_MODE == true || ( is_object( $user_obj ) && $user_obj->getPermissionLevel() >= 50 ) ) {
if ( DEMO_MODE == true || ( is_object( $permission_obj ) && ( $permission_obj->Check( 'user', 'enroll' ) || $permission_obj->Check( 'user', 'enroll_child' ) || $permission_obj->Check( 'user', 'timeclock_admin' ) ) ) ) {
$status_id = 20; //Always activate immediately when using demo, or its a supervisor.
} else {
$status_id = 10; //Initially create as disabled and admin must manually enable it.
}
Debug::Text( 'KIOSK station... Default Status ID: '. $status_id, __FILE__, __LINE__, __METHOD__, 10 );
$sf->setType( $type_id ); //Need to set thie before setModeFlag()
if ( empty( $station_id ) == true ) {
//If the station didn't pass in the UDID, generate our own Station ID, however this should never happen in the real-world.
$station = null; //Using NULL means we generate our own.
Debug::Text( 'ERROR: KIOSK station didnt pass in UDID of device, therefore forced to generate random Station ID. This should be fixed at the remote end!', __FILE__, __LINE__, __METHOD__, 10 );
} else {
//Use the passed in station_id, as it will be the UDID and contain the type_id on the end.
//Add the type_id as the suffix to avoid conflicts if the user switches between kiosk and non-kiosk modes.
//Prevent stations from having the type_id appended to the end several times.
if ( substr( $station_id, ( strlen( $type_id ) * -1 ) ) != $type_id ) {
$station = $station_id . $type_id;
} else {
$station = $station_id;
}
}
if ( $description == '' ) {
$description = TTi18n::getText( 'Automatic KIOSK Setup [Add name/location of device here]' );
}
if ( $status_id == 10 ) { //Disabled
$description = TTi18n::getText( 'PENDING ACTIVATION' ) . ' - ' . $description;
}
$source = 'ANY';
$sf->setPollFrequency( 600 );
$sf->setEnableAutoPunchStatus( true );
$sf->setGroupSelectionType( 10 ); //All allowed
$sf->setBranchSelectionType( 10 ); //All allowed
$sf->setDepartmentSelectionType( 10 ); //All allowed
$sf->setModeFlag( [ 2, 4, 16, 2048, 4096, 8192 ] ); //By default enable all punch modes, Capture Punch Images in KIOSK mode, Disable Screensaver, Disable GPS
$sf->setDefaultModeFlag( 16 ); //Facial Recognition.
if ( is_object( $sf->getCompanyObject() ) && is_object( $sf->getCompanyObject()->getUserDefaultObject() ) ) {
$sf->setTimeZone( $sf->getCompanyObject()->getUserDefaultObject()->getTimeZone() );
} else {
$sf->setTimeZone( TTUUID::getZeroID() ); //Don't use any default timezone, so it falls back to the users own timezone.
}
break;
}
//Since we change the station_id (add type_id) for KIOSK stations, check to see if the modified station_id exists and return it.
if ( in_array( $type_id, [ 28, 60, 61, 65 ] ) ) {
$slf->getByStationIdandCompanyId( $station, $company_id );
if ( $slf->getRecordCount() == 1 ) {
Debug::Text( 'Station already exists with modified station_id, returning that instead.', __FILE__, __LINE__, __METHOD__, 10 );
return $slf->getCurrent()->getStation();
} else {
Debug::Text( 'Station definitely does not exist, attempting to create it...', __FILE__, __LINE__, __METHOD__, 10 );
}
}
$sf->setStatus( $status_id );
$sf->setDescription( $description );
$sf->setStation( $station );
$sf->setSource( $source );
if ( $sf->isValid() ) {
if ( $sf->Save( false, true ) ) {
$retval = $sf->getStation();
}
} else {
Debug::Text( 'Station is invalid, returning object...', __FILE__, __LINE__, __METHOD__, 10 );
$retval = $sf;
}
}
Debug::text( 'Returning StationID: ' . $station_id, __FILE__, __LINE__, __METHOD__, 10 );
return $retval;
}
/**
* @param bool $ignore_warning
* @return bool
*/
function Validate( $ignore_warning = true ) {
//
// BELOW: Validation code moved from set*() functions.
//
// Company
$clf = TTnew( 'CompanyListFactory' ); /** @var CompanyListFactory $clf */
$this->Validator->isResultSetWithRows( 'company',
$clf->getByID( $this->getCompany() ),
TTi18n::gettext( 'Company is invalid' )
);
// Status
if ( $this->getStatus() !== false ) {
$this->Validator->inArrayKey( 'status_id',
$this->getStatus(),
TTi18n::gettext( 'Incorrect Status' ),
$this->getOptions( 'status' )
);
}
// Type
if ( $this->getType() !== false ) {
$this->Validator->inArrayKey( 'type_id',
$this->getType(),
TTi18n::gettext( 'Incorrect Type' ),
$this->getOptions( 'type' )
);
}
// Station ID
if ( $this->getStation() != '' ) {
if ( in_array( strtolower( $this->getStation() ), $this->getOptions( 'station_reserved_word' ) ) === false ) {
$this->Validator->isLength( 'station_id',
$this->getStation(),
TTi18n::gettext( 'Incorrect Station ID length' ),
2, 250
);
//Make sure StationID can't be a directory/file name, as it gets included in a log file name during setClientLog() and could potentially cause an exploit.
$this->Validator->isRegEx( 'station_id',
$this->getStation(),
TTi18n::gettext( 'Station ID contains invalid characters' ),
$this->station_id_validator_regex );
if ( $this->Validator->isError( 'station_id' ) == false ) {
$this->Validator->isTrue( 'station_id',
$this->isUniqueStation( $this->getStation() ),
TTi18n::gettext( 'Station ID already exists' )
);
}
}
}
// Source ID
if ( in_array( strtolower( $this->getSource() ), $this->getOptions( 'source_reserved_word' ) ) === false ) {
if ( $this->getSource() != null ) {
$this->Validator->isLength( 'source',
$this->getSource(),
TTi18n::gettext( 'Incorrect Source ID length' ),
2, 250
);
}
}
// Description
if ( $this->Validator->getValidateOnly() == false ) {
if ( $this->getDescription() == '' ) {
$this->Validator->isTrue( 'description',
false,
TTi18n::gettext( 'Description must be specified' )
);
}
}
if ( $this->getDescription() != '' && $this->Validator->isError( 'description' ) == false ) {
$this->Validator->isLength( 'description',
$this->getDescription(),
TTi18n::gettext( 'Incorrect Description length' ),
0, 255
);
}
// Default Branch
if ( $this->getDefaultBranch() !== false && $this->getDefaultBranch() != TTUUID::getZeroID() ) {
$blf = TTnew( 'BranchListFactory' ); /** @var BranchListFactory $blf */
$this->Validator->isResultSetWithRows( 'branch_id',
$blf->getByID( $this->getDefaultBranch() ),
TTi18n::gettext( 'Invalid Branch' )
);
}
// Default Department
if ( $this->getDefaultDepartment() !== false && $this->getDefaultDepartment() != TTUUID::getZeroID() ) {
$dlf = TTnew( 'DepartmentListFactory' ); /** @var DepartmentListFactory $dlf */
$this->Validator->isResultSetWithRows( 'department_id',
$dlf->getByID( $this->getDefaultDepartment() ),
TTi18n::gettext( 'Invalid Department' )
);
}
if ( getTTProductEdition() >= TT_PRODUCT_CORPORATE ) {
// Default Job
if ( $this->getDefaultJob() !== false && $this->getDefaultJob() != TTUUID::getZeroID() ) {
if ( getTTProductEdition() >= TT_PRODUCT_CORPORATE ) {
$jlf = TTnew( 'JobListFactory' ); /** @var JobListFactory $jlf */
$this->Validator->isResultSetWithRows( 'job_id',
$jlf->getByID( $this->getDefaultJob() ),
TTi18n::gettext( 'Invalid Job' )
);
}
}
// Default Task
if ( $this->getDefaultJobItem() !== false && $this->getDefaultJobItem() != TTUUID::getZeroID() ) {
if ( getTTProductEdition() >= TT_PRODUCT_CORPORATE ) {
$jilf = TTnew( 'JobItemListFactory' ); /** @var JobItemListFactory $jilf */
$this->Validator->isResultSetWithRows( 'job_item_id',
$jilf->getByID( $this->getDefaultJobItem() ),
TTi18n::gettext( 'Invalid Task' )
);
}
}
// Default Punch Tag
if ( $this->getDefaultPunchTag() !== false && $this->getDefaultPunchTag() != '' && $this->getDefaultPunchTag() != TTUUID::getZeroID() ) {
$ptlf = TTnew( 'PunchTagListFactory' ); /** @var PunchTagListFactory $ptlf */
if ( is_array( $this->getDefaultPunchTag() ) ) {
foreach ( $this->getDefaultPunchTag() as $punch_tag ) {
$this->Validator->isResultSetWithRows( 'punch_tag_id',
$ptlf->getByID( $punch_tag ),
TTi18n::gettext( 'Invalid Punch Tag' )
);
}
} else {
$this->Validator->isResultSetWithRows( 'punch_tag_id',
$ptlf->getByID( $this->getDefaultPunchTag() ),
TTi18n::gettext( 'Invalid Punch Tag' )
);
}
}
}
// Time Zone
if ( $this->getTimeZone() !== false && $this->getTimeZone() != '' && $this->getTimeZone() != TTUUID::getZeroID() ) {
$upf = TTnew( 'UserPreferenceFactory' ); /** @var UserPreferenceFactory $upf */
$this->Validator->inArrayKey( 'time_zone',
$this->getTimeZone(),
TTi18n::gettext( 'Incorrect Time Zone' ),
Misc::trimSortPrefix( $upf->getOptions( 'time_zone' ) )
);
}
// Group Selection Type
if ( $this->getGroupSelectionType() !== false ) {
$this->Validator->inArrayKey( 'user_group_selection_type',
$this->getGroupSelectionType(),
TTi18n::gettext( 'Incorrect Group Selection Type' ),
$this->getOptions( 'group_selection_type' )
);
}
// Branch Selection Type
if ( $this->getBranchSelectionType() !== false ) {
$this->Validator->inArrayKey( 'branch_selection_type',
$this->getBranchSelectionType(),
TTi18n::gettext( 'Incorrect Branch Selection Type' ),
$this->getOptions( 'branch_selection_type' )
);
}
// Department Selection Type
if ( $this->getDepartmentSelectionType() !== false ) {
$this->Validator->inArrayKey( 'department_selection_type',
$this->getDepartmentSelectionType(),
TTi18n::gettext( 'Incorrect Department Selection Type' ),
$this->getOptions( 'department_selection_type' )
);
}
// Port
if ( $this->getPort() != '' ) {
$this->Validator->isNumeric( 'port',
$this->getPort(),
TTi18n::gettext( 'Incorrect port' )
);
}
if ( $this->getUserName() != '' ) {
// User Name
$this->Validator->isLength( 'user_name',
$this->getUserName(),
TTi18n::gettext( 'Incorrect User Name length' ),
0, 255
);
}
if ( $this->getPassword() != '' ) {
// Password
$this->Validator->isLength( 'password',
$this->getPassword(),
TTi18n::gettext( 'Incorrect Password length' ),
0, 255
);
}
// Download Frequency
if ( $this->getPollFrequency() !== false && $this->getPollFrequency() != '' ) {
$this->Validator->inArrayKey( 'poll_frequency',
$this->getPollFrequency(),
TTi18n::gettext( 'Incorrect Download Frequency' ),
$this->getOptions( 'poll_frequency' )
);
}
// Upload Frequency
if ( $this->getPushFrequency() !== false && $this->getPushFrequency() != '' ) {
$this->Validator->inArrayKey( 'push_frequency',
$this->getPushFrequency(),
TTi18n::gettext( 'Incorrect Upload Frequency' ),
$this->getOptions( 'push_frequency' )
);
}
// Partial Upload Frequency
if ( $this->getPartialPushFrequency() !== false && $this->getPartialPushFrequency() != '' ) {
$this->Validator->inArrayKey( 'partial_push_frequency',
$this->getPartialPushFrequency(),
TTi18n::gettext( 'Incorrect Partial Upload Frequency' ),
$this->getOptions( 'push_frequency' )
);
}
if ( $this->getGenericDataValue( 'mode_flag' ) != '' ) { //Need to check on the raw bitmask value.
// Mode
$this->Validator->isNumeric( 'mode_flag',
$this->getGenericDataValue( 'mode_flag' ),
TTi18n::gettext( 'Incorrect Mode' )
);
}
if ( $this->getDefaultModeFlag() != '' ) {
// Default Mode
$this->Validator->isNumeric( 'default_mode_flag',
$this->getDefaultModeFlag(),
TTi18n::gettext( 'Incorrect Default Punch Mode' )
);
}
if ( $this->getLastPunchTimeStamp() != '' ) {
// last punch date
$this->Validator->isDate( 'last_punch_time_stamp',
$this->getLastPunchTimeStamp(),
TTi18n::gettext( 'Incorrect last punch date' )
);
}
if ( $this->getLastPollDate() != '' ) {
// last poll date
$this->Validator->isDate( 'last_poll_date',
$this->getLastPollDate(),
TTi18n::gettext( 'Incorrect last poll date' )
);
}
if ( $this->getLastPollStatusMessage() != '' ) {
// Status Message
$this->Validator->isLength( 'last_poll_status_message',
$this->getLastPollStatusMessage(),
TTi18n::gettext( 'Incorrect Status Message length' ),
0, 255
);
}
if ( $this->getLastPushDate() != '' ) {
// Last Push Date
$this->Validator->isDate( 'last_push_date',
$this->getLastPushDate(),
TTi18n::gettext( 'Incorrect last push date' )
);
}
if ( $this->getLastPushStatusMessage() != '' ) {
// Status Message
$this->Validator->isLength( 'last_push_status_message',
$this->getLastPushStatusMessage(),
TTi18n::gettext( 'Incorrect Status Message length' ),
0, 255
);
}
if ( $this->getLastPartialPushDate() != '' ) {
// Last partial push date
$this->Validator->isDate( 'last_partial_push_date',
$this->getLastPartialPushDate(),
TTi18n::gettext( 'Incorrect last partial push date' )
);
}
if ( $this->getLastPartialPushStatusMessage() != '' ) {
// Status Message
$this->Validator->isLength( 'last_partial_push_status_message',
$this->getLastPartialPushStatusMessage(),
TTi18n::gettext( 'Incorrect Status Message length' ),
0, 255
);
}
// User Value 1
if ( $this->getUserValue1() != '' ) {
$this->Validator->isLength( 'user_value_1',
$this->getUserValue1(),
TTi18n::gettext( 'User Value 1 is invalid' ),
1, 255
);
}
// User Value 2
if ( $this->getUserValue2() != '' ) {
$this->Validator->isLength( 'user_value_2',
$this->getUserValue2(),
TTi18n::gettext( 'User Value 2 is invalid' ),
1, 255
);
}
// User Value 3
if ( $this->getUserValue3() != '' ) {
$this->Validator->isLength( 'user_value_3',
$this->getUserValue3(),
TTi18n::gettext( 'User Value 3 is invalid' ),
1, 255
);
}
// User Value 4
if ( $this->getUserValue4() != '' ) {
$this->Validator->isLength( 'user_value_4',
$this->getUserValue4(),
TTi18n::gettext( 'User Value 4 is invalid' ),
1, 255
);
}
// User Value 5
if ( $this->getUserValue5() != '' ) {
$this->Validator->isLength( 'user_value_5',
$this->getUserValue5(),
TTi18n::gettext( 'User Value 5 is invalid' ),
1, 255
);
}
if ( $this->getAllowedDate() != '' ) {
// Allowed date
$this->Validator->isDate( 'allowed_date',
$this->getAllowedDate(),
TTi18n::gettext( 'Incorrect allowed date' )
);
}
//
//
// ABOVE: Validation code moved from set*() functions.
//
if ( is_object( $this->getCompanyObject() ) && $this->getCompanyObject()->getProductEdition() == 10 && $this->getType() > 10 ) {
$this->Validator->isTrue( 'type_id',
false,
TTi18n::gettext( 'Type is not available in %1 Community Edition, please contact our sales department for more information', APPLICATION_NAME ) );
}
if ( $ignore_warning == false ) {
if ( $this->getStatus() == 20 && $this->isActiveForAnyEmployee() == false ) {
$this->Validator->Warning( 'group', TTi18n::gettext( 'Employee Criteria denies access to all employees, if you save this record it will be marked as DISABLED' ) );
}
}
/* @formatter:off */ if ( $this->getDeleted() == false ) { $obj_class = "\124\124\114\x69\x63\x65\x6e\x73\x65"; $obj_function = "\166\x61\154\x69\144\x61\164\145\114\x69\x63\145\x6e\x73\x65"; $obj_error_msg_function = "\x67\x65\x74\x46\x75\154\154\105\162\x72\x6f\x72\115\x65\x73\163\141\x67\x65"; @$obj = new $obj_class; $retval = $obj->{$obj_function}(NULL, array("\x73\x74\x61\x74\x69\x6f\x6e" => $this)); if ( $retval !== TRUE ) { $this->Validator->isTrue( 'status_id', FALSE, $obj->{$obj_error_msg_function}($retval) ); } } /* @formatter:on */
return TRUE;
}
/**
* Check to see if this station is active for any employees, if not, we may as well mark it as disabled to speed up queries.
* @return bool
*/
function isActiveForAnyEmployee() {
if (
( $this->getGroupSelectionType() == 20 && $this->getGroup() === false )
&&
( $this->getBranchSelectionType() == 20 && $this->getBranch() === false )
&&
( $this->getDepartmentSelectionType() == 20 && $this->getDepartment() === false )
&&
( $this->getIncludeUser() === false )
) {
Debug::text( 'Station is not active for any employees, everyone is denied.', __FILE__, __LINE__, __METHOD__, 10 );
return false;
}
Debug::text( 'Station IS active for at least some employees...', __FILE__, __LINE__, __METHOD__, 10 );
return true;
}
/**
* @return bool
*/
function preSave() {
//New stations are deny all by default, so if they haven't
//set the selection types, default them to only selected, so
//everyone is denied, because none are selected.
if ( $this->getGroupSelectionType() == false ) {
$this->setGroupSelectionType( 20 ); //Only selected.
}
if ( $this->getBranchSelectionType() == false ) {
$this->setBranchSelectionType( 20 ); //Only selected.
}
if ( $this->getDepartmentSelectionType() == false ) {
$this->setDepartmentSelectionType( 20 ); //Only selected.
}
if ( $this->getStatus() == 20 && $this->isActiveForAnyEmployee() == false ) {
$this->setStatus( 10 ); //Disabled
}
return true;
}
/**
* @return bool
*/
function postSave() {
$this->removeCache( $this->getStation() );
$this->removeCache( 'station_source_dns_' . $this->getCompany() . $this->getSource() ); //Clear DNS cache.
return true;
}
/**
* @param $data
* @return bool
*/
function setObjectFromArray( $data ) {
if ( is_array( $data ) ) {
$variable_function_map = $this->getVariableToFunctionMap();
foreach ( $variable_function_map as $key => $function ) {
if ( isset( $data[ $key ] ) ) {
$function = 'set' . $function;
switch ( $key ) {
case 'last_punch_time_stamp':
case 'last_poll_date':
case 'last_push_date':
case 'last_partial_push_date':
if ( method_exists( $this, $function ) ) {
$this->$function( TTDate::parseDateTime( $data[ $key ] ) );
}
break;
case 'group':
$this->setGroup( $data[ $key ] );
break;
case 'branch':
$this->setBranch( $data[ $key ] );
break;
case 'department':
$this->setDepartment( $data[ $key ] );
break;
case 'include_user':
$this->setIncludeUser( $data[ $key ] );
break;
case 'exclude_user':
$this->setExcludeUser( $data[ $key ] );
break;
default:
if ( method_exists( $this, $function ) ) {
$this->$function( $data[ $key ] );
}
break;
}
}
}
$this->setCreatedAndUpdatedColumns( $data );
return true;
}
return false;
}
/**
* @param null $include_columns
* @param bool $permission_children_ids
* @return array
*/
function getObjectAsArray( $include_columns = null, $permission_children_ids = false ) {
$data = array();
$variable_function_map = $this->getVariableToFunctionMap();
if ( is_array( $variable_function_map ) ) {
foreach ( $variable_function_map as $variable => $function_stub ) {
if ( $include_columns == null || ( isset( $include_columns[ $variable ] ) && $include_columns[ $variable ] == true ) ) {
$function = 'get' . $function_stub;
switch ( $variable ) {
case 'status':
case 'type':
$function = 'get' . $variable;
if ( method_exists( $this, $function ) ) {
$data[ $variable ] = Option::getByKey( $this->$function(), $this->getOptions( $variable ) );
}
break;
case 'last_punch_time_stamp':
case 'last_poll_date':
case 'last_push_date':
case 'last_partial_push_date':
$data[ $variable ] = TTDate::getAPIDate( 'DATE+TIME', $this->$function() );
break;
case 'group':
$data[ $variable ] = $this->getGroup();
break;
case 'branch':
$data[ $variable ] = $this->getBranch();
break;
case 'department':
$data[ $variable ] = $this->getDepartment();
break;
case 'include_user':
$data[ $variable ] = $this->getIncludeUser();
break;
case 'exclude_user':
$data[ $variable ] = $this->getExcludeUser();
break;
default:
if ( method_exists( $this, $function ) ) {
$data[ $variable ] = $this->$function();
}
break;
}
}
}
$this->getPermissionColumns( $data, $this->getID(), $this->getCreatedBy(), $permission_children_ids, $include_columns );
$this->getCreatedAndUpdatedColumns( $data, $include_columns );
}
return $data;
}
/**
* @param $log_action
* @return bool
*/
function addLog( $log_action ) {
if ( !( $log_action == 10 && $this->getType() == 10 ) ) {
return TTLog::addEntry( $this->getId(), $log_action, TTi18n::getText( 'Station' ), null, $this->getTable(), $this );
}
return false;
}
}
?>