1091 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			1091 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?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".
 | 
						|
 *
 | 
						|
 ********************************************************************************/
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * @package Core
 | 
						|
 */
 | 
						|
class AuthorizationFactory extends Factory {
 | 
						|
	protected $table = 'authorizations';
 | 
						|
	protected $pk_sequence_name = 'authorizations_id_seq'; //PK Sequence name
 | 
						|
 | 
						|
	protected $obj_handler = null;
 | 
						|
	protected $obj_handler_obj = null;
 | 
						|
	protected $hierarchy_arr = null;
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @param $name
 | 
						|
	 * @param null $parent
 | 
						|
	 * @return array|null
 | 
						|
	 */
 | 
						|
	function _getFactoryOptions( $name, $parent = null ) {
 | 
						|
 | 
						|
		$retval = null;
 | 
						|
		switch ( $name ) {
 | 
						|
			case 'object_type':
 | 
						|
				$retval = [
 | 
						|
					//10 => 'default_schedule',
 | 
						|
					//20 => 'schedule_amendment',
 | 
						|
					//30 => 'shift_amendment',
 | 
						|
					//40 => 'pay_stub_amendment',
 | 
						|
 | 
						|
					//52 => 'request_vacation',
 | 
						|
					//54 => 'request_missed_punch',
 | 
						|
					//56 => 'request_edit_punch',
 | 
						|
					//58 => 'request_absence',
 | 
						|
					//59 => 'request_schedule',
 | 
						|
					90 => 'timesheet',
 | 
						|
 | 
						|
					200  => 'expense',
 | 
						|
 | 
						|
					//50 => 'request', //request_other
 | 
						|
					1010 => 'request_punch',
 | 
						|
					1020 => 'request_punch_adjust',
 | 
						|
					1030 => 'request_absence',
 | 
						|
					1040 => 'request_schedule',
 | 
						|
					1100 => 'request_other',
 | 
						|
				];
 | 
						|
				break;
 | 
						|
			case 'columns':
 | 
						|
				$retval = [
 | 
						|
 | 
						|
						'-1010-created_by'   => TTi18n::gettext( 'Name' ),
 | 
						|
						'-1020-created_date' => TTi18n::gettext( 'Date' ),
 | 
						|
						'-1030-authorized'   => TTi18n::gettext( 'Authorized' ),
 | 
						|
						//'-1100-object_type' => TTi18n::gettext('Object Type'),
 | 
						|
 | 
						|
						//'-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 = [
 | 
						|
						'created_by',
 | 
						|
						'created_date',
 | 
						|
						'authorized',
 | 
						|
				];
 | 
						|
				break;
 | 
						|
		}
 | 
						|
 | 
						|
		return $retval;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @param $data
 | 
						|
	 * @return array
 | 
						|
	 */
 | 
						|
	function _getVariableToFunctionMap( $data ) {
 | 
						|
		$variable_function_map = [
 | 
						|
				'id'             => 'ID',
 | 
						|
				'object_type_id' => 'ObjectType',
 | 
						|
				'object_type'    => false,
 | 
						|
				'object_id'      => 'Object',
 | 
						|
				'authorized'     => 'Authorized',
 | 
						|
				'deleted'        => 'Deleted',
 | 
						|
		];
 | 
						|
 | 
						|
		return $variable_function_map;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @return bool
 | 
						|
	 */
 | 
						|
	function getCurrentUserObject() {
 | 
						|
		return $this->getGenericObject( 'UserListFactory', $this->getCurrentUser(), 'user_obj' );
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Stores the current user in memory, so we can determine if its the employee verifying, or a superior.
 | 
						|
	 * @return mixed
 | 
						|
	 */
 | 
						|
	function getCurrentUser() {
 | 
						|
		return $this->getGenericTempDataValue( 'current_user_id' );
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @param string $value UUID
 | 
						|
	 * @return bool
 | 
						|
	 */
 | 
						|
	function setCurrentUser( $value ) {
 | 
						|
		$value = trim( $value );
 | 
						|
 | 
						|
		return $this->setGenericTempDataValue( 'current_user_id', $value );
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @return array|bool|null
 | 
						|
	 */
 | 
						|
	function getHierarchyArray() {
 | 
						|
		if ( is_array( $this->hierarchy_arr ) ) {
 | 
						|
			return $this->hierarchy_arr;
 | 
						|
		} else {
 | 
						|
			$user_id = $this->getCurrentUser();
 | 
						|
 | 
						|
			if ( is_object( $this->getObjectHandler() ) ) {
 | 
						|
				$this->getObjectHandler()->getByID( $this->getObject() );
 | 
						|
				$current_obj = $this->getObjectHandler()->getCurrent();
 | 
						|
				$object_user_id = $current_obj->getUser();
 | 
						|
 | 
						|
				if ( TTUUID::isUUID( $object_user_id ) && $object_user_id != TTUUID::getZeroID() && $object_user_id != TTUUID::getNotExistID() ) {
 | 
						|
					$ulf = TTnew( 'UserListFactory' ); /** @var UserListFactory $ulf */
 | 
						|
					$company_id = $ulf->getById( $object_user_id )->getCurrent()->getCompany();
 | 
						|
					Debug::Text( ' Authorizing User ID: ' . $user_id .' Object User ID: ' . $object_user_id . ' Company ID: ' . $company_id, __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
 | 
						|
					$hlf = TTnew( 'HierarchyListFactory' ); /** @var HierarchyListFactory $hlf */
 | 
						|
					$this->hierarchy_arr = $hlf->getHierarchyParentByCompanyIdAndUserIdAndObjectTypeID( $company_id, $object_user_id, $this->getObjectType(), false );
 | 
						|
					Debug::Arr( $this->hierarchy_arr, ' Hierarchy Arr: ', __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
 | 
						|
					return $this->hierarchy_arr;
 | 
						|
				} else {
 | 
						|
					Debug::Text( ' Could not find Object User ID: ' . $user_id, __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
				}
 | 
						|
			} else {
 | 
						|
				Debug::Text( ' ERROR: No ObjectHandler defined...', __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @return array|bool
 | 
						|
	 */
 | 
						|
	function getHierarchyChildLevelArray() {
 | 
						|
		$retval = [];
 | 
						|
 | 
						|
		$user_id = $this->getCurrentUser();
 | 
						|
		$parent_arr = $this->getHierarchyArray();
 | 
						|
		if ( is_array( $parent_arr ) && count( $parent_arr ) > 0 ) {
 | 
						|
			$next_level = false;
 | 
						|
			foreach ( $parent_arr as $level_parent_arr ) {
 | 
						|
				if ( in_array( $user_id, $level_parent_arr ) ) {
 | 
						|
					$next_level = true;
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
 | 
						|
				if ( $next_level == true ) {
 | 
						|
					//Debug::Arr( $level_parent_arr, ' Child: Level: '. $level, __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
					$retval = array_merge( $retval, $level_parent_arr ); //Append from all levels.
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if ( count( $retval ) > 0 ) {
 | 
						|
			return $retval;
 | 
						|
		}
 | 
						|
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @param bool $force
 | 
						|
	 * @return bool|mixed
 | 
						|
	 */
 | 
						|
	function getHierarchyCurrentLevelArray( $force = false ) {
 | 
						|
		$retval = false;
 | 
						|
 | 
						|
		$user_id = $this->getCurrentUser();
 | 
						|
		$parent_arr = $this->getHierarchyArray();
 | 
						|
		if ( is_array( $parent_arr ) && count( $parent_arr ) > 0 ) {
 | 
						|
			$next_level = false;
 | 
						|
			foreach ( $parent_arr as $level_parent_arr ) {
 | 
						|
				if ( in_array( $user_id, $level_parent_arr ) ) {
 | 
						|
					$next_level = true;
 | 
						|
					if ( $force == false ) {
 | 
						|
						continue;
 | 
						|
					}
 | 
						|
				}
 | 
						|
 | 
						|
				if ( $next_level == true ) { //Current level is alway one level lower, as this often gets called after the level has been changed.
 | 
						|
					$retval = $level_parent_arr;
 | 
						|
					//Debug::Arr( $level_parent_arr, ' Current: Level: ' . $level, __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
					break;
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			if ( $next_level == true && $retval == false ) {
 | 
						|
				//Current level was the top and only level.
 | 
						|
				$retval = $level_parent_arr;
 | 
						|
				//Debug::Arr( $level_parent_arr, ' Current: Level: ' . $level, __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		return $retval;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @return array|bool|mixed
 | 
						|
	 */
 | 
						|
	function getHierarchyParentLevelArray() {
 | 
						|
		$retval = false;
 | 
						|
 | 
						|
		$user_id = TTUUID::castUUID( $this->getCurrentUser() );
 | 
						|
		$parent_arr = array_reverse( (array)$this->getHierarchyArray() );
 | 
						|
		if ( is_array( $parent_arr ) && count( $parent_arr ) > 0 ) {
 | 
						|
			$next_level = false;
 | 
						|
			foreach ( $parent_arr as $level_parent_arr ) {
 | 
						|
				if ( is_array( $level_parent_arr ) && in_array( $user_id, $level_parent_arr ) ) {
 | 
						|
					$next_level = true;
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
 | 
						|
				//Since this loops in reverse, always assume the first element is the parent for cases where a subordinate may be submitting the object (ie: request) and it needs to go to the direct superiors.
 | 
						|
				if ( $next_level == true ) {
 | 
						|
					//Debug::Arr( $level_parent_arr, ' Parents: Level: '. $level, __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
					$retval = $level_parent_arr;
 | 
						|
					break;
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			//If we get here without finding a parent, use the lowest lower parents by default.
 | 
						|
			if ( $next_level == false ) {
 | 
						|
				reset( $parent_arr );
 | 
						|
				$retval = $parent_arr[key( $parent_arr )];
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		return $retval;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * This will return false if it can't find a hierarchy, or if its at the top level (1) and can't find a higher level.
 | 
						|
	 * @return bool|int|string
 | 
						|
	 */
 | 
						|
	function getNextHierarchyLevel() {
 | 
						|
		$retval = false;
 | 
						|
 | 
						|
		$user_id = $this->getCurrentUser();
 | 
						|
		$parent_arr = $this->getHierarchyArray();
 | 
						|
		if ( is_array( $parent_arr ) && count( $parent_arr ) > 0 ) {
 | 
						|
			foreach ( $parent_arr as $level => $level_parent_arr ) {
 | 
						|
				if ( in_array( $user_id, $level_parent_arr ) ) {
 | 
						|
					break;
 | 
						|
				}
 | 
						|
				$retval = $level;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if ( $retval < 1 ) {
 | 
						|
			Debug::Text( ' ERROR, hierarchy level goes past 1... This shouldnt happen...', __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
			$retval = false;
 | 
						|
		}
 | 
						|
 | 
						|
		return $retval;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @param string $company_id UUID
 | 
						|
	 * @param string $user_id    UUID
 | 
						|
	 * @param int $hierarchy_type_id
 | 
						|
	 * @return int|mixed
 | 
						|
	 */
 | 
						|
	static function getInitialHierarchyLevel( $company_id, $user_id, $hierarchy_type_id ) {
 | 
						|
		$hierarchy_highest_level = 99;
 | 
						|
		if ( $company_id != '' && $user_id != '' && $hierarchy_type_id > 0 ) {
 | 
						|
			$hlf = TTnew( 'HierarchyListFactory' ); /** @var HierarchyListFactory $hlf */
 | 
						|
			$hierarchy_arr = $hlf->getHierarchyParentByCompanyIdAndUserIdAndObjectTypeID( $company_id, $user_id, $hierarchy_type_id, false );
 | 
						|
			if ( isset( $hierarchy_arr ) && is_array( $hierarchy_arr ) ) {
 | 
						|
				//Debug::Arr( $hierarchy_arr, ' aUser ID ' . $user_id . ' Type ID: ' . $hierarchy_type_id . ' Array: ', __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
 | 
						|
				//See if current user is in superior list, if so, start at one level up in the hierarchy, unless its level 1.
 | 
						|
				foreach ( $hierarchy_arr as $level => $superior_user_ids ) {
 | 
						|
					if ( in_array( $user_id, $superior_user_ids, true ) == true ) {
 | 
						|
						Debug::Text( '   Found user in superior list at level: ' . $level, __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
 | 
						|
						$i = $level;
 | 
						|
						while ( isset( $hierarchy_arr[$i] ) ) {
 | 
						|
							if ( $i != 1 ) {
 | 
						|
								Debug::Text( '    Removing lower level: ' . $i, __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
								unset( $hierarchy_arr[$i] );
 | 
						|
							}
 | 
						|
							$i++;
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
 | 
						|
				//Debug::Arr( $hierarchy_arr, ' bUser ID ' . $user_id . ' Type ID: ' . $hierarchy_type_id . ' Array: ', __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
				$hierarchy_arr = array_keys( $hierarchy_arr );
 | 
						|
				$hierarchy_highest_level = end( $hierarchy_arr );
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		Debug::Text( ' Returning initial hierarchy level to: ' . $hierarchy_highest_level, __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
 | 
						|
		return $hierarchy_highest_level;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @return bool
 | 
						|
	 */
 | 
						|
	function isValidParent() {
 | 
						|
		$user_id = $this->getCurrentUser();
 | 
						|
		$parent_arr = $this->getHierarchyArray();
 | 
						|
		if ( is_array( $parent_arr ) && count( $parent_arr ) > 0 ) {
 | 
						|
			krsort( $parent_arr );
 | 
						|
			foreach ( $parent_arr as $level_parent_arr ) {
 | 
						|
				if ( in_array( $user_id, $level_parent_arr ) ) {
 | 
						|
					return true;
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		Debug::Text( ' Authorizing User is not a parent of the object owner: ', __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @return bool
 | 
						|
	 */
 | 
						|
	function isFinalAuthorization() {
 | 
						|
		$user_id = $this->getCurrentUser();
 | 
						|
		$parent_arr = $this->getHierarchyArray();
 | 
						|
		if ( is_array( $parent_arr ) && count( $parent_arr ) > 0 ) {
 | 
						|
			//Check that level 1 parent exists
 | 
						|
			if ( isset( $parent_arr[1] ) && in_array( $user_id, $parent_arr[1] ) ) {
 | 
						|
				Debug::Text( ' Final Authorization!', __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
 | 
						|
				return true;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		Debug::Text( ' NOT Final Authorization!', __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Checks to see if the currently logged in user is the only superior in the hierarchy at the current level.
 | 
						|
	 *   This would normally be paired with a isFinalAuthorization() check as well.
 | 
						|
	 * @return bool
 | 
						|
	 */
 | 
						|
	function isCurrentUserOnlySuperior() {
 | 
						|
		$hierarchy_current_level_user_ids = $this->getHierarchyCurrentLevelArray();
 | 
						|
		if ( count( $hierarchy_current_level_user_ids ) == 1 && in_array( $this->getCurrentUser(), $hierarchy_current_level_user_ids ) ) {
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @return null|object
 | 
						|
	 */
 | 
						|
	function getObjectHandler() {
 | 
						|
		if ( is_object( $this->obj_handler ) ) {
 | 
						|
			return $this->obj_handler;
 | 
						|
		} else {
 | 
						|
			switch ( $this->getObjectType() ) {
 | 
						|
				case 90: //TimeSheet
 | 
						|
					$this->obj_handler = TTnew( 'PayPeriodTimeSheetVerifyListFactory' );
 | 
						|
					break;
 | 
						|
				case 200:
 | 
						|
					$this->obj_handler = TTnew( 'UserExpenseListFactory' );
 | 
						|
					break;
 | 
						|
				case 50: //Requests
 | 
						|
				case 1010:
 | 
						|
				case 1020:
 | 
						|
				case 1030:
 | 
						|
				case 1040:
 | 
						|
				case 1100:
 | 
						|
					$this->obj_handler = TTnew( 'RequestListFactory' );
 | 
						|
					break;
 | 
						|
			}
 | 
						|
 | 
						|
			return $this->obj_handler;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @return bool|int
 | 
						|
	 */
 | 
						|
	function getObjectType() {
 | 
						|
		return $this->getGenericDataValue( 'object_type_id' );
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @param $value
 | 
						|
	 * @return bool
 | 
						|
	 */
 | 
						|
	function setObjectType( $value ) {
 | 
						|
		$value = (int)trim( $value );
 | 
						|
 | 
						|
		return $this->setGenericDataValue( 'object_type_id', $value );
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @return bool|mixed
 | 
						|
	 */
 | 
						|
	function getObject() {
 | 
						|
		return $this->getGenericDataValue( 'object_id' );
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @param string $value UUID
 | 
						|
	 * @return bool
 | 
						|
	 */
 | 
						|
	function setObject( $value ) {
 | 
						|
		$value = TTUUID::castUUID( $value );
 | 
						|
 | 
						|
		return $this->setGenericDataValue( 'object_id', $value );
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @return bool
 | 
						|
	 */
 | 
						|
	function getAuthorized() {
 | 
						|
		return $this->fromBool( $this->getGenericDataValue( 'authorized' ) );
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @param $value
 | 
						|
	 * @return bool
 | 
						|
	 */
 | 
						|
	function setAuthorized( $value ) {
 | 
						|
		return $this->setGenericDataValue( 'authorized', $this->toBool( $value ) );
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @return bool
 | 
						|
	 */
 | 
						|
	function clearHistory() {
 | 
						|
		Debug::text( 'Clearing Authorization History For Type: ' . $this->getObjectType() . ' ID: ' . $this->getObject(), __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
 | 
						|
		if ( $this->getObjectType() === false || $this->getObject() === false ) {
 | 
						|
			Debug::text( 'Clearing Authorization History FAILED!', __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
 | 
						|
		$alf = TTnew( 'AuthorizationListFactory' ); /** @var AuthorizationListFactory $alf */
 | 
						|
		$alf->getByObjectTypeAndObjectId( $this->getObjectType(), $this->getObject() );
 | 
						|
		foreach ( $alf as $authorization_obj ) {
 | 
						|
			$authorization_obj->setDeleted( true );
 | 
						|
			$authorization_obj->Save();
 | 
						|
		}
 | 
						|
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @return object
 | 
						|
	 */
 | 
						|
	function getObjectHandlerObject() {
 | 
						|
		if ( is_object( $this->obj_handler_obj ) ) {
 | 
						|
			return $this->obj_handler_obj;
 | 
						|
		} else {
 | 
						|
			//Get user_id of object.
 | 
						|
			$this->getObjectHandler()->getByID( $this->getObject() );
 | 
						|
			$this->obj_handler_obj = $this->getObjectHandler()->getCurrent();
 | 
						|
//			if ( method_exists( $this->obj_handler_obj, 'setCurrentUser' ) AND $this->obj_handler_obj->getCurrentUser() != $this->getCurrentUser() ) { //Required for authorizing TimeSheets from MyAccount -> TimeSheet Authorization.
 | 
						|
//				$this->obj_handler_obj->setCurrentUser( $this->getCurrentUser() );
 | 
						|
//			}
 | 
						|
 | 
						|
			return $this->obj_handler_obj;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @return boolean
 | 
						|
	 */
 | 
						|
	function setObjectHandlerStatus() {
 | 
						|
		$is_final_authorization = $this->isFinalAuthorization();
 | 
						|
 | 
						|
		$this->obj_handler_obj = $this->getObjectHandlerObject();
 | 
						|
		if ( $this->getAuthorized() === true ) {
 | 
						|
			if ( $is_final_authorization === true ) {
 | 
						|
				//If no other superiors exist in the hierarchy and we are at the top level, assume its authorized.
 | 
						|
				if ( $this->getCurrentUser() != $this->obj_handler_obj->getUser() || $this->isCurrentUserOnlySuperior() == true ) {
 | 
						|
					Debug::Text( '  Approving Authorization... Final Authorizing Object: ' . $this->getObject() . ' - Type: ' . $this->getObjectType(), __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
					$this->obj_handler_obj->setAuthorizationLevel( 1 );
 | 
						|
					$this->obj_handler_obj->setStatus( 50 ); //Active/Authorized
 | 
						|
					$this->obj_handler_obj->setAuthorized( true );
 | 
						|
				} else {
 | 
						|
					Debug::Text( '  Currently logged in user is authorizing (or submitting as new) their own request, when other superiors exist in the hierarchy, not authorizing...', __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
				}
 | 
						|
			} else {
 | 
						|
				Debug::text( '  Approving Authorization, moving to next level up...', __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
				$current_level = $this->obj_handler_obj->getAuthorizationLevel();
 | 
						|
				if ( $current_level > 1 ) { //Highest level is 1, so no point in making it less than that.
 | 
						|
 | 
						|
					//Get the next level above the current user doing the authorization, in case they have dropped down a level or two.
 | 
						|
					$next_level = $this->getNextHierarchyLevel();
 | 
						|
					if ( $next_level !== false && $next_level < $current_level ) {
 | 
						|
						Debug::text( '  Current Level: ' . $current_level . ' Moving Up To Level: ' . $next_level, __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
						$this->obj_handler_obj->setAuthorizationLevel( $next_level );
 | 
						|
					}
 | 
						|
				}
 | 
						|
				unset( $current_level, $next_level );
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			Debug::text( '  Declining Authorization...', __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
			$this->obj_handler_obj->setStatus( 55 ); //'AUTHORIZATION DECLINED'
 | 
						|
			$this->obj_handler_obj->setAuthorized( false );
 | 
						|
		}
 | 
						|
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @return array|bool
 | 
						|
	 */
 | 
						|
	function getUserAuthorizationIds() {
 | 
						|
		$object_handler_user_id = $this->getObjectHandlerObject()->getUser(); //Object handler (request) user_id.
 | 
						|
 | 
						|
		$is_final_authorization = $this->isFinalAuthorization();
 | 
						|
		$authorization_level = $this->getObjectHandlerObject()->getAuthorizationLevel(); //This is the *new* level, not the old level.
 | 
						|
 | 
						|
		$hierarchy_current_level_arr = $this->getHierarchyCurrentLevelArray();
 | 
						|
		Debug::Arr( $hierarchy_current_level_arr, '  Authorization Level: ' . $authorization_level . ' Authorized: ' . (int)$this->getAuthorized() . ' Is Final Auth: ' . (int)$is_final_authorization . ' Object Handler User ID: ' . $object_handler_user_id, __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
 | 
						|
		if ( $this->getAuthorized() == true && $authorization_level == 0 ) {
 | 
						|
			//Final authorization has taken place
 | 
						|
			//Notify original submittor and all lower level superiors?
 | 
						|
			$user_ids = $this->getHierarchyChildLevelArray();
 | 
						|
 | 
						|
			if ( is_a( $this->getObjectHandlerObject(), 'PayPeriodTimeSheetVerify' ) ) { //is_a() will match on plugin class names too because it also checks the parent class name.
 | 
						|
				//Check to see what type of timesheet verification is required, if its superior only, don't notify the employee to avoid confusion.
 | 
						|
				if ( $this->getObjectHandlerObject()->getVerificationType() != 30 ) {
 | 
						|
					$user_ids[] = $object_handler_user_id;
 | 
						|
				} else {
 | 
						|
					Debug::text( '  TimeSheetVerification for superior only, dont motify employee...', __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
				}
 | 
						|
			} else {
 | 
						|
				$user_ids[] = $object_handler_user_id;
 | 
						|
			}
 | 
						|
			//Debug::Arr($user_ids , '  aAuthorization Level: '. $authorization_level .' Authorized: '. (int)$this->getAuthorized() .' Child: ' , __FILE__, __LINE__, __METHOD__, 10);
 | 
						|
		} else {
 | 
						|
			//Debug::Text('  bAuthorization Level: '. $authorization_level .' Authorized: '. (int)$this->getAuthorized(), __FILE__, __LINE__, __METHOD__, 10);
 | 
						|
			//Final authorization has *not* yet taken place
 | 
						|
			if ( $this->getObjectHandlerObject()->getStatus() == 55 ) { //Declined
 | 
						|
				//Authorization declined. Notify original submittor and all lower level superiors?
 | 
						|
				$user_ids = $this->getHierarchyChildLevelArray();
 | 
						|
				$user_ids[] = $object_handler_user_id;
 | 
						|
				//Debug::Arr($user_ids , '  b1Authorization Level: '. $authorization_level .' Authorized: '. (int)$this->getAuthorized() .' Child: ', __FILE__, __LINE__, __METHOD__, 10);
 | 
						|
			} else if ( $is_final_authorization == true && $this->getCurrentUser() == $object_handler_user_id && $this->getAuthorized() == true && $authorization_level == 1 ) {
 | 
						|
				//Subordinate who is also a superior at the top and only level of the hierarchy is submitting a request.
 | 
						|
				$user_ids = $this->getHierarchyCurrentLevelArray( true ); //Force to real current level.
 | 
						|
				//Debug::Arr($user_ids , '  b2Authorization Level: '. $authorization_level .' Authorized: '. (int)$this->getAuthorized() .' Child: ', __FILE__, __LINE__, __METHOD__, 10);
 | 
						|
			} else {
 | 
						|
				//Authorized at a middle level, notify current level superiors only so they know its waiting on them.
 | 
						|
				$user_ids = $this->getHierarchyParentLevelArray();
 | 
						|
				//Debug::Arr($user_ids , '  b3Authorization Level: '. $authorization_level .' Authorized: '. (int)$this->getAuthorized() .' Parent: ', __FILE__, __LINE__, __METHOD__, 10);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if( isset( $user_ids ) && !empty( $user_ids ) ) {
 | 
						|
			//Remove the current authorizing user from the array, as they don't need to be notified as they are performing the action.
 | 
						|
			$user_ids = array_diff( (array)$user_ids, [ $this->getCurrentUser() ] );         //CurrentUser is currently logged in user.
 | 
						|
 | 
						|
			//remove duplicate user_ids
 | 
						|
			$user_ids = array_unique( $user_ids );
 | 
						|
			return $user_ids;
 | 
						|
		}
 | 
						|
 | 
						|
		return [];
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @return bool
 | 
						|
	 */
 | 
						|
	function sendNotificationAuthorization( ) {
 | 
						|
		Debug::Text( 'getNotificationData: ', __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
 | 
						|
		$user_ids = $this->getUserAuthorizationIds();
 | 
						|
		if ( empty ( $user_ids ) ) {
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
 | 
						|
		//Get initiator user from User Object so we can include more information in the message.
 | 
						|
		if ( is_object( $this->getCurrentUserObject() ) ) {
 | 
						|
			$u_obj = $this->getCurrentUserObject();
 | 
						|
		} else {
 | 
						|
			Debug::Text( 'From object does not exist: ' . $this->getCurrentUser(), __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
 | 
						|
		foreach ( $user_ids as $user_id ) {
 | 
						|
			//Grab each users preferences as they can be custom to them and their language etc.
 | 
						|
			$ulf = TTnew( 'UserListFactory' ); /** @var UserListFactory $ulf */
 | 
						|
			$ulf->getById( $user_id );
 | 
						|
			if ( $ulf->getRecordCount() == 1 ) {
 | 
						|
				$user_to_obj = $ulf->getCurrent();
 | 
						|
 | 
						|
				if ( is_object( $user_to_obj ) ) {
 | 
						|
					$user_to_pref_obj = $user_to_obj->getUserPreferenceObject(); /** @var UserPreferenceFactory $user_to_pref_obj */
 | 
						|
					$user_to_pref_obj->setDateTimePreferences();
 | 
						|
					TTi18n::setLanguage( $user_to_pref_obj->getLanguage() );
 | 
						|
					TTi18n::setCountry( $user_to_obj->getCountry() );
 | 
						|
					TTi18n::setLocale();
 | 
						|
				} else {
 | 
						|
					return false;
 | 
						|
				}
 | 
						|
			} else {
 | 
						|
				Debug::Text( 'ERROR: User does not exist: ' . $user_id, __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
 | 
						|
			$object_handler_user_obj = $this->getObjectHandlerObject()->getUserObject();                                                                                       //Object handler (request) user_id.
 | 
						|
			$status_label = TTi18n::ucfirst( TTi18n::strtolower( Option::getByKey( $this->getObjectHandlerObject()->getStatus(), Misc::trimSortPrefix( $this->getObjectHandlerObject()->getOptions( 'status' ) ) ) ) ); //PENDING, AUTHORIZED, DECLINED
 | 
						|
 | 
						|
			$title_short = '#object_type# '. TTi18n::gettext( 'by' ) .' #object_employee_first_name# #object_employee_last_name# #status#.';
 | 
						|
			$title_long = '#object_type# '. TTi18n::gettext( 'by' ) .' #object_employee_first_name# #object_employee_last_name# #status# '. TTi18n::gettext( 'for' ) .' #date#';
 | 
						|
 | 
						|
			switch ( $this->getObjectType() ) {
 | 
						|
				case 90: //TimeSheet
 | 
						|
					$object_type = TTi18n::getText( 'TimeSheet' );
 | 
						|
					$notification_object_type = 90;
 | 
						|
					if ( $this->getAuthorized() == true && $this->getObjectHandlerObject()->getAuthorizationLevel() == 0 ) {
 | 
						|
						// Timesheet has been verified link back to timesheet.
 | 
						|
						$link = Misc::getURLProtocol() . '://' . Misc::getHostName() . Environment::getDefaultInterfaceBaseURL() . 'html5/#!m=TimeSheet';
 | 
						|
						// If timesheet belongs to user being notified set type as timesheet_verify timesheet_authorize for supervisors.
 | 
						|
						if ( $object_handler_user_obj->getId() === $user_to_obj->getId() ) {
 | 
						|
							$notification_type = 'timesheet_verify';
 | 
						|
						} else {
 | 
						|
							$notification_type = 'timesheet_authorize';
 | 
						|
						}
 | 
						|
					} else {
 | 
						|
						$link = Misc::getURLProtocol() . '://' . Misc::getHostName() . Environment::getDefaultInterfaceBaseURL() . 'html5/#!m=TimeSheetAuthorization&a=view&id=' . $this->getObject() . '&tab=TimeSheetVerification';
 | 
						|
						$notification_type = 'timesheet_authorize';
 | 
						|
					}
 | 
						|
					$display_date = TTDate::getDate( 'DATE', $this->getObjectHandlerObject()->getPayPeriodObject()->getEndDate() );
 | 
						|
					$body_short = TTi18n::getText( 'Pay Period' ) . ': ' . TTDate::getDate( 'DATE', $this->getObjectHandlerObject()->getPayPeriodObject()->getStartDate() ) . ' -> ' . TTDate::getDate( 'DATE', $this->getObjectHandlerObject()->getPayPeriodObject()->getEndDate() );
 | 
						|
					break;
 | 
						|
				case 200: //Expense
 | 
						|
					$object_type = TTi18n::getText( 'Expense' );
 | 
						|
					$notification_object_type = 110;
 | 
						|
					if ( $this->getAuthorized() == true && $this->getObjectHandlerObject()->getAuthorizationLevel() == 0 ) {
 | 
						|
						// Expense has been authorized link back to original expense and not the authorization view.
 | 
						|
						$link = Misc::getURLProtocol() . '://' . Misc::getHostName() . Environment::getDefaultInterfaceBaseURL() . 'html5/#!m=LoginUserExpense&a=view&id=' . $this->getObject() . '&tab=Expense';
 | 
						|
						// If expense belongs to user being notified set type as expense_verify else expense_authorize for supervisors.
 | 
						|
						if ( $object_handler_user_obj->getId() === $user_to_obj->getId() ) {
 | 
						|
							$notification_type = 'expense_verify';
 | 
						|
						} else {
 | 
						|
							$notification_type = 'expense_authorize';
 | 
						|
						}
 | 
						|
					} else {
 | 
						|
						$link = Misc::getURLProtocol() . '://' . Misc::getHostName() . Environment::getDefaultInterfaceBaseURL() . 'html5/#!m=ExpenseAuthorization&a=edit&id=' . $this->getObject() . '&tab=Expense';
 | 
						|
						$notification_type = 'expense_authorize';
 | 
						|
					}
 | 
						|
					$display_date = TTDate::getDate( 'DATE', $this->getObjectHandlerObject()->getIncurredDate() );
 | 
						|
 | 
						|
					//Check if its a custom unit or just dollars so the message can be formatted properly for each.
 | 
						|
					if ( is_object( $this->getObjectHandlerObject()->getExpensePolicyObject() ) && $this->getObjectHandlerObject()->getExpensePolicyObject()->getType() == 30 ) { //30=Per Unit
 | 
						|
						$body_short = $this->getObjectHandlerObject()->getGrossAmount() . ' ' . $this->getObjectHandlerObject()->getExpensePolicyObject()->getUnitName() . ' ' . TTi18n::getText( 'incurred on' ) . ': ' . TTDate::getDate( 'DATE', $this->getObjectHandlerObject()->getIncurredDate() );
 | 
						|
					} else {
 | 
						|
						$body_short = '$' . $this->getObjectHandlerObject()->getGrossAmount() . ' ' . TTi18n::getText( 'incurred on' ) . ': ' . TTDate::getDate( 'DATE', $this->getObjectHandlerObject()->getIncurredDate() );
 | 
						|
					}
 | 
						|
 | 
						|
					//Add the reimbursable amount so its clear to the end-user.
 | 
						|
					$body_short .= "\n". TTi18n::getText( 'Reimbursable Amount' ) .': $'. $this->getObjectHandlerObject()->getReimburseAmount();
 | 
						|
 | 
						|
					break;
 | 
						|
				case 50: //Requests
 | 
						|
				case 1010:
 | 
						|
				case 1020:
 | 
						|
				case 1030:
 | 
						|
				case 1040:
 | 
						|
				case 1100:
 | 
						|
					$object_type = TTi18n::getText( 'Request' );
 | 
						|
					$notification_object_type = 50;
 | 
						|
					if ( $this->getAuthorized() == true && $this->getObjectHandlerObject()->getAuthorizationLevel() == 0 ) {
 | 
						|
						// Request has been authorized link back to original request and not the authorization view.
 | 
						|
						$link = Misc::getURLProtocol() . '://' . Misc::getHostName() . Environment::getDefaultInterfaceBaseURL() . 'html5/#!m=Request&a=view&id=' . $this->getObject() . '&tab=Request';
 | 
						|
						// If request belongs to user being notified set type as request else request_authorize for supervisors.
 | 
						|
						if ( $object_handler_user_obj->getId() === $user_to_obj->getId() ) {
 | 
						|
							$notification_type = 'request';
 | 
						|
						} else {
 | 
						|
							$notification_type = 'request_authorize';
 | 
						|
						}
 | 
						|
					} else {
 | 
						|
						$link = Misc::getURLProtocol() . '://' . Misc::getHostName() . Environment::getDefaultInterfaceBaseURL() . 'html5/#!m=RequestAuthorization&a=view&id=' . $this->getObject() . '&tab=Request';
 | 
						|
						$notification_type = 'request_authorize';
 | 
						|
					}
 | 
						|
					$display_date = TTDate::getDate( 'DATE', $this->getObjectHandlerObject()->getDateStamp() );
 | 
						|
					$body_short = Option::getByKey( $this->getObjectHandlerObject()->getType(), Misc::trimSortPrefix( $this->getObjectHandlerObject()->getOptions( 'type' ) ) ) . ' ' . TTi18n::getText( 'on' ) . ' ' . TTDate::getDate( 'DATE', $this->getObjectHandlerObject()->getDateStamp() );
 | 
						|
					break;
 | 
						|
			}
 | 
						|
 | 
						|
			//Define title_short/body variables here.
 | 
						|
			$search_arr = [
 | 
						|
					'#object_type#',
 | 
						|
					'#object_type_long_description#',
 | 
						|
					'#status#',
 | 
						|
					'#date#',
 | 
						|
 | 
						|
					'#current_employee_first_name#',
 | 
						|
					'#current_employee_last_name#',
 | 
						|
 | 
						|
					'#object_employee_first_name#',
 | 
						|
					'#object_employee_last_name#',
 | 
						|
					'#object_employee_default_branch#',
 | 
						|
					'#object_employee_default_department#',
 | 
						|
					'#object_employee_group#',
 | 
						|
					'#object_employee_title#',
 | 
						|
 | 
						|
					'#company_name#',
 | 
						|
					'#url#',
 | 
						|
			];
 | 
						|
 | 
						|
			$replace_arr = Misc::escapeHTML( [
 | 
						|
					$object_type,
 | 
						|
					$body_short,
 | 
						|
					$status_label,
 | 
						|
					$display_date,
 | 
						|
 | 
						|
					$u_obj->getFirstName(),
 | 
						|
					$u_obj->getLastName(),
 | 
						|
 | 
						|
					$object_handler_user_obj->getFirstName(),
 | 
						|
					$object_handler_user_obj->getLastName(),
 | 
						|
					( is_object( $object_handler_user_obj->getDefaultBranchObject() ) ) ? $object_handler_user_obj->getDefaultBranchObject()->getName() : null,
 | 
						|
					( is_object( $object_handler_user_obj->getDefaultDepartmentObject() ) ) ? $object_handler_user_obj->getDefaultDepartmentObject()->getName() : null,
 | 
						|
					( is_object( $object_handler_user_obj->getGroupObject() ) ) ? $object_handler_user_obj->getGroupObject()->getName() : null,
 | 
						|
					( is_object( $object_handler_user_obj->getTitleObject() ) ) ? $object_handler_user_obj->getTitleObject()->getName() : null,
 | 
						|
 | 
						|
					( is_object( $object_handler_user_obj->getCompanyObject() ) ) ? $object_handler_user_obj->getCompanyObject()->getName() : null,
 | 
						|
					( Misc::getURLProtocol() . '://' . Misc::getHostName() . Environment::getDefaultInterfaceBaseURL() ),
 | 
						|
			] );
 | 
						|
 | 
						|
			$title_short = str_replace( $search_arr, $replace_arr, $title_short );
 | 
						|
			$title_long = str_replace( $search_arr, $replace_arr, $title_long );
 | 
						|
			$body_short = str_replace( $search_arr, $replace_arr, $body_short );
 | 
						|
 | 
						|
			//$body_long = TTi18n::gettext( '*DO NOT REPLY TO THIS EMAIL - PLEASE USE THE LINK BELOW INSTEAD*' ) . "\n\n";
 | 
						|
			$body_long = '#object_type# '. TTi18n::gettext( 'by' ) .' #object_employee_first_name# #object_employee_last_name# #status#'. "\n";
 | 
						|
			$body_long .= ( $replace_arr[1] != '' ) ? '#object_type_long_description#' . "\n" : null;
 | 
						|
			$body_long .= "\n";
 | 
						|
			$body_long .= ( $replace_arr[8] != '' ) ? TTi18n::gettext( 'Default Branch' ) . ': #object_employee_default_branch#' . "\n" : null;
 | 
						|
			$body_long .= ( $replace_arr[9] != '' ) ? TTi18n::gettext( 'Default Department' ) . ': #object_employee_default_department#' . "\n" : null;
 | 
						|
			$body_long .= ( $replace_arr[10] != '' ) ? TTi18n::gettext( 'Group' ) . ': #object_employee_group#' . "\n" : null;
 | 
						|
			$body_long .= ( $replace_arr[11] != '' ) ? TTi18n::gettext( 'Title' ) . ': #object_employee_title#' . "\n" : null;
 | 
						|
			$body_long .= TTi18n::gettext( 'Link' ) . ': <a href="#url#">' . APPLICATION_NAME . ' ' . TTi18n::gettext( 'Login' ) . '</a>' . "\n";
 | 
						|
 | 
						|
			$body_long .= NotificationFactory::addEmailFooter( ( ( is_object( $object_handler_user_obj->getCompanyObject() ) ) ? $object_handler_user_obj->getCompanyObject()->getName() : null ) );
 | 
						|
			$body_long = '<html><body><pre>' . str_replace( $search_arr, $replace_arr, $body_long ) . '</pre></body></html>';
 | 
						|
 | 
						|
			$notification_data = [
 | 
						|
					'object_id'      => $this->getObject(),
 | 
						|
					'user_id'        => $user_id,
 | 
						|
					'type_id'        => $notification_type,
 | 
						|
					'object_type_id' => $notification_object_type,
 | 
						|
					'title_short'    => $title_short,
 | 
						|
					'title_long'     => $title_long,
 | 
						|
					'body_short'     => $body_short,
 | 
						|
					'body_long_html' => $body_long, //For emails
 | 
						|
					'payload'        => [ 'link' => $link ],
 | 
						|
			];
 | 
						|
 | 
						|
			Notification::sendNotification( $notification_data );
 | 
						|
		}
 | 
						|
 | 
						|
		//reset datetime and tti8n preferences to current user
 | 
						|
		$user_pref_obj = $u_obj->getUserPreferenceObject(); /** @var UserPreferenceFactory $user_pref_obj */
 | 
						|
		$user_pref_obj->setDateTimePreferences();
 | 
						|
		TTi18n::setLanguage( $user_pref_obj->getLanguage() );
 | 
						|
		TTi18n::setCountry( $u_obj->getCountry() );
 | 
						|
		TTi18n::setLocale();
 | 
						|
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	function markRelatedNotificationsAsRead() {
 | 
						|
		$request_object_type_to_notification_object_type_map = [
 | 
						|
			90 => 90, //'timesheet',
 | 
						|
			200  => 110, //'expense',
 | 
						|
			//50 => 'request', //request_other
 | 
						|
			1010 => 50, //'request_punch',
 | 
						|
			1020 => 50, //'request_punch_adjust',
 | 
						|
			1030 => 50, //'request_absence',
 | 
						|
			1040 => 50, //'request_schedule',
 | 
						|
			1100 => 50, //'request_other',
 | 
						|
		];
 | 
						|
 | 
						|
		if ( isset( $request_object_type_to_notification_object_type_map[$this->getObjectType()] ) ) {
 | 
						|
			$notification_object_type_id = $request_object_type_to_notification_object_type_map[$this->getObjectType()];
 | 
						|
			if ( $this->isFinalAuthorization() == true ) {
 | 
						|
				//If its a final authorization, mark notification as read for *all* notifications/users at any level.
 | 
						|
				NotificationFactory::updateStatusByObjectIdAndObjectTypeId( $notification_object_type_id, $this->getObject() ); //Mark any notifications linked to these exceptions as read.
 | 
						|
			} else {
 | 
						|
				//If its a superior at a low level, only mark notifications as read for any other superior at the same level.
 | 
						|
				$hierarchy_current_level_user_ids = $this->getHierarchyCurrentLevelArray();
 | 
						|
				NotificationFactory::updateStatusByObjectIdAndObjectTypeId( $notification_object_type_id, $this->getObject(), $hierarchy_current_level_user_ids ); //Mark any notifications linked to these exceptions as read.
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Used by Request/TimeSheetVerification/Expense when initially saving a record to notify the immediate superiors, rather than using the message notification.
 | 
						|
	 * @param string $current_user_id UUID
 | 
						|
	 * @param int $object_type_id
 | 
						|
	 * @param string $object_id       UUID
 | 
						|
	 * @return bool
 | 
						|
	 */
 | 
						|
	static function sendNotificationAuthorizationOnInitialObjectSave( $current_user_id, $object_type_id, $object_id ) {
 | 
						|
		$authorization_obj = TTNew( 'AuthorizationFactory' ); /** @var AuthorizationFactory $authorization_obj */
 | 
						|
		$authorization_obj->setObjectType( $object_type_id );
 | 
						|
		$authorization_obj->setObject( $object_id );
 | 
						|
		$authorization_obj->setCurrentUser( $current_user_id );
 | 
						|
		$authorization_obj->setAuthorized( true );
 | 
						|
		$authorization_obj->sendNotificationAuthorization();
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @return bool
 | 
						|
	 */
 | 
						|
	function isUnique() {
 | 
						|
		$ph = [
 | 
						|
				'object_type' => (int)$this->getObjectType(),
 | 
						|
				'object_id'   => TTUUID::castUUID( $this->getObject() ),
 | 
						|
				'authorized'  => (int)$this->getAuthorized(),
 | 
						|
				'created_by'  => TTUUID::castUUID( $this->getCreatedBy() ),
 | 
						|
		];
 | 
						|
 | 
						|
		$query = 'select id from ' . $this->getTable() . ' where object_type_id = ? AND object_id = ? AND authorized = ? AND created_by = ?';
 | 
						|
		$id = $this->db->GetOne( $query, $ph );
 | 
						|
		Debug::Arr( $id, 'Unique Authorization: ' . $id, __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
 | 
						|
		if ( $id === false ) {
 | 
						|
			return true;
 | 
						|
		} else {
 | 
						|
			if ( $id == $this->getId() ) {
 | 
						|
				return true;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @param bool $ignore_warning
 | 
						|
	 * @return bool
 | 
						|
	 */
 | 
						|
	function Validate( $ignore_warning = true ) {
 | 
						|
		//
 | 
						|
		// BELOW: Validation code moved from set*() functions.
 | 
						|
		//
 | 
						|
		// Object Type
 | 
						|
		$this->Validator->inArrayKey( 'object_type',
 | 
						|
									  $this->getObjectType(),
 | 
						|
									  TTi18n::gettext( 'Object Type is invalid' ),
 | 
						|
									  $this->getOptions( 'object_type' )
 | 
						|
		);
 | 
						|
		// Object ID
 | 
						|
		$this->Validator->isResultSetWithRows( 'object',
 | 
						|
											   ( is_object( $this->getObjectHandler() ) ) ? $this->getObjectHandler()->getByID( $this->getObject() ) : false,
 | 
						|
											   TTi18n::gettext( 'Object ID is invalid' )
 | 
						|
		);
 | 
						|
 | 
						|
		//Prevent duplicate authorizations by the same person.
 | 
						|
		// This may cause problems if the hierarchy is changed and the same superior needs to authorize the request again though?
 | 
						|
		//   By definition this should never happen at the final authorization level, so someone higher up in the hierarchy could always drop down and authorize it during the transition.
 | 
						|
		if ( $this->getDeleted() == false ) {
 | 
						|
			if ( $this->Validator->getValidateOnly() == false && $this->isUnique() == false ) {
 | 
						|
				$this->Validator->isTrue( 'object',
 | 
						|
										  false,
 | 
						|
										  TTi18n::gettext( 'Record has already been authorized/declined by you' ) );
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		//
 | 
						|
		// ABOVE: Validation code moved from set*() functions.
 | 
						|
		//
 | 
						|
		if ( $this->getDeleted() === false
 | 
						|
				&& $this->isFinalAuthorization() === false
 | 
						|
				&& $this->isValidParent() === false ) {
 | 
						|
			//FYI: This error may occur on timesheet authorization if the timesheet cannot be verified because pending requests or critical severity exceptions exist. Though it should display a proper validation message to that affect instead.
 | 
						|
			$this->Validator->isTrue( 'parent',
 | 
						|
									  false,
 | 
						|
									  TTi18n::gettext( 'Employee authorizing this object is not a superior in the hierarchy that controls it' ) );
 | 
						|
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
 | 
						|
		$this->setObjectHandlerStatus();
 | 
						|
 | 
						|
		if ( $this->getDeleted() == false && is_object( $this->getObjectHandlerObject() ) && $this->getObjectHandlerObject()->isValid() == false ) {
 | 
						|
			Debug::text( '  ObjectHandler Validation Failed, pass validation errors up the chain...', __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
			$this->Validator->merge( $this->getObjectHandlerObject()->Validator );
 | 
						|
		}
 | 
						|
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @return bool
 | 
						|
	 */
 | 
						|
	function preSave() {
 | 
						|
		//Debug::Text(' Calling preSave!: ', __FILE__, __LINE__, __METHOD__, 10);
 | 
						|
		$this->StartTransaction();
 | 
						|
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @return bool
 | 
						|
	 */
 | 
						|
	function postSave() {
 | 
						|
		if ( $this->getDeleted() == false ) {
 | 
						|
			if ( is_object( $this->getObjectHandlerObject() ) && $this->getObjectHandlerObject()->isValid() == true ) {
 | 
						|
				Debug::text( '  Object Valid...', __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
				//Return true if object saved correctly.
 | 
						|
				$retval = $this->getObjectHandlerObject()->Save( false );
 | 
						|
				if ( $this->getObjectHandlerObject()->isValid() == false ) {
 | 
						|
					Debug::text( '  Object postSave validation FAILED!', __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
					$this->Validator->merge( $this->getObjectHandlerObject()->Validator );
 | 
						|
				} else {
 | 
						|
					Debug::text( '  Object postSave validation SUCCESS!', __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
					$this->markRelatedNotificationsAsRead(); //Mark existing notifications as read before new ones are sent.
 | 
						|
					$this->sendNotificationAuthorization();
 | 
						|
				}
 | 
						|
 | 
						|
				if ( $retval === true ) {
 | 
						|
					$this->CommitTransaction();
 | 
						|
 | 
						|
					return true;
 | 
						|
				} else {
 | 
						|
					$this->FailTransaction();
 | 
						|
				}
 | 
						|
			} else {
 | 
						|
				//Always fail the transaction if we get this far.
 | 
						|
				//This stops authorization entries from being inserted.
 | 
						|
				$this->FailTransaction();
 | 
						|
			}
 | 
						|
 | 
						|
			$this->CommitTransaction(); //preSave() starts the transaction
 | 
						|
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
 | 
						|
		$this->CommitTransaction(); //preSave() starts the transaction
 | 
						|
 | 
						|
		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 ) {
 | 
						|
						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 = [];
 | 
						|
		$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 'object_type':
 | 
						|
							Debug::text( '  Object Type...', __FILE__, __LINE__, __METHOD__, 10 );
 | 
						|
							$data[$variable] = Option::getByKey( $this->getObjectType(), $this->getOptions( $variable ) );
 | 
						|
							break;
 | 
						|
						default:
 | 
						|
							if ( method_exists( $this, $function ) ) {
 | 
						|
								$data[$variable] = $this->$function();
 | 
						|
							}
 | 
						|
							break;
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
			$this->getPermissionColumns( $data, $this->getColumn( 'user_id' ), $this->getCreatedBy(), $permission_children_ids, $include_columns );
 | 
						|
			$this->getCreatedAndUpdatedColumns( $data, $include_columns );
 | 
						|
		}
 | 
						|
 | 
						|
		return $data;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @param $log_action
 | 
						|
	 * @return bool
 | 
						|
	 */
 | 
						|
	function addLog( $log_action ) {
 | 
						|
		if ( $this->getAuthorized() === true ) {
 | 
						|
			$authorized = TTi18n::getText( 'True' );
 | 
						|
		} else {
 | 
						|
			$authorized = TTi18n::getText( 'False' );
 | 
						|
		}
 | 
						|
 | 
						|
		return TTLog::addEntry( $this->getId(), $log_action, TTi18n::getText( 'Authorization Object Type' ) . ': ' . ucwords( str_replace( '_', ' ', Option::getByKey( $this->getObjectType(), $this->getOptions( 'object_type' ) ) ) ) . ' ' . TTi18n::getText( 'Authorized' ) . ': ' . $authorized, null, $this->getTable() );
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
?>
 |