TimeTrex Community Edition v16.2.0
This commit is contained in:
550
classes/modules/hierarchy/HierarchyControlFactory.class.php
Normal file
550
classes/modules/hierarchy/HierarchyControlFactory.class.php
Normal file
@ -0,0 +1,550 @@
|
||||
<?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 Modules\Hierarchy
|
||||
*/
|
||||
class HierarchyControlFactory extends Factory {
|
||||
protected $table = 'hierarchy_control';
|
||||
protected $pk_sequence_name = 'hierarchy_control_id_seq'; //PK Sequence name
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $parent
|
||||
* @return array|null
|
||||
*/
|
||||
function _getFactoryOptions( $name, $parent = null ) {
|
||||
|
||||
$retval = null;
|
||||
switch ( $name ) {
|
||||
case 'object_type':
|
||||
$hotlf = TTnew( 'HierarchyObjectTypeListFactory' ); /** @var HierarchyObjectTypeListFactory $hotlf */
|
||||
$retval = $hotlf->getOptions( 'object_type' ); //Must contain sort prefixes, otherwise Edit Employee -> Hierarchy tab will be in the wrong order.
|
||||
break;
|
||||
case 'short_object_type':
|
||||
$hotlf = TTnew( 'HierarchyObjectTypeListFactory' ); /** @var HierarchyObjectTypeListFactory $hotlf */
|
||||
$retval = $hotlf->getOptions( 'short_object_type' );
|
||||
break;
|
||||
case 'columns':
|
||||
$retval = [
|
||||
'-1010-name' => TTi18n::gettext( 'Name' ),
|
||||
'-1020-description' => TTi18n::gettext( 'Description' ),
|
||||
'-1030-superiors' => TTi18n::gettext( 'Superiors' ),
|
||||
'-1030-subordinates' => TTi18n::gettext( 'Subordinates' ),
|
||||
'-1050-object_type_display' => TTi18n::gettext( 'Objects' ),
|
||||
|
||||
'-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 = [
|
||||
'name',
|
||||
'description',
|
||||
'superiors',
|
||||
'subordinates',
|
||||
'object_type_display',
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
return $retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @return array
|
||||
*/
|
||||
function _getVariableToFunctionMap( $data ) {
|
||||
$variable_function_map = [
|
||||
'id' => 'ID',
|
||||
'company_id' => 'Company',
|
||||
'name' => 'Name',
|
||||
'description' => 'Description',
|
||||
'superiors' => 'TotalSuperiors',
|
||||
'subordinates' => 'TotalSubordinates',
|
||||
'object_type' => 'ObjectType',
|
||||
'object_type_display' => false,
|
||||
'user' => 'User',
|
||||
'deleted' => 'Deleted',
|
||||
];
|
||||
|
||||
return $variable_function_map;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|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 );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return bool
|
||||
*/
|
||||
function isUniqueName( $name ) {
|
||||
$name = trim( $name );
|
||||
if ( $name == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ph = [
|
||||
'company_id' => TTUUID::castUUID( $this->getCompany() ),
|
||||
'name' => TTi18n::strtolower( $name ),
|
||||
];
|
||||
|
||||
$query = 'select id from ' . $this->getTable() . ' where company_id = ? AND lower(name) = ? AND deleted = 0';
|
||||
$hierarchy_control_id = $this->db->GetOne( $query, $ph );
|
||||
Debug::Arr( $hierarchy_control_id, 'Unique Hierarchy Control ID: ' . $hierarchy_control_id, __FILE__, __LINE__, __METHOD__, 10 );
|
||||
|
||||
if ( $hierarchy_control_id === false ) {
|
||||
return true;
|
||||
} else {
|
||||
if ( $hierarchy_control_id == $this->getId() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|mixed
|
||||
*/
|
||||
function getName() {
|
||||
return $this->getGenericDataValue( 'name' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @return bool
|
||||
*/
|
||||
function setName( $value ) {
|
||||
$value = trim( $value );
|
||||
|
||||
return $this->setGenericDataValue( 'name', $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 null|string
|
||||
*/
|
||||
function getObjectTypeDisplay() {
|
||||
$object_type_ids = $this->getObjectType();
|
||||
$object_types = Misc::trimSortPrefix( $this->getOptions( 'short_object_type' ) );
|
||||
|
||||
$retval = [];
|
||||
if ( is_array( $object_type_ids ) ) {
|
||||
foreach ( $object_type_ids as $object_type_id ) {
|
||||
$retval[] = Option::getByKey( $object_type_id, $object_types );
|
||||
}
|
||||
sort( $retval ); //Maintain consistent order.
|
||||
|
||||
return implode( ',', $retval );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|bool
|
||||
*/
|
||||
function getObjectType() {
|
||||
$valid_object_type_ids = Misc::trimSortPrefix( $this->getOptions( 'object_type' ) );
|
||||
|
||||
$hotlf = TTnew( 'HierarchyObjectTypeListFactory' ); /** @var HierarchyObjectTypeListFactory $hotlf */
|
||||
$hotlf->getByHierarchyControlId( $this->getId() );
|
||||
if ( $hotlf->getRecordCount() > 0 ) {
|
||||
foreach ( $hotlf as $object_type ) {
|
||||
if ( isset( $valid_object_type_ids[$object_type->getObjectType()] ) ) {
|
||||
$object_type_list[] = $object_type->getObjectType();
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $object_type_list ) ) {
|
||||
return $object_type_list;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|string[] $ids UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setObjectType( $ids ) {
|
||||
if ( is_array( $ids ) && count( $ids ) > 0 ) {
|
||||
$tmp_ids = [];
|
||||
Debug::Arr( $ids, 'IDs: ', __FILE__, __LINE__, __METHOD__, 10 );
|
||||
|
||||
if ( !$this->isNew() ) {
|
||||
//If needed, delete mappings first.
|
||||
$lf_a = TTnew( 'HierarchyObjectTypeListFactory' ); /** @var HierarchyObjectTypeListFactory $lf_a */
|
||||
$lf_a->getByHierarchyControlId( $this->getId() );
|
||||
Debug::text( 'Existing Object Type Rows: ' . $lf_a->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10 );
|
||||
|
||||
foreach ( $lf_a as $obj ) {
|
||||
//$id = $obj->getId();
|
||||
$id = $obj->getObjectType(); //Need to use object_types rather than row IDs.
|
||||
Debug::text( 'Hierarchy Object Type ID: ' . $obj->getId() . ' ID: ' . $id, __FILE__, __LINE__, __METHOD__, 10 );
|
||||
|
||||
//Delete users that are not selected.
|
||||
if ( !in_array( $id, $ids ) ) {
|
||||
Debug::text( 'Deleting: Object Type: ' . $id . ' ID: ' . $obj->getID(), __FILE__, __LINE__, __METHOD__, 10 );
|
||||
$obj->Delete();
|
||||
$obj->postSave(); //Clear cache.
|
||||
} else {
|
||||
//Save ID's that need to be updated.
|
||||
Debug::text( 'NOT Deleting: Object Type: ' . $id . ' ID: ' . $obj->getID(), __FILE__, __LINE__, __METHOD__, 10 );
|
||||
$tmp_ids[] = $id;
|
||||
}
|
||||
}
|
||||
unset( $id, $obj );
|
||||
}
|
||||
|
||||
foreach ( $ids as $id ) {
|
||||
if ( isset( $ids ) && !in_array( $id, $tmp_ids ) ) {
|
||||
$hotf = TTnew( 'HierarchyObjectTypeFactory' ); /** @var HierarchyObjectTypeFactory $hotf */
|
||||
$hotf->setHierarchyControl( $this->getId() );
|
||||
$hotf->setObjectType( $id );
|
||||
|
||||
if ( $this->Validator->isTrue( 'object_type',
|
||||
$hotf->isValid(),
|
||||
TTi18n::gettext( 'Object type is already assigned to another hierarchy' ) ) ) {
|
||||
$hotf->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->Validator->isTrue( 'object_type',
|
||||
false,
|
||||
TTi18n::gettext( 'At least one object must be selected' ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|bool
|
||||
*/
|
||||
function getUser() {
|
||||
$hulf = TTnew( 'HierarchyUserListFactory' ); /** @var HierarchyUserListFactory $hulf */
|
||||
$hulf->getByHierarchyControlID( $this->getId() );
|
||||
foreach ( $hulf as $obj ) {
|
||||
$list[] = $obj->getUser();
|
||||
}
|
||||
|
||||
if ( isset( $list ) ) {
|
||||
return $list;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $ids UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setUser( $ids ) {
|
||||
if ( !is_array( $ids ) ) {
|
||||
$ids = [ $ids ];
|
||||
}
|
||||
|
||||
Debug::text( 'Setting User IDs : ', __FILE__, __LINE__, __METHOD__, 10 );
|
||||
if ( is_array( $ids ) ) {
|
||||
$tmp_ids = [];
|
||||
|
||||
if ( !$this->isNew() ) {
|
||||
//If needed, delete mappings first.
|
||||
$hulf = TTnew( 'HierarchyUserListFactory' ); /** @var HierarchyUserListFactory $hulf */
|
||||
$hulf->getByHierarchyControlID( $this->getId() );
|
||||
|
||||
foreach ( $hulf as $obj ) {
|
||||
$id = $obj->getUser();
|
||||
Debug::text( 'HierarchyControl ID: ' . $obj->getHierarchyControl() . ' 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.
|
||||
$ulf = TTnew( 'UserListFactory' ); /** @var UserListFactory $ulf */
|
||||
|
||||
foreach ( $ids as $id ) {
|
||||
if ( isset( $ids ) && !in_array( $id, $tmp_ids ) ) {
|
||||
$huf = TTnew( 'HierarchyUserFactory' ); /** @var HierarchyUserFactory $huf */
|
||||
$huf->setHierarchyControl( $this->getId() );
|
||||
$huf->setUser( $id );
|
||||
|
||||
$ulf->getById( $id );
|
||||
if ( $ulf->getRecordCount() > 0 ) {
|
||||
$obj = $ulf->getCurrent();
|
||||
|
||||
if ( $this->Validator->isTrue( 'user',
|
||||
$huf->isValid(),
|
||||
TTi18n::gettext( 'Selected subordinate is invalid or already assigned to another hierarchy with the same objects' ) . ' (' . $obj->getFullName() . ')' )
|
||||
) {
|
||||
$huf->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Debug::text( 'No User IDs to set.', __FILE__, __LINE__, __METHOD__, 10 );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
function getTotalSubordinates() {
|
||||
$hulf = TTnew( 'HierarchyUserListFactory' ); /** @var HierarchyUserListFactory $hulf */
|
||||
$hulf->getByHierarchyControlID( $this->getId() );
|
||||
|
||||
return $hulf->getRecordCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
function getTotalSuperiors() {
|
||||
$hllf = TTnew( 'HierarchyLevelListFactory' ); /** @var HierarchyLevelListFactory $hllf */
|
||||
$hllf->getByHierarchyControlId( $this->getID() );
|
||||
|
||||
return $hllf->getRecordCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* @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( 'Invalid Company' )
|
||||
);
|
||||
// Name
|
||||
$this->Validator->isLength( 'name',
|
||||
$this->getName(),
|
||||
TTi18n::gettext( 'Name is invalid' ),
|
||||
2, 250
|
||||
);
|
||||
if ( $this->Validator->isError( 'name' ) == false ) {
|
||||
$this->Validator->isTrue( 'name',
|
||||
$this->isUniqueName( $this->getName() ),
|
||||
TTi18n::gettext( 'Name is already in use' )
|
||||
);
|
||||
}
|
||||
// Description
|
||||
if ( $this->getDescription() != '' ) {
|
||||
$this->Validator->isLength( 'description',
|
||||
$this->getDescription(),
|
||||
TTi18n::gettext( 'Description is invalid' ),
|
||||
1, 250
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// ABOVE: Validation code moved from set*() functions.
|
||||
//
|
||||
if ( $this->getName() == false && $this->Validator->hasError( 'name' ) == false ) {
|
||||
$this->Validator->isTrue( 'name',
|
||||
false,
|
||||
TTi18n::gettext( 'Name is not specified' ) );
|
||||
}
|
||||
|
||||
//When the user changes just the hierarchy objects, we need to loop through ALL users and confirm no conflicting hierarchies exist.
|
||||
//Only do this for existing hierarchies and ones that are already valid up to this point.
|
||||
if ( !$this->isNew() && $this->Validator->isValid() == true ) {
|
||||
|
||||
$user_ids = $this->getUser();
|
||||
if ( is_array( $user_ids ) ) {
|
||||
$huf = TTNew( 'HierarchyUserFactory' ); /** @var HierarchyUserFactory $huf */
|
||||
$huf->setHierarchyControl( $this->getID() );
|
||||
|
||||
foreach ( $user_ids as $user_id ) {
|
||||
if ( $huf->isUniqueUser( $user_id ) == false ) {
|
||||
$ulf = TTnew( 'UserListFactory' ); /** @var UserListFactory $ulf */
|
||||
$ulf->getById( $user_id );
|
||||
if ( $ulf->getRecordCount() > 0 ) {
|
||||
$obj = $ulf->getCurrent();
|
||||
$this->Validator->isTrue( 'user',
|
||||
$huf->isUniqueUser( $user_id, $this->getID() ),
|
||||
TTi18n::gettext( 'Selected subordinate is invalid or already assigned to another hierarchy with the same objects' ) . ' (' . $obj->getFullName() . ')' );
|
||||
} else {
|
||||
TTi18n::gettext( 'Selected subordinate is invalid or already assigned to another hierarchy with the same object. User ID: %1', [ $user_id ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
* @return mixed
|
||||
*/
|
||||
function getObjectAsArray( $include_columns = null ) {
|
||||
$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 'superiors':
|
||||
//case 'subordinates':
|
||||
// $data[$variable] = $this->getColumn($variable);
|
||||
// break;
|
||||
case 'object_type_display':
|
||||
$data[$variable] = $this->getObjectTypeDisplay();
|
||||
break;
|
||||
default:
|
||||
if ( method_exists( $this, $function ) ) {
|
||||
$data[$variable] = $this->$function();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->getCreatedAndUpdatedColumns( $data, $include_columns );
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $log_action
|
||||
* @return bool
|
||||
*/
|
||||
function addLog( $log_action ) {
|
||||
return TTLog::addEntry( $this->getId(), $log_action, TTi18n::getText( 'Hierarchy' ), null, $this->getTable(), $this );
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
455
classes/modules/hierarchy/HierarchyControlListFactory.class.php
Normal file
455
classes/modules/hierarchy/HierarchyControlListFactory.class.php
Normal file
@ -0,0 +1,455 @@
|
||||
<?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 Modules\Hierarchy
|
||||
*/
|
||||
class HierarchyControlListFactory extends HierarchyControlFactory implements IteratorAggregate {
|
||||
|
||||
/**
|
||||
* @param int $limit Limit the number of records returned
|
||||
* @param int $page Page number of records to return for pagination
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return $this
|
||||
*/
|
||||
function getAll( $limit = null, $page = null, $where = null, $order = null ) {
|
||||
$query = '
|
||||
select *
|
||||
from ' . $this->getTable() . '
|
||||
WHERE deleted = 0';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, null, $limit, $page );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyControlListFactory
|
||||
*/
|
||||
function getById( $id, $where = null, $order = null ) {
|
||||
if ( $id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ph = [
|
||||
'id' => TTUUID::castUUID( $id ),
|
||||
];
|
||||
|
||||
|
||||
$query = '
|
||||
select *
|
||||
from ' . $this->getTable() . '
|
||||
where id = ?
|
||||
AND deleted = 0';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param string $company_id UUID
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyControlListFactory
|
||||
*/
|
||||
function getByIdAndCompanyId( $id, $company_id, $where = null, $order = null ) {
|
||||
if ( $id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $company_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ph = [
|
||||
'id' => TTUUID::castUUID( $id ),
|
||||
'company_id' => TTUUID::castUUID( $company_id ),
|
||||
];
|
||||
|
||||
$query = '
|
||||
select *
|
||||
from ' . $this->getTable() . '
|
||||
where id = ?
|
||||
AND company_id = ?
|
||||
AND deleted = 0';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param int $limit Limit the number of records returned
|
||||
* @param int $page Page number of records to return for pagination
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyControlListFactory
|
||||
*/
|
||||
function getByCompanyId( $id, $limit = null, $page = null, $where = null, $order = null ) {
|
||||
if ( $id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$strict_order = true;
|
||||
if ( $order == null ) {
|
||||
$order = [ 'name' => 'asc' ];
|
||||
$strict_order = false;
|
||||
}
|
||||
|
||||
$ph = [
|
||||
'id' => TTUUID::castUUID( $id ),
|
||||
];
|
||||
|
||||
|
||||
$query = '
|
||||
select *
|
||||
from ' . $this->getTable() . '
|
||||
where
|
||||
company_id = ?
|
||||
AND deleted = 0
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order, $strict_order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph, $limit, $page );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $lf
|
||||
* @param bool $include_blank
|
||||
* @param bool $object_sorted_array
|
||||
* @param bool $include_name
|
||||
* @return array|bool
|
||||
*/
|
||||
function getArrayByListFactory( $lf, $include_blank = true, $object_sorted_array = false, $include_name = true ) {
|
||||
if ( !is_object( $lf ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$list = [];
|
||||
if ( $object_sorted_array == false && $include_blank == true ) {
|
||||
$list[TTUUID::getZeroID()] = TTi18n::gettext('-- None --');
|
||||
}
|
||||
|
||||
//Make sure we always ensure that we return valid object_types for the product edition.
|
||||
$valid_object_type_ids = Misc::trimSortPrefix( $this->getOptions( 'object_type' ) );
|
||||
|
||||
foreach ( $lf as $obj ) {
|
||||
if ( isset( $valid_object_type_ids[$obj->getColumn( 'object_type_id' )] ) ) {
|
||||
if ( $object_sorted_array == true ) {
|
||||
if ( $include_blank == true && !isset( $list[$obj->getColumn( 'object_type_id' )][TTUUID::getZeroID()] ) ) {
|
||||
$list[$obj->getColumn( 'object_type_id' )][TTUUID::getZeroID()] = TTi18n::gettext('-- None --');
|
||||
}
|
||||
|
||||
if ( $include_name == true ) {
|
||||
$list[$obj->getColumn( 'object_type_id' )][$obj->getID()] = $obj->getName();
|
||||
} else {
|
||||
$list[$obj->getColumn( 'object_type_id' )] = $obj->getID();
|
||||
}
|
||||
} else {
|
||||
$list[$obj->getID()] = $obj->getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $list ) == false ) {
|
||||
return $list;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $company_id UUID
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyControlListFactory
|
||||
*/
|
||||
function getObjectTypeAppendedListByCompanyID( $company_id, $where = null, $order = null ) {
|
||||
if ( $company_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $order == null ) {
|
||||
$order = [ 'name' => 'asc', 'description' => 'asc' ];
|
||||
$strict = false;
|
||||
} else {
|
||||
//Always sort by last name, first name after other columns
|
||||
if ( !isset( $order['name'] ) ) {
|
||||
$order['name'] = 'asc';
|
||||
}
|
||||
$strict = true;
|
||||
}
|
||||
|
||||
$hotf = new HierarchyObjectTypeFactory();
|
||||
|
||||
$ph = [
|
||||
'company_id' => TTUUID::castUUID( $company_id ),
|
||||
];
|
||||
|
||||
$query = '
|
||||
select a.*,
|
||||
b.object_type_id
|
||||
from ' . $this->getTable() . ' as a
|
||||
LEFT JOIN ' . $hotf->getTable() . ' as b ON a.id = b.hierarchy_control_id
|
||||
where a.company_id = ?
|
||||
AND a.deleted = 0
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order, $strict );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $company_id UUID
|
||||
* @param string $user_id UUID
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyControlListFactory
|
||||
*/
|
||||
function getObjectTypeAppendedListByCompanyIDAndUserID( $company_id, $user_id, $where = null, $order = null ) {
|
||||
if ( $company_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $user_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$hotf = new HierarchyObjectTypeFactory();
|
||||
$huf = new HierarchyUserFactory();
|
||||
|
||||
$ph = [
|
||||
'company_id' => TTUUID::castUUID( $company_id ),
|
||||
'user_id' => TTUUID::castUUID( $user_id ),
|
||||
];
|
||||
|
||||
$query = '
|
||||
select a.*,
|
||||
b.object_type_id
|
||||
from ' . $this->getTable() . ' as a
|
||||
LEFT JOIN ' . $hotf->getTable() . ' as b ON a.id = b.hierarchy_control_id
|
||||
LEFT JOIN ' . $huf->getTable() . ' as c ON a.id = c.hierarchy_control_id
|
||||
where a.company_id = ?
|
||||
AND c.user_id = ?
|
||||
AND a.deleted = 0
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $company_id UUID
|
||||
* @param string $user_id UUID
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyControlListFactory
|
||||
*/
|
||||
function getObjectTypeAppendedListByCompanyIDAndSuperiorUserID( $company_id, $user_id, $where = null, $order = null ) {
|
||||
if ( $company_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $user_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$hotf = new HierarchyObjectTypeFactory();
|
||||
$hlf = new HierarchyLevelFactory();
|
||||
|
||||
$ph = [
|
||||
'company_id' => TTUUID::castUUID( $company_id ),
|
||||
'user_id' => TTUUID::castUUID( $user_id ),
|
||||
];
|
||||
|
||||
$query = '
|
||||
select a.*,
|
||||
b.object_type_id
|
||||
from ' . $this->getTable() . ' as a
|
||||
LEFT JOIN ' . $hotf->getTable() . ' as b ON a.id = b.hierarchy_control_id
|
||||
LEFT JOIN ' . $hlf->getTable() . ' as c ON a.id = c.hierarchy_control_id
|
||||
where a.company_id = ?
|
||||
AND c.user_id = ?
|
||||
AND a.deleted = 0
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $company_id UUID
|
||||
* @param $filter_data
|
||||
* @param int $limit Limit the number of records returned
|
||||
* @param int $page Page number of records to return for pagination
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyControlListFactory
|
||||
*/
|
||||
function getAPISearchByCompanyIdAndArrayCriteria( $company_id, $filter_data, $limit = null, $page = null, $where = null, $order = null ) {
|
||||
if ( $company_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !is_array( $order ) ) {
|
||||
//Use Filter Data ordering if its set.
|
||||
if ( isset( $filter_data['sort_column'] ) && $filter_data['sort_order'] ) {
|
||||
$order = [ Misc::trimSortPrefix( $filter_data['sort_column'] ) => $filter_data['sort_order'] ];
|
||||
}
|
||||
}
|
||||
|
||||
$additional_order_fields = [];
|
||||
|
||||
$sort_column_aliases = [
|
||||
'superiors' => false, //Don't sort by this.
|
||||
'subordinates' => false, //Don't sort by this.
|
||||
'object_type_display' => false, //Don't sort by this.
|
||||
];
|
||||
|
||||
$order = $this->getColumnsFromAliases( $order, $sort_column_aliases );
|
||||
|
||||
if ( $order == null ) {
|
||||
$order = [ 'name' => 'asc', 'description' => 'asc' ];
|
||||
$strict = false;
|
||||
} else {
|
||||
//Always sort by last name, first name after other columns
|
||||
if ( !isset( $order['name'] ) ) {
|
||||
$order['name'] = 'asc';
|
||||
}
|
||||
$strict = true;
|
||||
}
|
||||
//Debug::Arr($order, 'Order Data:', __FILE__, __LINE__, __METHOD__, 10);
|
||||
//Debug::Arr($filter_data, 'Filter Data:', __FILE__, __LINE__, __METHOD__, 10);
|
||||
|
||||
$uf = new UserFactory();
|
||||
$hlf = new HierarchyLevelFactory();
|
||||
$huf = new HierarchyUserFactory();
|
||||
$hotf = new HierarchyObjectTypeFactory();
|
||||
|
||||
$ph = [
|
||||
'company_id' => TTUUID::castUUID( $company_id ),
|
||||
];
|
||||
|
||||
//Count total users in HierarchyControlFactory factory, so we can disable it when needed. That way it doesn't slow down Hierarchy dropdown boxes.
|
||||
//(select count(*) from '. $hlf->getTable().' as hlf WHERE a.id = hlf.hierarchy_control_id AND hlf.deleted = 0 AND a.deleted = 0) as superiors,
|
||||
//(select count(*) from '. $huf->getTable().' as hulf WHERE a.id = hulf.hierarchy_control_id AND a.deleted = 0 ) as subordinates,
|
||||
// LEFT JOIN ' . $hotf->getTable() . ' as hotf ON ( a.id = hotf.hierarchy_control_id )
|
||||
// LEFT JOIN ' . $hlf->getTable() . ' as hlf ON ( a.id = hlf.hierarchy_control_id AND hlf.deleted = 0 )
|
||||
// LEFT JOIN ' . $huf->getTable() . ' as huf ON ( a.id = huf.hierarchy_control_id )
|
||||
$query = '
|
||||
select a.*,
|
||||
y.first_name as created_by_first_name,
|
||||
y.middle_name as created_by_middle_name,
|
||||
y.last_name as created_by_last_name,
|
||||
z.first_name as updated_by_first_name,
|
||||
z.middle_name as updated_by_middle_name,
|
||||
z.last_name as updated_by_last_name
|
||||
from ' . $this->getTable() . ' as a
|
||||
LEFT JOIN ' . $uf->getTable() . ' as y ON ( a.created_by = y.id AND y.deleted = 0 )
|
||||
LEFT JOIN ' . $uf->getTable() . ' as z ON ( a.updated_by = z.id AND z.deleted = 0 )
|
||||
where a.company_id = ?
|
||||
';
|
||||
|
||||
$query .= ( isset( $filter_data['permission_children_ids'] ) ) ? $this->getWhereClauseSQL( 'a.created_by', $filter_data['permission_children_ids'], 'uuid_list', $ph ) : null;
|
||||
$query .= ( isset( $filter_data['id'] ) ) ? $this->getWhereClauseSQL( 'a.id', $filter_data['id'], 'uuid_list', $ph ) : null;
|
||||
$query .= ( isset( $filter_data['exclude_id'] ) ) ? $this->getWhereClauseSQL( 'a.id', $filter_data['exclude_id'], 'not_uuid_list', $ph ) : null;
|
||||
|
||||
$query .= ( isset( $filter_data['name'] ) ) ? $this->getWhereClauseSQL( 'a.name', $filter_data['name'], 'text', $ph ) : null;
|
||||
$query .= ( isset( $filter_data['description'] ) ) ? $this->getWhereClauseSQL( 'a.description', $filter_data['description'], 'text', $ph ) : null;
|
||||
|
||||
//$query .= ( isset( $filter_data['object_type'] ) ) ? $this->getWhereClauseSQL( 'hotf.object_type_id', $filter_data['object_type'], 'numeric_list', $ph ) : null;
|
||||
//$query .= ( isset( $filter_data['superior_user_id'] ) ) ? $this->getWhereClauseSQL( 'hlf.user_id', $filter_data['superior_user_id'], 'uuid_list', $ph ) : null;
|
||||
//$query .= ( isset( $filter_data['user_id'] ) ) ? $this->getWhereClauseSQL( 'huf.user_id', $filter_data['user_id'], 'uuid_list', $ph ) : null;
|
||||
|
||||
//This is a major optimization as it eliminates the need for LEFT JOINs on these tables, which when dealing with thousands of employees causing millions of records to be returned and having to go through DISTINCT()
|
||||
if ( isset( $filter_data['object_type'] ) ) {
|
||||
$query .= ' AND a.id in ( SELECT DISTINCT hierarchy_control_id FROM ' . $hotf->getTable() . ' as hotf WHERE '. ( $this->getWhereClauseSQL( 'hotf.object_type_id', $filter_data['object_type'], 'numeric_list', $ph, null, false ) ?: '1=1' ) .' )';
|
||||
}
|
||||
if ( isset( $filter_data['superior_user_id'] ) ) {
|
||||
$query .= ' AND a.id in ( SELECT DISTINCT hierarchy_control_id FROM ' . $hlf->getTable() . ' as hlf WHERE '. ( $this->getWhereClauseSQL( 'hlf.user_id', $filter_data['superior_user_id'], 'uuid_list', $ph, null, false ) ?: '1=1' ).' AND hlf.deleted = 0 )';
|
||||
}
|
||||
if ( isset( $filter_data['user_id'] ) ) {
|
||||
$query .= ' AND a.id in ( SELECT DISTINCT hierarchy_control_id FROM ' . $huf->getTable() . ' as huf WHERE '. ( $this->getWhereClauseSQL( 'huf.user_id', $filter_data['user_id'], 'uuid_list', $ph, null, false ) ?: '1=1' ) .' )';
|
||||
}
|
||||
|
||||
$query .= ( isset( $filter_data['created_by'] ) ) ? $this->getWhereClauseSQL( [ 'a.created_by', 'y.first_name', 'y.last_name' ], $filter_data['created_by'], 'user_id_or_name', $ph ) : null;
|
||||
$query .= ( isset( $filter_data['updated_by'] ) ) ? $this->getWhereClauseSQL( [ 'a.updated_by', 'z.first_name', 'z.last_name' ], $filter_data['updated_by'], 'user_id_or_name', $ph ) : null;
|
||||
|
||||
//Don't filter hlf.deleted=0 here as that will not shown hierarchies without any superiors assigned to them. Do the filter on the JOIN instead.
|
||||
$query .= ' AND ( a.deleted = 0 ) ';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order, $strict, $additional_order_fields );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph, $limit, $page );
|
||||
//Debug::Query( $query, $ph, __FILE__, __LINE__, __METHOD__, 10);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
412
classes/modules/hierarchy/HierarchyFactory.class.php
Normal file
412
classes/modules/hierarchy/HierarchyFactory.class.php
Normal file
@ -0,0 +1,412 @@
|
||||
<?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 Modules\Hierarchy
|
||||
*/
|
||||
class HierarchyFactory extends Factory {
|
||||
|
||||
protected $table = 'hierarchy'; //Used for caching purposes only.
|
||||
|
||||
protected $fasttree_obj = null;
|
||||
//protected $tmp_data = array(); //Tmp data.
|
||||
|
||||
/**
|
||||
* @return FastTree|null
|
||||
*/
|
||||
function getFastTreeObject() {
|
||||
|
||||
if ( is_object( $this->fasttree_obj ) ) {
|
||||
return $this->fasttree_obj;
|
||||
} else {
|
||||
global $fast_tree_options;
|
||||
$this->fasttree_obj = new FastTree( $fast_tree_options );
|
||||
|
||||
return $this->fasttree_obj;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|mixed
|
||||
*/
|
||||
function getId() {
|
||||
return $this->getGenericDataValue( 'id' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setId( $value ) {
|
||||
$this->setGenericDataValue( 'id', TTUUID::castUUID( $value ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|mixed
|
||||
*/
|
||||
function getHierarchyControl() {
|
||||
return $this->getGenericDataValue( 'hierarchy_control_id' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setHierarchyControl( $value ) {
|
||||
$this->setGenericDataValue( 'hierarchy_control_id', TTUUID::castUUID( $value ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this for completly editing a row in the tree
|
||||
* Basically "old_id".
|
||||
* @return bool|mixed
|
||||
*/
|
||||
function getPreviousUser() {
|
||||
return $this->getGenericDataValue( 'previous_user_id' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setPreviousUser( $value ) {
|
||||
$this->setGenericDataValue( 'previous_user_id', TTUUID::castUUID( $value ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|mixed
|
||||
*/
|
||||
function getParent() {
|
||||
return $this->getGenericDataValue( 'parent_user_id' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setParent( $value ) {
|
||||
$this->setGenericDataValue( 'parent_user_id', TTUUID::castUUID( $value ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|mixed
|
||||
*/
|
||||
function getUser() {
|
||||
return $this->getGenericDataValue( 'user_id' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setUser( $value ) {
|
||||
$this->setGenericDataValue( 'user_id', TTUUID::castUUID( $value ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getShared() {
|
||||
return $this->fromBool( $this->getGenericDataValue( 'shared' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @return bool
|
||||
*/
|
||||
function setShared( $value ) {
|
||||
return $this->setGenericDataValue( 'shared', $this->toBool( $value ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param bool $ignore_warning
|
||||
* @return bool
|
||||
*/
|
||||
function Validate( $ignore_warning = true ) {
|
||||
|
||||
if ( $this->getUser() == $this->getParent() ) {
|
||||
$this->Validator->isTrue( 'parent',
|
||||
false,
|
||||
TTi18n::gettext( 'User is the same as parent' )
|
||||
);
|
||||
}
|
||||
|
||||
//Make sure both user and parent belong to the same company
|
||||
$ulf = TTnew( 'UserListFactory' ); /** @var UserListFactory $ulf */
|
||||
$ulf->getById( $this->getUser() );
|
||||
$user = $ulf->getIterator()->current();
|
||||
unset( $ulf );
|
||||
|
||||
$ulf = TTnew( 'UserListFactory' ); /** @var UserListFactory $ulf */
|
||||
$ulf->getById( $this->getParent() );
|
||||
$parent = $ulf->getIterator()->current();
|
||||
unset( $ulf );
|
||||
|
||||
|
||||
if ( $this->getUser() == TTUUID::getZeroID() && $this->getParent() == TTUUID::getZeroID() ) {
|
||||
$parent_company_id = TTUUID::getZeroID();
|
||||
$user_company_id = TTUUID::getZeroID();
|
||||
} else if ( $this->getUser() == TTUUID::getZeroID() ) {
|
||||
$parent_company_id = $parent->getCompany();
|
||||
$user_company_id = $parent->getCompany();
|
||||
} else if ( $this->getParent() == TTUUID::getZeroID() ) {
|
||||
$parent_company_id = $user->getCompany();
|
||||
$user_company_id = $user->getCompany();
|
||||
} else {
|
||||
$parent_company_id = $parent->getCompany();
|
||||
$user_company_id = $user->getCompany();
|
||||
}
|
||||
|
||||
if ( TTUUID::isUUID( $user_company_id ) && $user_company_id != TTUUID::getZeroID() && $user_company_id != TTUUID::getNotExistID() && TTUUID::isUUID( $parent_company_id ) && $parent_company_id != TTUUID::getZeroID() && $parent_company_id != TTUUID::getNotExistID() ) {
|
||||
|
||||
Debug::Text( ' User Company: ' . $user_company_id . ' Parent Company: ' . $parent_company_id, __FILE__, __LINE__, __METHOD__, 10 );
|
||||
if ( $user_company_id != $parent_company_id ) {
|
||||
$this->Validator->isTrue( 'parent',
|
||||
false,
|
||||
TTi18n::gettext( 'User or parent has incorrect company' )
|
||||
);
|
||||
}
|
||||
|
||||
$this->getFastTreeObject()->setTree( $this->getHierarchyControl() );
|
||||
$children_arr = $this->getFastTreeObject()->getAllChildren( $this->getUser(), 'RECURSE' );
|
||||
if ( is_array( $children_arr ) ) {
|
||||
$children_ids = array_keys( $children_arr );
|
||||
|
||||
if ( isset( $children_ids ) && is_array( $children_ids ) && in_array( $this->getParent(), $children_ids ) == true ) {
|
||||
Debug::Text( ' Objects cant be re-parented to their own children...', __FILE__, __LINE__, __METHOD__, 10 );
|
||||
$this->Validator->isTrue( 'parent',
|
||||
false,
|
||||
TTi18n::gettext( 'Unable to change parent to a child of itself' )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $reset_data
|
||||
* @param bool $force_lookup
|
||||
* @return bool
|
||||
*/
|
||||
function Save( $reset_data = true, $force_lookup = false ) {
|
||||
$this->StartTransaction();
|
||||
|
||||
$this->getFastTreeObject()->setTree( $this->getHierarchyControl() );
|
||||
|
||||
$retval = true;
|
||||
if ( $this->getId() === false ) {
|
||||
Debug::Text( ' Adding Node ', __FILE__, __LINE__, __METHOD__, 10 );
|
||||
$log_action = 10;
|
||||
|
||||
//Add node to tree
|
||||
if ( $this->getFastTreeObject()->add( $this->getUser(), $this->getParent() ) === false ) {
|
||||
Debug::Text( ' Failed adding Node ', __FILE__, __LINE__, __METHOD__, 10 );
|
||||
|
||||
$this->Validator->isTrue( 'user',
|
||||
false,
|
||||
TTi18n::gettext( 'Employee is already assigned to this hierarchy' )
|
||||
);
|
||||
$retval = false;
|
||||
}
|
||||
} else {
|
||||
Debug::Text( ' Editing Node ', __FILE__, __LINE__, __METHOD__, 10 );
|
||||
$log_action = 20;
|
||||
|
||||
//Edit node.
|
||||
if ( $this->getFastTreeObject()->edit( $this->getPreviousUser(), $this->getUser() ) === true ) {
|
||||
$retval = $this->getFastTreeObject()->move( $this->getUser(), $this->getParent() );
|
||||
} else {
|
||||
Debug::Text( ' Failed editing Node ', __FILE__, __LINE__, __METHOD__, 10 );
|
||||
|
||||
//$retval = FALSE;
|
||||
$retval = true;
|
||||
}
|
||||
}
|
||||
|
||||
TTLog::addEntry( $this->getUser(), $log_action, TTi18n::getText( 'Hierarchy Tree - Control ID' ) . ': ' . $this->getHierarchyControl(), null, $this->getTable() );
|
||||
|
||||
$this->CommitTransaction();
|
||||
//$this->FailTransaction();
|
||||
|
||||
$cache_id = $this->getHierarchyControl() . $this->getParent();
|
||||
$this->removeCache( $cache_id );
|
||||
|
||||
return $retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $disable_audit_log
|
||||
* @return bool
|
||||
*/
|
||||
function Delete( $disable_audit_log = false ) {
|
||||
if ( $this->getUser() !== false ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//This table doesn't have any of these columns, so overload the functions.
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getDeleted() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $bool
|
||||
* @return bool
|
||||
*/
|
||||
function setDeleted( $bool ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getCreatedDate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $epoch EPOCH
|
||||
* @return bool
|
||||
*/
|
||||
function setCreatedDate( $epoch = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getCreatedBy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setCreatedBy( $id = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getUpdatedDate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $epoch EPOCH
|
||||
* @return bool
|
||||
*/
|
||||
function setUpdatedDate( $epoch = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getUpdatedBy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setUpdatedBy( $id = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getDeletedDate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $epoch EPOCH
|
||||
* @return bool
|
||||
*/
|
||||
function setDeletedDate( $epoch = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getDeletedBy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setDeletedBy( $id = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
481
classes/modules/hierarchy/HierarchyLevelFactory.class.php
Normal file
481
classes/modules/hierarchy/HierarchyLevelFactory.class.php
Normal file
@ -0,0 +1,481 @@
|
||||
<?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 Modules\Hierarchy
|
||||
*/
|
||||
class HierarchyLevelFactory extends Factory {
|
||||
protected $table = 'hierarchy_level';
|
||||
protected $pk_sequence_name = 'hierarchy_level_id_seq'; //PK Sequence name
|
||||
|
||||
var $hierarchy_control_obj = null;
|
||||
var $user_obj = null;
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $parent
|
||||
* @return array|null
|
||||
*/
|
||||
function _getFactoryOptions( $name, $parent = null ) {
|
||||
|
||||
$retval = null;
|
||||
switch ( $name ) {
|
||||
case 'columns':
|
||||
$retval = [
|
||||
'-1010-level' => TTi18n::gettext( 'Level' ),
|
||||
'-1020-user' => TTi18n::gettext( 'Superior' ),
|
||||
|
||||
'-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 = [
|
||||
'level',
|
||||
'user',
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
return $retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @return array
|
||||
*/
|
||||
function _getVariableToFunctionMap( $data ) {
|
||||
$variable_function_map = [
|
||||
'id' => 'ID',
|
||||
'hierarchy_control_id' => 'HierarchyControl',
|
||||
'level' => 'Level',
|
||||
'user_id' => 'User',
|
||||
'deleted' => 'Deleted',
|
||||
];
|
||||
|
||||
return $variable_function_map;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|null
|
||||
*/
|
||||
function getUserObject() {
|
||||
if ( is_object( $this->user_obj ) ) {
|
||||
return $this->user_obj;
|
||||
} else {
|
||||
$ulf = TTnew( 'UserListFactory' ); /** @var UserListFactory $ulf */
|
||||
$ulf->getById( $this->getUser() );
|
||||
if ( $ulf->getRecordCount() == 1 ) {
|
||||
$this->user_obj = $ulf->getCurrent();
|
||||
|
||||
return $this->user_obj;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null
|
||||
*/
|
||||
function getHierarchyControlObject() {
|
||||
if ( is_object( $this->hierarchy_control_obj ) ) {
|
||||
return $this->hierarchy_control_obj;
|
||||
} else {
|
||||
$hclf = TTnew( 'HierarchyControlListFactory' ); /** @var HierarchyControlListFactory $hclf */
|
||||
$this->hierarchy_control_obj = $hclf->getById( $this->getHierarchyControl() )->getCurrent();
|
||||
|
||||
return $this->hierarchy_control_obj;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|mixed
|
||||
*/
|
||||
function getHierarchyControl() {
|
||||
return $this->getGenericDataValue( 'hierarchy_control_id' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setHierarchyControl( $value ) {
|
||||
$value = TTUUID::castUUID( $value );
|
||||
|
||||
//This is a sub-class, need to support setting HierachyControlID before its created.
|
||||
return $this->setGenericDataValue( 'hierarchy_control_id', $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|int
|
||||
*/
|
||||
function getLevel() {
|
||||
return (int)$this->getGenericDataValue( 'level' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @return bool
|
||||
*/
|
||||
function setLevel( $value ) {
|
||||
$value = trim( $value );
|
||||
if ( $value <= 0 ) {
|
||||
$value = 1; //1 is the lowest level
|
||||
}
|
||||
if ( $value > 0 ) {
|
||||
return $this->setGenericDataValue( 'level', $value );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|mixed
|
||||
*/
|
||||
function getUser() {
|
||||
return $this->getGenericDataValue( 'user_id' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setUser( $id ) {
|
||||
$id = trim( $id );
|
||||
|
||||
$ulf = TTnew( 'UserListFactory' ); /** @var UserListFactory $ulf */
|
||||
$hllf = TTnew( 'HierarchyLevelListFactory' ); /** @var HierarchyLevelListFactory $hllf */
|
||||
//$hulf = TTnew( 'HierarchyUserListFactory' );
|
||||
|
||||
if ( $this->getHierarchyControl() == false ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Get user object so we can get the users full name to display as an error message.
|
||||
$ulf->getById( $id );
|
||||
|
||||
//Shouldn't allow the same superior to be assigned at multiple levels. Can't check that properly here though, must be done at the Hierarchy Control level?
|
||||
|
||||
|
||||
//Don't allow a level to be set without a superior assigned to it.
|
||||
//$id == 0
|
||||
if (
|
||||
(
|
||||
$this->Validator->isResultSetWithRows( 'user',
|
||||
$ulf->getByID( $id ),
|
||||
TTi18n::gettext( 'No superior defined for level' ) . ' (' . (int)$this->getLevel() . ')'
|
||||
)
|
||||
&&
|
||||
/*
|
||||
//Allow superiors to be assigned as subordinates in the same hierarchy to make it easier to administer hierarchies
|
||||
//that have superiors sharing responsibility.
|
||||
//For example Super1 and Super2 look after 10 subordinates as well as each other. This would require 3 hierarchies normally,
|
||||
//but if we allow Super1 and Super2 to be subordinates in the same hierarchy, it can be done with a single hierarchy.
|
||||
//The key with this though is to have Permission->getPermissionChildren() *not* return the current user, even if they are a subordinates,
|
||||
//as that could cause a conflict with view_own and view_child permissions (as a child would imply view_own)
|
||||
(
|
||||
$ulf->getRecordCount() > 0
|
||||
AND
|
||||
$this->Validator->isNotResultSetWithRows( 'user',
|
||||
$hulf->getByHierarchyControlAndUserId( $this->getHierarchyControl(), $id ),
|
||||
$ulf->getCurrent()->getFullName() .' '. TTi18n::gettext('is assigned as both a superior and subordinate')
|
||||
)
|
||||
)
|
||||
AND
|
||||
*/
|
||||
(
|
||||
$this->Validator->hasError( 'user' ) == false
|
||||
&&
|
||||
$this->Validator->isNotResultSetWithRows( 'user',
|
||||
$hllf->getByHierarchyControlIdAndUserIdAndExcludeId( $this->getHierarchyControl(), $id, $this->getID() ),
|
||||
$ulf->getCurrent()->getFullName() . ' ' . TTi18n::gettext( 'is already assigned as a superior' )
|
||||
)
|
||||
|
||||
)
|
||||
)
|
||||
) {
|
||||
$this->setGenericDataValue( 'user_id', $id );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $hierarchy_level_data
|
||||
* @return array|bool
|
||||
*/
|
||||
static function RemoveDuplicateHierarchyLevels( $hierarchy_level_data ) {
|
||||
if ( !is_array( $hierarchy_level_data ) ) {
|
||||
return false;
|
||||
}
|
||||
Debug::Arr( $hierarchy_level_data, ' aHierarchy Users:', __FILE__, __LINE__, __METHOD__, 10 );
|
||||
|
||||
$tmp_hierarchy_users = [];
|
||||
foreach ( $hierarchy_level_data as $hierarchy_level_id => $hierarchy_level ) {
|
||||
$tmp_hierarchy_users[$hierarchy_level_id] = $hierarchy_level['user_id'];
|
||||
}
|
||||
|
||||
//Remove duplicate superiors.
|
||||
$unique_hierarchy_users = array_unique( $tmp_hierarchy_users );
|
||||
if ( count( $tmp_hierarchy_users ) != count( $unique_hierarchy_users ) ) {
|
||||
//Duplicate superiors found.
|
||||
$diff_hierarchy_users = array_diff_assoc( $tmp_hierarchy_users, $unique_hierarchy_users );
|
||||
Debug::Arr( $diff_hierarchy_users, ' Diff Hierarchy Users:', __FILE__, __LINE__, __METHOD__, 10 );
|
||||
if ( is_array( $diff_hierarchy_users ) ) {
|
||||
foreach ( $diff_hierarchy_users as $diff_hierarchy_key => $diff_hierarchy_value ) {
|
||||
unset( $hierarchy_level_data[$diff_hierarchy_key] );
|
||||
}
|
||||
}
|
||||
}
|
||||
unset( $tmp_hierarchy_users, $unique_hierarchy_users, $diff_hierarchy_users, $diff_hierarchy_key, $diff_hierarchy_value );
|
||||
|
||||
Debug::Arr( $hierarchy_level_data, ' bHierarchy Users:', __FILE__, __LINE__, __METHOD__, 10 );
|
||||
|
||||
return $hierarchy_level_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remaps raw hierarchy_levels so they always start from 1, and have no gaps in them.
|
||||
* Also remove any duplicate superiors from the hierarchy.
|
||||
* @param $hierarchy_level_data
|
||||
* @return bool
|
||||
*/
|
||||
static function ReMapHierarchyLevels( $hierarchy_level_data ) {
|
||||
if ( !is_array( $hierarchy_level_data ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$remapped_hierarchy_levels = false;
|
||||
$tmp_hierarchy_levels = [];
|
||||
foreach ( $hierarchy_level_data as $hierarchy_level ) {
|
||||
$tmp_hierarchy_levels[] = $hierarchy_level['level'];
|
||||
}
|
||||
sort( $tmp_hierarchy_levels );
|
||||
|
||||
$level = 0;
|
||||
$prev_level = false;
|
||||
foreach ( $tmp_hierarchy_levels as $hierarchy_level ) {
|
||||
if ( $prev_level != $hierarchy_level ) {
|
||||
$level++;
|
||||
}
|
||||
|
||||
$remapped_hierarchy_levels[$hierarchy_level] = $level;
|
||||
|
||||
$prev_level = $hierarchy_level;
|
||||
}
|
||||
|
||||
return $remapped_hierarchy_levels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a hierarchy level map array and converts it to a SQL where clause.
|
||||
* @param $hierarchy_level_map
|
||||
* @param string $object_table
|
||||
* @param string $hierarchy_user_table
|
||||
* @param null $type_id_column
|
||||
* @return bool|string
|
||||
*/
|
||||
static function convertHierarchyLevelMapToSQL( $hierarchy_level_map, $object_table = 'a.', $hierarchy_user_table = 'z.', $type_id_column = null ) {
|
||||
/*
|
||||
( z.hierarchy_control_id = 469 AND a.authorization_level = 1 )
|
||||
OR ( z.hierarchy_control_id = 471 AND a.authorization_level = 2 )
|
||||
OR ( z.hierarchy_control_id = 470 AND a.authorization_level = 3 )
|
||||
|
||||
OR
|
||||
|
||||
( z.hierarchy_control_id = 469 AND a.authorization_level = 1 AND a.type_id in (10, 20, 30) )
|
||||
OR ( z.hierarchy_control_id = 471 AND a.authorization_level = 2 AND a.type_id in (10) )
|
||||
OR ( z.hierarchy_control_id = 470 AND a.authorization_level = 3 AND a.type_id in (100) )
|
||||
*/
|
||||
|
||||
if ( is_array( $hierarchy_level_map ) ) {
|
||||
$rf = new RequestFactory();
|
||||
$clause_arr = [];
|
||||
foreach ( $hierarchy_level_map as $hierarchy_data ) {
|
||||
if ( !isset( $hierarchy_data['hierarchy_control_id'] ) || !isset( $hierarchy_data['level'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( isset( $hierarchy_data['last_level'] ) && $hierarchy_data['last_level'] == true ) {
|
||||
$operator = ' >= ';
|
||||
} else {
|
||||
$operator = ' = ';
|
||||
}
|
||||
|
||||
$object_type_clause = null;
|
||||
if ( $type_id_column != '' && isset( $hierarchy_data['object_type_id'] ) && count( $hierarchy_data['object_type_id'] ) > 0 ) {
|
||||
$hierarchy_data['object_type_id'] = $rf->getTypeIdFromHierarchyTypeId( $hierarchy_data['object_type_id'] );
|
||||
$object_type_clause = ' AND ' . $type_id_column . ' in (' . implode( ',', $hierarchy_data['object_type_id'] ) . ')';
|
||||
}
|
||||
$clause_arr[] = '( ' . $hierarchy_user_table . 'hierarchy_control_id = \'' . TTUUID::castUUID( $hierarchy_data['hierarchy_control_id'] ) . '\' AND ' . $object_table . 'authorization_level ' . $operator . ' ' . (int)$hierarchy_data['level'] . $object_type_clause . ' )';
|
||||
}
|
||||
$retval = implode( ' OR ', $clause_arr );
|
||||
|
||||
//Debug::Text(' Hierarchy Filter SQL: '. $retval, __FILE__, __LINE__, __METHOD__, 10);
|
||||
return $retval;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
* @return array
|
||||
*/
|
||||
function getObjectAsArray( $include_columns = null ) {
|
||||
$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 ) {
|
||||
default:
|
||||
if ( method_exists( $this, $function ) ) {
|
||||
$data[$variable] = $this->$function();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->getCreatedAndUpdatedColumns( $data, $include_columns );
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $log_action
|
||||
* @return bool
|
||||
*/
|
||||
function addLog( $log_action ) {
|
||||
$u_obj = $this->getUserObject();
|
||||
if ( is_object( $u_obj ) ) {
|
||||
return TTLog::addEntry( $this->getHierarchyControl(), $log_action, TTi18n::getText( 'Superior' ) . ': ' . $u_obj->getFullName() . ' ' . TTi18n::getText( 'Level' ) . ': ' . $this->getLevel(), null, $this->getTable(), $this );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $ignore_warning
|
||||
* @return bool
|
||||
*/
|
||||
function Validate( $ignore_warning = true ) {
|
||||
//
|
||||
// BELOW: Validation code moved from set*() functions.
|
||||
//
|
||||
// Hierarchy Control
|
||||
$hclf = TTnew( 'HierarchyControlListFactory' ); /** @var HierarchyControlListFactory $hclf */
|
||||
$this->Validator->isResultSetWithRows( 'hierarchy_control_id',
|
||||
$hclf->getByID( $this->getHierarchyControl() ),
|
||||
TTi18n::gettext( 'Invalid Hierarchy Control' )
|
||||
);
|
||||
// Level
|
||||
if ( $this->getLevel() !== false && $this->getLevel() > 0 ) {
|
||||
$this->Validator->isNumeric( 'level',
|
||||
$this->getLevel(),
|
||||
TTi18n::gettext( 'Level is invalid' )
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// ABOVE: Validation code moved from set*() functions.
|
||||
//
|
||||
|
||||
|
||||
if ( $this->getUser() === false || TTUUID::isUUID( $this->getUser() ) == false ) {
|
||||
$this->Validator->isTrue( 'user_id',
|
||||
false,
|
||||
TTi18n::gettext( 'A superior must be specified' )
|
||||
);
|
||||
}
|
||||
|
||||
if ( $this->getDeleted() == true ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
590
classes/modules/hierarchy/HierarchyLevelListFactory.class.php
Normal file
590
classes/modules/hierarchy/HierarchyLevelListFactory.class.php
Normal file
@ -0,0 +1,590 @@
|
||||
<?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 Modules\Hierarchy
|
||||
*/
|
||||
class HierarchyLevelListFactory extends HierarchyLevelFactory implements IteratorAggregate {
|
||||
|
||||
/**
|
||||
* @param int $limit Limit the number of records returned
|
||||
* @param int $page Page number of records to return for pagination
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return $this
|
||||
*/
|
||||
function getAll( $limit = null, $page = null, $where = null, $order = null ) {
|
||||
$query = '
|
||||
select *
|
||||
from ' . $this->getTable() . '
|
||||
where deleted = 0
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, null, $limit, $page );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyLevelListFactory
|
||||
*/
|
||||
function getById( $id, $where = null, $order = null ) {
|
||||
if ( $id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ph = [
|
||||
'id' => TTUUID::castUUID( $id ),
|
||||
];
|
||||
|
||||
|
||||
$query = '
|
||||
select *
|
||||
from ' . $this->getTable() . '
|
||||
where id = ?
|
||||
AND deleted = 0
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $company_id UUID
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyLevelListFactory
|
||||
*/
|
||||
function getByCompanyId( $company_id, $where = null, $order = null ) {
|
||||
if ( $company_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$hcf = new HierarchyControlFactory();
|
||||
|
||||
$ph = [
|
||||
'company_id' => TTUUID::castUUID( $company_id ),
|
||||
];
|
||||
|
||||
$query = '
|
||||
select a.*
|
||||
from ' . $this->getTable() . ' as a
|
||||
LEFT JOIN ' . $hcf->getTable() . ' as b ON a.hierarchy_control_id = b.id
|
||||
where b.company_id = ?
|
||||
AND a.deleted = 0
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param string $company_id UUID
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyLevelListFactory
|
||||
*/
|
||||
function getByIdAndCompanyId( $id, $company_id, $where = null, $order = null ) {
|
||||
if ( $id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $company_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$hcf = new HierarchyControlFactory();
|
||||
|
||||
$ph = [
|
||||
'id' => TTUUID::castUUID( $id ),
|
||||
'company_id' => TTUUID::castUUID( $company_id ),
|
||||
];
|
||||
|
||||
$query = '
|
||||
select a.*
|
||||
from ' . $this->getTable() . ' as a
|
||||
LEFT JOIN ' . $hcf->getTable() . ' as b ON a.hierarchy_control_id = b.id
|
||||
where a.id = ?
|
||||
AND b.company_id = ?
|
||||
AND a.deleted = 0
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyLevelListFactory
|
||||
*/
|
||||
function getByHierarchyControlId( $id, $where = null, $order = null ) {
|
||||
if ( $id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$strict_order = true;
|
||||
if ( $order == null ) {
|
||||
$order = [ 'level' => 'asc', 'user_id' => 'asc' ];
|
||||
$strict_order = false;
|
||||
}
|
||||
|
||||
$ph = [
|
||||
'id' => TTUUID::castUUID( $id ),
|
||||
];
|
||||
|
||||
|
||||
$query = '
|
||||
select *
|
||||
from ' . $this->getTable() . '
|
||||
where hierarchy_control_id = ?
|
||||
AND deleted = 0
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order, $strict_order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param string $user_id UUID
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyLevelListFactory
|
||||
*/
|
||||
function getByHierarchyControlIdAndUserId( $id, $user_id, $where = null, $order = null ) {
|
||||
if ( $id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$strict_order = true;
|
||||
if ( $order == null ) {
|
||||
$order = [ 'level' => 'asc', 'user_id' => 'asc' ];
|
||||
$strict_order = false;
|
||||
}
|
||||
|
||||
$ph = [
|
||||
'id' => TTUUID::castUUID( $id ),
|
||||
'user_id' => TTUUID::castUUID( $user_id ),
|
||||
];
|
||||
|
||||
$query = '
|
||||
select *
|
||||
from ' . $this->getTable() . '
|
||||
where hierarchy_control_id = ?
|
||||
AND user_id = ?
|
||||
AND deleted = 0
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order, $strict_order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param string $user_id UUID
|
||||
* @param string $exclude_id UUID
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyLevelListFactory
|
||||
*/
|
||||
function getByHierarchyControlIdAndUserIdAndExcludeID( $id, $user_id, $exclude_id, $where = null, $order = null ) {
|
||||
if ( $id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$strict_order = true;
|
||||
if ( $order == null ) {
|
||||
$order = [ 'level' => 'asc', 'user_id' => 'asc' ];
|
||||
$strict_order = false;
|
||||
}
|
||||
|
||||
$ph = [
|
||||
'id' => TTUUID::castUUID( $id ),
|
||||
'user_id' => TTUUID::castUUID( $user_id ),
|
||||
'exclude_id' => TTUUID::castUUID( $exclude_id ),
|
||||
];
|
||||
|
||||
$query = '
|
||||
select *
|
||||
from ' . $this->getTable() . '
|
||||
where hierarchy_control_id = ?
|
||||
AND user_id = ?
|
||||
AND id != ?
|
||||
AND deleted = 0
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order, $strict_order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param string $user_id UUID
|
||||
* @return bool
|
||||
*/
|
||||
function getLevelsByHierarchyControlIdAndUserId( $id, $user_id ) {
|
||||
if ( $id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $user_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ph = [
|
||||
'id' => TTUUID::castUUID( $id ),
|
||||
'idb' => $id,
|
||||
'user_id' => TTUUID::castUUID( $user_id ),
|
||||
];
|
||||
|
||||
$query = '
|
||||
select distinct(level)
|
||||
from ' . $this->getTable() . '
|
||||
where hierarchy_control_id = ?
|
||||
AND level >= (
|
||||
select level
|
||||
from ' . $this->getTable() . '
|
||||
where hierarchy_control_id = ?
|
||||
AND user_id = ?
|
||||
AND deleted = 0
|
||||
LIMIT 1
|
||||
)
|
||||
AND deleted = 0
|
||||
ORDER BY level ASC
|
||||
';
|
||||
|
||||
$retarr = $this->db->GetCol( $query, $ph );
|
||||
|
||||
return $retarr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user_id UUID
|
||||
* @param int $object_type_id
|
||||
* @return bool|HierarchyLevelListFactory
|
||||
*/
|
||||
function getByUserIdAndObjectTypeID( $user_id, $object_type_id = 50 ) { //50 = Requests
|
||||
|
||||
if ( $user_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $object_type_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$hotf = new HierarchyObjectTypeFactory();
|
||||
|
||||
$ph = [
|
||||
'user_id' => TTUUID::castUUID( $user_id ),
|
||||
];
|
||||
|
||||
$query = '
|
||||
select a.*
|
||||
from ' . $this->getTable() . ' as a
|
||||
LEFT JOIN ' . $hotf->getTable() . ' as b ON a.hierarchy_control_id = b.hierarchy_control_id
|
||||
where a.user_id = ?
|
||||
AND b.object_type_id in (' . $this->getListSQL( $object_type_id, $ph, 'int' ) . ')
|
||||
AND ( a.deleted = 0 )
|
||||
';
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
//Debug::Query( $query, $ph, __FILE__, __LINE__, __METHOD__, 10);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $company_id UUID
|
||||
* @param string $user_id UUID
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyLevelListFactory
|
||||
*/
|
||||
function getObjectTypeAndHierarchyAppendedListByCompanyIDAndUserID( $company_id, $user_id, $where = null, $order = null ) {
|
||||
if ( $company_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $user_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$additional_order_fields = [ 'object_type_id', 'hierarchy_control_name' ];
|
||||
if ( $order == null ) {
|
||||
$order = [ 'object_type_id' => 'asc', 'hierarchy_control_name' => 'asc', 'level' => 'asc', 'user_id' => 'asc' ];
|
||||
$strict = false;
|
||||
} else {
|
||||
$strict = true;
|
||||
}
|
||||
|
||||
$hcf = new HierarchyControlFactory();
|
||||
$hotf = new HierarchyObjectTypeFactory();
|
||||
$huf = new HierarchyUserFactory();
|
||||
|
||||
$ph = [
|
||||
'company_id' => TTUUID::castUUID( $company_id ),
|
||||
'user_id' => TTUUID::castUUID( $user_id ),
|
||||
];
|
||||
|
||||
$query = '
|
||||
select hlf.*,
|
||||
hcf.name as hierarchy_control_name,
|
||||
hotf.object_type_id
|
||||
from ' . $this->getTable() . ' as hlf
|
||||
LEFT JOIN ' . $hcf->getTable() . ' as hcf ON hcf.id = hlf.hierarchy_control_id
|
||||
LEFT JOIN ' . $hotf->getTable() . ' as hotf ON hcf.id = hotf.hierarchy_control_id
|
||||
LEFT JOIN ' . $huf->getTable() . ' as huf ON hcf.id = huf.hierarchy_control_id
|
||||
where hcf.company_id = ?
|
||||
AND huf.user_id = ?
|
||||
AND ( hlf.deleted = 0 AND hcf.deleted = 0 )
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order, $strict, $additional_order_fields );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user_id UUID
|
||||
* @param int $object_type_id
|
||||
* @return array|bool
|
||||
*/
|
||||
function getLevelsAndHierarchyControlIDsByUserIdAndObjectTypeID( $user_id, $object_type_id = 50 ) {
|
||||
if ( $user_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $object_type_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$hotf = new HierarchyObjectTypeFactory();
|
||||
$hcf = new HierarchyControlFactory();
|
||||
|
||||
$ph = [
|
||||
'user_id' => TTUUID::castUUID( $user_id ),
|
||||
];
|
||||
|
||||
//Include object_type_ids for each hierarchy_control_id, because we need to do additional filtering by hierarchy_control_id, level, object_type_ids
|
||||
$query = '
|
||||
select
|
||||
x.hierarchy_control_id as hierarchy_control_id,
|
||||
x.level as level,
|
||||
z.object_type_id as object_type_id
|
||||
from ' . $this->getTable() . ' as x,
|
||||
' . $hcf->getTable() . ' as y,
|
||||
(
|
||||
select a.hierarchy_control_id, a.level, b.object_type_id
|
||||
from ' . $this->getTable() . ' as a
|
||||
LEFT JOIN ' . $hotf->getTable() . ' as b ON a.hierarchy_control_id = b.hierarchy_control_id
|
||||
where a.user_id = ?
|
||||
AND b.object_type_id in (' . $this->getListSQL( $object_type_id, $ph, 'int' ) . ')
|
||||
AND a.deleted = 0
|
||||
) as z
|
||||
where
|
||||
x.hierarchy_control_id = y.id
|
||||
AND x.hierarchy_control_id = z.hierarchy_control_id
|
||||
AND x.level >= z.level
|
||||
AND ( x.deleted = 0 AND y.deleted = 0 )
|
||||
ORDER BY x.level asc
|
||||
';
|
||||
|
||||
$rs = $this->ExecuteSQL( $query, $ph );
|
||||
//Debug::Text(' Rows: '. $rs->RecordCount(), __FILE__, __LINE__, __METHOD__, 10);
|
||||
|
||||
$hierarchy_to_level_map = [];
|
||||
$hierarchy_to_object_type_map = [];
|
||||
if ( $rs->RecordCount() > 0 ) {
|
||||
foreach ( $rs as $row ) {
|
||||
$hierarchy_to_level_map[$row['hierarchy_control_id']][] = (int)$row['level'];
|
||||
$hierarchy_to_object_type_map[$row['hierarchy_control_id']][] = (int)$row['object_type_id'];
|
||||
}
|
||||
//Debug::Arr($hierarchy_to_level_map, ' Hierarchy To Level Map: ', __FILE__, __LINE__, __METHOD__, 10);
|
||||
//Debug::Arr($hierarchy_to_object_type_map, ' Hierarchy To Object Type Map: ', __FILE__, __LINE__, __METHOD__, 10);
|
||||
|
||||
//Take each hierarchy_control and level element and convert it into virtual levels, where the first level (regardless of what it is in the actual hierarchy)
|
||||
//is always virtual_level 1, so the supervisor can see all necessary requests that are waiting on them at level 1. Dropping down any other levels
|
||||
//is looking and requests waiting on OTHER supervisors.
|
||||
//Track the last level for each hierarchy, so we know when to include all requests that may be higher than that level, so if the hierarchy is changed
|
||||
//and levels are taken out, requests don't sit in limbo forever.
|
||||
$retarr = [];
|
||||
foreach ( $hierarchy_to_level_map as $hierarchy_control_id => $level_arr ) {
|
||||
//Unique each level arr so we don't start creating extra virtual levels when multiple superiors are at the same level.
|
||||
//This fixes a bug where if there were 5 superiors at the same level, 5 virtual levels would be created.
|
||||
$level_arr = array_unique( $level_arr );
|
||||
|
||||
$i = 1;
|
||||
foreach ( $level_arr as $level ) {
|
||||
if ( $level == end( $hierarchy_to_level_map[$hierarchy_control_id] ) ) {
|
||||
$last_level = true;
|
||||
} else {
|
||||
$last_level = false;
|
||||
}
|
||||
|
||||
$retarr[$i][] = [ 'hierarchy_control_id' => TTUUID::castUUID( $hierarchy_control_id ), 'level' => $level, 'last_level' => $last_level, 'object_type_id' => array_unique( $hierarchy_to_object_type_map[$hierarchy_control_id] ) ];
|
||||
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
//Debug::Arr($retarr, ' Final Hierarchy To Level Map: ', __FILE__, __LINE__, __METHOD__, 10);
|
||||
return $retarr;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $company_id UUID
|
||||
* @param $filter_data
|
||||
* @param int $limit Limit the number of records returned
|
||||
* @param int $page Page number of records to return for pagination
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyLevelListFactory
|
||||
*/
|
||||
function getAPISearchByCompanyIdAndArrayCriteria( $company_id, $filter_data, $limit = null, $page = null, $where = null, $order = null ) {
|
||||
if ( $company_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !is_array( $order ) ) {
|
||||
//Use Filter Data ordering if its set.
|
||||
if ( isset( $filter_data['sort_column'] ) && $filter_data['sort_order'] ) {
|
||||
$order = [ Misc::trimSortPrefix( $filter_data['sort_column'] ) => $filter_data['sort_order'] ];
|
||||
}
|
||||
}
|
||||
|
||||
$additional_order_fields = [];
|
||||
|
||||
$sort_column_aliases = [
|
||||
'user' => false, //Don't sort by this.
|
||||
];
|
||||
|
||||
$order = $this->getColumnsFromAliases( $order, $sort_column_aliases );
|
||||
|
||||
if ( $order == null ) {
|
||||
$order = [ 'level' => 'asc' ];
|
||||
$strict = false;
|
||||
} else {
|
||||
//Always sort by last name, first name after other columns
|
||||
if ( !isset( $order['level'] ) ) {
|
||||
$order['level'] = 'asc';
|
||||
}
|
||||
$strict = true;
|
||||
}
|
||||
//Debug::Arr($order, 'Order Data:', __FILE__, __LINE__, __METHOD__, 10);
|
||||
//Debug::Arr($filter_data, 'Filter Data:', __FILE__, __LINE__, __METHOD__, 10);
|
||||
|
||||
$uf = new UserFactory();
|
||||
$hcf = new HierarchyControlFactory();
|
||||
|
||||
$ph = [
|
||||
'company_id' => TTUUID::castUUID( $company_id ),
|
||||
];
|
||||
|
||||
$query = '
|
||||
select a.*,
|
||||
y.first_name as created_by_first_name,
|
||||
y.middle_name as created_by_middle_name,
|
||||
y.last_name as created_by_last_name,
|
||||
z.first_name as updated_by_first_name,
|
||||
z.middle_name as updated_by_middle_name,
|
||||
z.last_name as updated_by_last_name
|
||||
from ' . $this->getTable() . ' as a
|
||||
LEFT JOIN ' . $hcf->getTable() . ' as b ON ( a.hierarchy_control_id = b.id AND b.deleted = 0 )
|
||||
LEFT JOIN ' . $uf->getTable() . ' as y ON ( a.created_by = y.id AND y.deleted = 0 )
|
||||
LEFT JOIN ' . $uf->getTable() . ' as z ON ( a.updated_by = z.id AND z.deleted = 0 )
|
||||
where b.company_id = ?
|
||||
';
|
||||
|
||||
$query .= ( isset( $filter_data['permission_children_ids'] ) ) ? $this->getWhereClauseSQL( 'a.created_by', $filter_data['permission_children_ids'], 'uuid_list', $ph ) : null;
|
||||
$query .= ( isset( $filter_data['id'] ) ) ? $this->getWhereClauseSQL( 'a.id', $filter_data['id'], 'uuid_list', $ph ) : null;
|
||||
$query .= ( isset( $filter_data['exclude_id'] ) ) ? $this->getWhereClauseSQL( 'a.id', $filter_data['exclude_id'], 'not_uuid_list', $ph ) : null;
|
||||
|
||||
$query .= ( isset( $filter_data['hierarchy_control_id'] ) ) ? $this->getWhereClauseSQL( 'a.hierarchy_control_id', $filter_data['hierarchy_control_id'], 'uuid_list', $ph ) : null;
|
||||
|
||||
$query .= ( isset( $filter_data['created_by'] ) ) ? $this->getWhereClauseSQL( [ 'a.created_by', 'y.first_name', 'y.last_name' ], $filter_data['created_by'], 'user_id_or_name', $ph ) : null;
|
||||
$query .= ( isset( $filter_data['updated_by'] ) ) ? $this->getWhereClauseSQL( [ 'a.updated_by', 'z.first_name', 'z.last_name' ], $filter_data['updated_by'], 'user_id_or_name', $ph ) : null;
|
||||
|
||||
$query .= ' AND a.deleted = 0 ';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order, $strict, $additional_order_fields );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph, $limit, $page );
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
876
classes/modules/hierarchy/HierarchyListFactory.class.php
Normal file
876
classes/modules/hierarchy/HierarchyListFactory.class.php
Normal file
@ -0,0 +1,876 @@
|
||||
<?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 Modules\Hierarchy
|
||||
*/
|
||||
class HierarchyListFactory extends HierarchyFactory implements IteratorAggregate {
|
||||
|
||||
protected $fasttree_obj = null;
|
||||
|
||||
/**
|
||||
* @return FastTree|null
|
||||
*/
|
||||
function getFastTreeObject() {
|
||||
|
||||
if ( is_object( $this->fasttree_obj ) ) {
|
||||
return $this->fasttree_obj;
|
||||
} else {
|
||||
global $fast_tree_options;
|
||||
$this->fasttree_obj = new FastTree( $fast_tree_options );
|
||||
|
||||
return $this->fasttree_obj;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $tree_id UUID
|
||||
* @param string $user_id UUID
|
||||
* @param bool $recurse
|
||||
* @return array|bool
|
||||
*/
|
||||
function getChildLevelIdArrayByHierarchyControlIdAndUserId( $tree_id, $user_id, $recurse = false ) {
|
||||
//This only gets the immediate children
|
||||
//Used for authorization list when they just want to see immediate children.
|
||||
|
||||
if ( $tree_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $user_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->getFastTreeObject()->setTree( $tree_id );
|
||||
|
||||
//Get current level IDs first, then get children of all of them.
|
||||
$ids = $this->getCurrentLevelIdArrayByHierarchyControlIdAndUserId( $tree_id, $user_id, false );
|
||||
//Debug::Arr($ids, ' zzNodes at the same level: User ID: '. $user_id, __FILE__, __LINE__, __METHOD__, 10);
|
||||
|
||||
if ( $ids === false ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$retarr = [];
|
||||
foreach ( $ids as $id ) {
|
||||
//Debug::Text(' Getting Children of ID: '. $id, __FILE__, __LINE__, __METHOD__, 10);
|
||||
$children = $this->getFastTreeObject()->getAllChildren( $id, $recurse );
|
||||
//Debug::Arr($children, ' ccNodes at the same level', __FILE__, __LINE__, __METHOD__, 10);
|
||||
|
||||
if ( $children === false ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//Remove $user_id from final array, otherwise permission checks will think the user doing the permission
|
||||
//check is a child of themself, preventing users from view/editing children but not themselves.
|
||||
/*
|
||||
if ( isset($children[$user_id]) ) {
|
||||
unset($children[$user_id]);
|
||||
}
|
||||
*/
|
||||
$child_ids = array_keys( $children );
|
||||
|
||||
$retarr = array_merge( $retarr, $child_ids );
|
||||
unset( $child_ids );
|
||||
}
|
||||
|
||||
return $retarr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $tree_id UUID
|
||||
* @param string $user_id UUID
|
||||
* @return array|bool
|
||||
*/
|
||||
function getAllParentLevelIdArrayByHierarchyControlIdAndUserId( $tree_id, $user_id ) {
|
||||
//This only gets the immediate parents
|
||||
if ( $tree_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $user_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->getFastTreeObject()->setTree( $tree_id );
|
||||
|
||||
$ids = $this->getFastTreeObject()->getAllParents( $user_id );
|
||||
//Debug::Arr($ids, ' Parent Nodes', __FILE__, __LINE__, __METHOD__, 10);
|
||||
|
||||
//Find out if any of the parents are shared.
|
||||
$hslf = new HierarchyShareListFactory();
|
||||
|
||||
$retarr = [];
|
||||
foreach ( $ids as $id ) {
|
||||
|
||||
$hierarchy_share = $hslf->getByHierarchyControlIdAndUserId( $tree_id, $id )->getCurrent()->isNew();
|
||||
|
||||
if ( $hierarchy_share === false ) {
|
||||
//Debug::Text(' Node IS shared: '. $id, __FILE__, __LINE__, __METHOD__, 10);
|
||||
|
||||
//Get current level IDs
|
||||
$current_level_ids = $this->getCurrentLevelIdArrayByHierarchyControlIdAndUserId( $tree_id, $id );
|
||||
$retarr = array_merge( $retarr, $current_level_ids );
|
||||
unset( $current_level_ids );
|
||||
} else {
|
||||
//Debug::Text(' Node isnt shared: '. $id, __FILE__, __LINE__, __METHOD__, 10);
|
||||
$retarr[] = TTUUID::castUUID( $id );
|
||||
}
|
||||
}
|
||||
|
||||
//Debug::Arr($retarr, ' Final Parent Nodes including shared', __FILE__, __LINE__, __METHOD__, 10);
|
||||
return array_unique( $retarr );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param string $user_id UUID
|
||||
* @return bool
|
||||
*/
|
||||
function getLevelsByHierarchyControlIdAndUserId( $id, $user_id ) {
|
||||
if ( $id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $user_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$hllf = new HierarchyLevelListFactory();
|
||||
|
||||
return $hllf->getLevelsByHierarchyControlIdAndUserId( $id, $user_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $tree_id UUID
|
||||
* @param string $user_id UUID
|
||||
* @return array|bool
|
||||
*/
|
||||
function getByHierarchyControlIdAndUserId( $tree_id, $user_id ) {
|
||||
if ( $tree_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $user_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->getFastTreeObject()->setTree( $tree_id );
|
||||
|
||||
$node = $this->getFastTreeObject()->getNode( $user_id );
|
||||
|
||||
if ( $node === false ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ulf = new UserListFactory();
|
||||
$user_obj = $ulf->getById( $node['object_id'] )->getCurrent();
|
||||
|
||||
$hslf = new HierarchyShareListFactory();
|
||||
$hierarchy_share = $hslf->getByHierarchyControlIdAndUserId( $tree_id, $user_id )->getCurrent()->isNew();
|
||||
|
||||
if ( $hierarchy_share === false ) {
|
||||
$shared = true;
|
||||
} else {
|
||||
$shared = false;
|
||||
}
|
||||
|
||||
$retarr = [
|
||||
'id' => $node['object_id'],
|
||||
'parent_id' => $node['parent_id'],
|
||||
'name' => $user_obj->getFullName(),
|
||||
'level' => $node['level'],
|
||||
'shared' => $shared,
|
||||
];
|
||||
|
||||
return $retarr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $tree_id UUID
|
||||
* @return array|bool
|
||||
*/
|
||||
function getByHierarchyControlId( $tree_id ) {
|
||||
if ( $tree_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->getFastTreeObject()->setTree( $tree_id );
|
||||
|
||||
$children = $this->getFastTreeObject()->getAllChildren( null, 'RECURSE' );
|
||||
|
||||
$ulf = new UserListFactory();
|
||||
$hslf = new HierarchyShareListFactory();
|
||||
$hslf->getByHierarchyControlId( $tree_id );
|
||||
$shared_user_ids = [];
|
||||
foreach ( $hslf as $hierarchy_share ) {
|
||||
$shared_user_ids[] = $hierarchy_share->getUser();
|
||||
}
|
||||
|
||||
if ( $children !== false ) {
|
||||
|
||||
$nodes = [];
|
||||
foreach ( $children as $object_id => $level ) {
|
||||
|
||||
if ( $object_id !== TTUUID::getZeroID() ) {
|
||||
$user_obj = $ulf->getById( $object_id )->getCurrent();
|
||||
|
||||
$shared = false;
|
||||
if ( in_array( $object_id, $shared_user_ids ) === true ) {
|
||||
$shared = true;
|
||||
}
|
||||
|
||||
$nodes[] = [
|
||||
'id' => $object_id,
|
||||
'name' => $user_obj->getFullName(),
|
||||
'level' => $level,
|
||||
'shared' => $shared,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $nodes ) == false ) {
|
||||
return $nodes;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param string $user_id UUID
|
||||
* @param int $level
|
||||
* @return array|bool
|
||||
*/
|
||||
function getByHierarchyControlIdAndUserIdAndLevel( $id, $user_id, $level = 1 ) {
|
||||
if ( $id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $user_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !is_numeric( $level ) ) {
|
||||
return false;
|
||||
}
|
||||
$min_level = ( $level - 1 );
|
||||
if ( $min_level <= 1 ) {
|
||||
$min_level = 1;
|
||||
}
|
||||
$max_level = ( $level + 1 );
|
||||
Debug::Text( ' User ID: ' . $user_id . ' Level: ' . $level, __FILE__, __LINE__, __METHOD__, 10 );
|
||||
|
||||
$retarr = [ 'current_level' => [], 'parent_level' => [], 'child_level' => [] ];
|
||||
|
||||
$hlf = new HierarchyLevelFactory();
|
||||
$huf = new HierarchyUserFactory();
|
||||
|
||||
$ph = [
|
||||
'id' => TTUUID::castUUID( $id ),
|
||||
'idb' => $id,
|
||||
'idc' => $id,
|
||||
'min_level' => $min_level,
|
||||
'max_level' => $max_level,
|
||||
'user_id' => TTUUID::castUUID( $user_id ),
|
||||
];
|
||||
|
||||
$query = '
|
||||
select * from (
|
||||
select a.level,
|
||||
a.user_id
|
||||
from ' . $hlf->getTable() . ' as a
|
||||
where a.hierarchy_control_id = ?
|
||||
AND a.deleted = 0
|
||||
|
||||
UNION ALL
|
||||
|
||||
select (select max(level)+1 from ' . $hlf->getTable() . ' as z where z.hierarchy_control_id = ? AND z.deleted = 0 ) as level,
|
||||
b.user_id
|
||||
from ' . $huf->getTable() . ' as b
|
||||
where b.hierarchy_control_id = ?
|
||||
) as tmp
|
||||
WHERE level >= ?
|
||||
AND level <= ?
|
||||
ORDER BY user_id = ? DESC, level ASC, user_id ASC
|
||||
';
|
||||
|
||||
|
||||
//Debug::Text(' Query: '. $query, __FILE__, __LINE__, __METHOD__, 10);
|
||||
|
||||
$rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
if ( $rs->RecordCount() > 0 ) {
|
||||
|
||||
//The first row should belong to the user_id that was passed.
|
||||
$current_level = false;
|
||||
$i = 0;
|
||||
foreach ( $rs as $row ) {
|
||||
if ( $i == 0 && $user_id == $row['user_id'] ) {
|
||||
//First row.
|
||||
$current_level = $row['level'];
|
||||
$retarr['current_level'][] = $row['user_id'];
|
||||
} else if ( $i > 0 && $row['level'] < $current_level ) {
|
||||
$retarr['parent_level'][] = $row['user_id'];
|
||||
} else if ( $i > 0 && $row['level'] > $current_level ) {
|
||||
$retarr['child_level'][] = $row['user_id'];
|
||||
} else {
|
||||
//Debug::Text(' User not in hierarchy...', __FILE__, __LINE__, __METHOD__, 10);
|
||||
return false;
|
||||
}
|
||||
|
||||
$i++;
|
||||
}
|
||||
|
||||
$retarr['current_level'] = array_unique( $retarr['current_level'] );
|
||||
$retarr['parent_level'] = array_unique( $retarr['parent_level'] );
|
||||
$retarr['child_level'] = array_unique( $retarr['child_level'] );
|
||||
|
||||
//Debug::Arr($retarr, ' aChildren of User: '. $user_id .' At Level: '. $level, __FILE__, __LINE__, __METHOD__, 10);
|
||||
|
||||
return $retarr;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user_id UUID
|
||||
* @param int $object_type_id
|
||||
* @param int $level
|
||||
* @param bool $recursive
|
||||
* @return array|bool
|
||||
*/
|
||||
function getByUserIdAndObjectTypeIDAndLevel( $user_id, $object_type_id, $level = 1, $recursive = true ) {
|
||||
if ( $user_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !is_numeric( $level ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$min_level = ( $level - 1 );
|
||||
if ( $min_level <= 0 ) {
|
||||
$min_level = 0;
|
||||
}
|
||||
|
||||
//This should have two modes, one where it returns just the immediate child level, and one that returns all children "recursively".
|
||||
if ( $recursive == true ) {
|
||||
$max_level = 99;
|
||||
} else {
|
||||
$max_level = ( $level + 1 );
|
||||
}
|
||||
Debug::Text( ' User ID: ' . $user_id . ' Object Type ID: ' . $object_type_id . ' Level: ' . $level . ' Min Level: ' . $min_level . ' Max Level: ' . $max_level, __FILE__, __LINE__, __METHOD__, 10 );
|
||||
|
||||
$retarr = [ 'current_level' => [], 'parent_level' => [], 'child_level' => [] ];
|
||||
|
||||
$hcf = new HierarchyControlFactory();
|
||||
$hlf = new HierarchyLevelFactory();
|
||||
$huf = new HierarchyUserFactory();
|
||||
$hotf = new HierarchyObjectTypeFactory();
|
||||
|
||||
$ph = [];
|
||||
|
||||
//UNION two queries together, the first query gets all superiors, one level above, and all levels below.
|
||||
//The 2nd query gets all subordinates.
|
||||
$query = '
|
||||
select * from (
|
||||
select x.hierarchy_control_id,
|
||||
x.user_id,
|
||||
x.level,
|
||||
0 as is_subordinate
|
||||
from ' . $hlf->getTable() . ' as x
|
||||
LEFT JOIN ' . $hcf->getTable() . ' as y ON x.hierarchy_control_id = y.id
|
||||
LEFT JOIN ' . $hotf->getTable() . ' as y2 ON x.hierarchy_control_id = y2.hierarchy_control_id
|
||||
LEFT JOIN ' . $hlf->getTable() . ' as z ON x.hierarchy_control_id = z.hierarchy_control_id AND z.user_id = \'' . TTUUID::castUUID( $user_id ) . '\'
|
||||
where
|
||||
y2.object_type_id in (' . $this->getListSQL( $object_type_id, $ph, 'int' ) . ')
|
||||
AND x.level >= z.level-1
|
||||
AND ( x.deleted = 0 AND y.deleted = 0 AND z.deleted = 0 )
|
||||
|
||||
UNION ALL
|
||||
|
||||
select
|
||||
n.hierarchy_control_id,
|
||||
n.user_id,
|
||||
(
|
||||
select max(level)+1
|
||||
from ' . $hlf->getTable() . ' as z
|
||||
where z.hierarchy_control_id = n.hierarchy_control_id AND z.deleted = 0
|
||||
) as level,
|
||||
1 as is_subordinate
|
||||
from ' . $huf->getTable() . ' as n
|
||||
LEFT JOIN ' . $hcf->getTable() . ' as o ON n.hierarchy_control_id = o.id
|
||||
LEFT JOIN ' . $hotf->getTable() . ' as p ON n.hierarchy_control_id = p.hierarchy_control_id
|
||||
LEFT JOIN ' . $hlf->getTable() . ' as z ON n.hierarchy_control_id = z.hierarchy_control_id AND z.user_id = \'' . TTUUID::castUUID( $user_id ) . '\'
|
||||
where
|
||||
p.object_type_id in (' . $this->getListSQL( $object_type_id, $ph, 'int' ) . ')
|
||||
AND ( o.deleted = 0 AND z.deleted = 0 )
|
||||
) as tmp
|
||||
WHERE level >= ' . (int)$min_level . '
|
||||
AND level <= ' . (int)$max_level . '
|
||||
ORDER BY level ASC, user_id ASC
|
||||
';
|
||||
|
||||
//Debug::Text(' Query: '. $query, __FILE__, __LINE__, __METHOD__, 10);
|
||||
$rs = $this->ExecuteSQL( $query, $ph );
|
||||
//Debug::Text(' Rows: '. $rs->RecordCount(), __FILE__, __LINE__, __METHOD__, 10);
|
||||
|
||||
if ( $rs->RecordCount() > 0 ) {
|
||||
$current_level = $level;
|
||||
$i = 0;
|
||||
foreach ( $rs as $row ) {
|
||||
//Debug::Text(' User ID: '. $row['user_id'] .' Level: '. $row['level'] .' Sub: '. $row['is_subordinate'] .' Current Level: '. $current_level, __FILE__, __LINE__, __METHOD__, 10);
|
||||
if ( $row['level'] == $current_level && $row['is_subordinate'] == 0 ) {
|
||||
$retarr['current_level'][] = $row['user_id'];
|
||||
} else if ( $row['level'] < $current_level && $row['is_subordinate'] == 0 ) {
|
||||
$retarr['parent_level'][] = $row['user_id'];
|
||||
} else if ( $row['level'] > $current_level && $row['is_subordinate'] == 1 ) {
|
||||
//Only ever show subordinates at child levels, this fixes the bug where the currently logged in user would see their own requests
|
||||
//in the authorization list.
|
||||
$retarr['child_level'][] = $row['user_id'];
|
||||
} //else { //Debug::Text(' Skipping row...', __FILE__, __LINE__, __METHOD__, 10);
|
||||
|
||||
$i++;
|
||||
}
|
||||
|
||||
$retarr['current_level'] = array_unique( $retarr['current_level'] );
|
||||
$retarr['parent_level'] = array_unique( $retarr['parent_level'] );
|
||||
$retarr['child_level'] = array_unique( $retarr['child_level'] );
|
||||
|
||||
//Debug::Arr($retarr, ' aChildren of User: '. $user_id .' At Level: '. $level, __FILE__, __LINE__, __METHOD__, 10);
|
||||
|
||||
return $retarr;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $user_id UUID
|
||||
* @param int $object_type_id
|
||||
* @param int $level
|
||||
* @param string $hierarchy_control_ids UUID
|
||||
* @param bool $recursive
|
||||
* @return array|bool
|
||||
*/
|
||||
function getByUserIdAndObjectTypeIDAndLevelAndHierarchyControlIDs( $user_id, $object_type_id, $level, $hierarchy_control_ids, $recursive = true ) {
|
||||
if ( $user_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !is_numeric( $level ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$min_level = ( $level - 1 );
|
||||
if ( $min_level <= 0 ) {
|
||||
$min_level = 0;
|
||||
}
|
||||
|
||||
//This should have two modes, one where it returns just the immediate child level, and one that returns all children "recursively".
|
||||
if ( $recursive == true ) {
|
||||
$max_level = 99;
|
||||
} else {
|
||||
$max_level = ( $level + 1 );
|
||||
}
|
||||
Debug::Text( ' User ID: ' . $user_id . ' Object Type ID: ' . $object_type_id . ' Level: ' . $level . ' Min Level: ' . $min_level . ' Max Level: ' . $max_level, __FILE__, __LINE__, __METHOD__, 10 );
|
||||
|
||||
$retarr = [ 'current_level' => [], 'parent_level' => [], 'child_level' => [] ];
|
||||
|
||||
$hcf = new HierarchyControlFactory();
|
||||
$hlf = new HierarchyLevelFactory();
|
||||
$huf = new HierarchyUserFactory();
|
||||
$hotf = new HierarchyObjectTypeFactory();
|
||||
|
||||
$ph = [];
|
||||
|
||||
//UNION two queries together, the first query gets all superiors, one level above, and all levels below.
|
||||
//The 2nd query gets all subordinates.
|
||||
$query = '
|
||||
select * from (
|
||||
select x.hierarchy_control_id,
|
||||
x.user_id,
|
||||
x.level,
|
||||
0 as is_subordinate
|
||||
from ' . $hlf->getTable() . ' as x
|
||||
LEFT JOIN ' . $hcf->getTable() . ' as y ON x.hierarchy_control_id = y.id
|
||||
LEFT JOIN ' . $hotf->getTable() . ' as y2 ON x.hierarchy_control_id = y2.hierarchy_control_id
|
||||
LEFT JOIN ' . $hlf->getTable() . ' as z ON x.hierarchy_control_id = z.hierarchy_control_id AND z.user_id = \'' . TTUUID::castUUID( $user_id ) . '\'
|
||||
where
|
||||
y2.object_type_id in (' . $this->getListSQL( $object_type_id, $ph, 'int' ) . ')
|
||||
AND x.level >= z.level-1
|
||||
AND ( x.deleted = 0 AND y.deleted = 0 AND z.deleted = 0 )
|
||||
|
||||
UNION ALL
|
||||
|
||||
select
|
||||
n.hierarchy_control_id,
|
||||
n.user_id,
|
||||
(
|
||||
select max(level)+1
|
||||
from ' . $hlf->getTable() . ' as z
|
||||
where z.hierarchy_control_id = n.hierarchy_control_id AND z.deleted = 0
|
||||
) as level,
|
||||
1 as is_subordinate
|
||||
from ' . $huf->getTable() . ' as n
|
||||
LEFT JOIN ' . $hcf->getTable() . ' as o ON n.hierarchy_control_id = o.id
|
||||
LEFT JOIN ' . $hotf->getTable() . ' as p ON n.hierarchy_control_id = p.hierarchy_control_id
|
||||
LEFT JOIN ' . $hlf->getTable() . ' as z ON n.hierarchy_control_id = z.hierarchy_control_id AND z.user_id = \'' . TTUUID::castUUID( $user_id ) . '\'
|
||||
where
|
||||
p.object_type_id in (' . $this->getListSQL( $object_type_id, $ph, 'int' ) . ')
|
||||
AND ( o.deleted = 0 AND z.deleted = 0 )
|
||||
) as tmp
|
||||
WHERE
|
||||
hierarchy_control_id in (' . $this->getListSQL( $hierarchy_control_ids, $ph, 'uuid' ) . ')
|
||||
AND ( level >= ' . (int)$min_level . ' AND level <= ' . (int)$max_level . ' )
|
||||
ORDER BY level ASC, user_id ASC
|
||||
';
|
||||
|
||||
//Debug::Text(' Query: '. $query, __FILE__, __LINE__, __METHOD__, 10);
|
||||
$rs = $this->ExecuteSQL( $query, $ph );
|
||||
//Debug::Text(' Rows: '. $rs->RecordCount(), __FILE__, __LINE__, __METHOD__, 10);
|
||||
|
||||
if ( $rs->RecordCount() > 0 ) {
|
||||
$current_level = $level;
|
||||
$i = 0;
|
||||
foreach ( $rs as $row ) {
|
||||
Debug::Text( ' User ID: ' . $row['user_id'] . ' Level: ' . $row['level'] . ' Sub: ' . $row['is_subordinate'] . ' Current Level: ' . $current_level, __FILE__, __LINE__, __METHOD__, 10 );
|
||||
if ( $row['level'] == $current_level && $row['is_subordinate'] == 0 ) {
|
||||
$retarr['current_level'][] = $row['user_id'];
|
||||
} else if ( $row['level'] < $current_level && $row['is_subordinate'] == 0 ) {
|
||||
$retarr['parent_level'][] = $row['user_id'];
|
||||
} else if ( $row['level'] > $current_level && $row['is_subordinate'] == 1 ) {
|
||||
//Only ever show subordinates at child levels, this fixes the bug where the currently logged in user would see their own requests
|
||||
//in the authorization list.
|
||||
$retarr['child_level'][] = $row['user_id'];
|
||||
} //else { //Debug::Text(' Skipping row...', __FILE__, __LINE__, __METHOD__, 10);
|
||||
|
||||
$i++;
|
||||
}
|
||||
|
||||
$retarr['current_level'] = array_unique( $retarr['current_level'] );
|
||||
$retarr['parent_level'] = array_unique( $retarr['parent_level'] );
|
||||
$retarr['child_level'] = array_unique( $retarr['child_level'] );
|
||||
|
||||
Debug::Arr( $retarr, ' aChildren of User: ' . $user_id . ' At Level: ' . $level, __FILE__, __LINE__, __METHOD__, 10 );
|
||||
|
||||
return $retarr;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $company_id UUID
|
||||
* @param string $user_id UUID
|
||||
* @param int $object_type_id
|
||||
* @param bool $immediate_parents_only
|
||||
* @param bool $include_levels
|
||||
* @return array|bool
|
||||
*/
|
||||
function getHierarchyParentByCompanyIdAndUserIdAndObjectTypeID( $company_id, $user_id, $object_type_id = 100, $immediate_parents_only = true, $include_levels = true ) {
|
||||
if ( $company_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $user_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $object_type_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Parents are only considered if an employee is explicitly assigned to a hierarchy as a subordinate.
|
||||
//This does not take into account an employee being in the middle of a hierarchy but not assigned to it as a subordinate.
|
||||
//This is because the same employee can be assigned as a superior to many hierarchies, but only to a single hierarchy (of the same object type) if they are subordinates.
|
||||
|
||||
$uf = new UserFactory();
|
||||
$hlf = new HierarchyLevelFactory();
|
||||
$huf = new HierarchyUserFactory();
|
||||
$hotf = new HierarchyObjectTypeFactory();
|
||||
$hcf = new HierarchyControlFactory();
|
||||
|
||||
$ph = [
|
||||
'user_id' => TTUUID::castUUID( $user_id ),
|
||||
'company_id' => TTUUID::castUUID( $company_id ),
|
||||
//'object_type_id' => (int)$object_type_id,
|
||||
];
|
||||
|
||||
$query = '
|
||||
select w.level, w.user_id
|
||||
from ' . $hlf->getTable() . ' as w
|
||||
LEFT JOIN ' . $huf->getTable() . ' as x ON w.hierarchy_control_id = x.hierarchy_control_id
|
||||
LEFT JOIN ' . $hotf->getTable() . ' as y ON w.hierarchy_control_id = y.hierarchy_control_id
|
||||
LEFT JOIN ' . $uf->getTable() . ' as z ON x.user_id = z.id
|
||||
LEFT JOIN ' . $hcf->getTable() . ' as e ON w.hierarchy_control_id = e.id
|
||||
WHERE
|
||||
x.user_id = ?
|
||||
AND z.company_id = ?
|
||||
AND y.object_type_id in (' . $this->getListSQL( $object_type_id, $ph, 'int' ) . ')
|
||||
AND ( w.deleted = 0 AND e.deleted = 0 )
|
||||
ORDER BY w.level DESC
|
||||
';
|
||||
|
||||
//Debug::Query( $query, $ph, __FILE__, __LINE__, __METHOD__, 10);
|
||||
$rs = $this->ExecuteSQL( $query, $ph );
|
||||
//Debug::Text(' Rows: '. $rs->RecordCount(), __FILE__, __LINE__, __METHOD__, 10);
|
||||
|
||||
if ( $rs->RecordCount() > 0 ) {
|
||||
$retval = [];
|
||||
|
||||
$valid_level = false;
|
||||
foreach ( $rs as $row ) {
|
||||
if ( $immediate_parents_only == true ) {
|
||||
//Even if immediate_parents_only is set, we need to return all parents at the same level.
|
||||
//Prior to v3.1 we just returned a single parent.
|
||||
if ( $valid_level === false || $valid_level == $row['level'] ) {
|
||||
$retval[] = TTUUID::castUUID( $row['user_id'] );
|
||||
|
||||
if ( $valid_level === false ) {
|
||||
$valid_level = $row['level'];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( $include_levels == true ) {
|
||||
$retval[(int)$row['level']][] = TTUUID::castUUID( $row['user_id'] );
|
||||
} else {
|
||||
$retval[] = TTUUID::castUUID( $row['user_id'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( $immediate_parents_only == false ) {
|
||||
ksort( $retval );
|
||||
}
|
||||
} else {
|
||||
$retval = false;
|
||||
}
|
||||
|
||||
return $retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $company_id UUID
|
||||
* @param string $user_id UUID
|
||||
* @param int $object_type_id
|
||||
* @return array|bool
|
||||
*/
|
||||
function getHierarchyChildrenByCompanyIdAndUserIdAndObjectTypeID( $company_id, $user_id, $object_type_id = 100 ) {
|
||||
global $profiler;
|
||||
$profiler->startTimer( 'getPermissionHierarchyChildrenByCompanyIdAndUserId' );
|
||||
|
||||
if ( $company_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $user_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $object_type_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$uf = new UserFactory();
|
||||
$hlf = new HierarchyLevelFactory();
|
||||
$huf = new HierarchyUserFactory();
|
||||
$hotf = new HierarchyObjectTypeFactory();
|
||||
$hcf = new HierarchyControlFactory();
|
||||
|
||||
//When it comes to permissions we only consider subordinates, not other supervisors/managers in the hierarchy.
|
||||
|
||||
$ph = [
|
||||
'user_id' => TTUUID::castUUID( $user_id ),
|
||||
'company_id' => TTUUID::castUUID( $company_id ),
|
||||
];
|
||||
|
||||
//w.user_id != x.user_id, is there to make sure we exclude the current user from the subordinate list,
|
||||
//as we now allow superiors to also be subordinates in the same hierarchy.
|
||||
$query = '
|
||||
SELECT w.user_id as user_id
|
||||
FROM ' . $huf->getTable() . ' as w
|
||||
LEFT JOIN ' . $hlf->getTable() . ' as x ON w.hierarchy_control_id = x.hierarchy_control_id
|
||||
LEFT JOIN ' . $hotf->getTable() . ' as y ON w.hierarchy_control_id = y.hierarchy_control_id
|
||||
LEFT JOIN ' . $uf->getTable() . ' as z ON x.user_id = z.id
|
||||
LEFT JOIN ' . $hcf->getTable() . ' as z2 ON w.hierarchy_control_id = z2.id
|
||||
WHERE
|
||||
x.user_id = ?
|
||||
AND z.company_id = ?
|
||||
AND y.object_type_id in (' . $this->getListSQL( $object_type_id, $ph, 'int' ) . ')
|
||||
AND w.user_id != x.user_id
|
||||
AND ( x.deleted = 0 AND z2.deleted = 0 AND z.deleted = 0 )
|
||||
';
|
||||
|
||||
//Debug::Query( $query, $ph, __FILE__, __LINE__, __METHOD__, 10);
|
||||
$retval = $this->db->getCol( $query, $ph );
|
||||
$profiler->stopTimer( 'getPermissionHierarchyChildrenByCompanyIdAndUserId' );
|
||||
|
||||
//Debug::Arr( $retval, ' Retval: ', __FILE__, __LINE__, __METHOD__, 10);
|
||||
return $retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Used by installer to upgrade.
|
||||
|
||||
/**
|
||||
* @param string $company_id UUID
|
||||
* @param string $tree_id UUID
|
||||
* @return array|bool
|
||||
*/
|
||||
function getByCompanyIdAndHierarchyControlId( $company_id, $tree_id ) {
|
||||
if ( $company_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $tree_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$hclf = new HierarchyControlListFactory();
|
||||
$hclf->getByIdAndCompanyId( $tree_id, $company_id );
|
||||
if ( $hclf->getRecordCount() == 0 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->getByHierarchyControlId( $tree_id );
|
||||
}
|
||||
|
||||
//Used by installer to upgrade
|
||||
|
||||
/**
|
||||
* @param string $tree_id UUID
|
||||
* @param string $user_id UUID
|
||||
* @return array|bool
|
||||
*/
|
||||
function getParentLevelIdArrayByHierarchyControlIdAndUserId( $tree_id, $user_id ) {
|
||||
//This only gets the immediate parents
|
||||
if ( $tree_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $user_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->getFastTreeObject()->setTree( $tree_id );
|
||||
|
||||
//Get the parent, then get the current level from that.
|
||||
$parent_id = $this->getFastTreeObject()->getParentId( $user_id );
|
||||
|
||||
$retarr = [];
|
||||
|
||||
$parent_nodes = $this->getCurrentLevelIdArrayByHierarchyControlIdAndUserId( $tree_id, $parent_id );
|
||||
//Debug::Arr($parent_nodes, ' Parent Nodes', __FILE__, __LINE__, __METHOD__, 10);
|
||||
if ( is_array( $parent_nodes ) ) {
|
||||
$retarr = $parent_nodes;
|
||||
}
|
||||
|
||||
return $retarr;
|
||||
}
|
||||
|
||||
//Used by installer to upgrade
|
||||
|
||||
/**
|
||||
* @param string $tree_id UUID
|
||||
* @param string $user_id UUID
|
||||
* @param bool $ignore_self
|
||||
* @return array|bool
|
||||
*/
|
||||
function getCurrentLevelIdArrayByHierarchyControlIdAndUserId( $tree_id, $user_id, $ignore_self = false ) {
|
||||
if ( $tree_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $user_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->getFastTreeObject()->setTree( $tree_id );
|
||||
|
||||
$parent_id = $this->getFastTreeObject()->getParentId( $user_id );
|
||||
|
||||
$children = $this->getFastTreeObject()->getAllChildren( $parent_id );
|
||||
if ( $children === false ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ids = array_keys( $children );
|
||||
//Debug::Arr($ids, ' zNodes at the same level', __FILE__, __LINE__, __METHOD__, 10);
|
||||
|
||||
$hslf = new HierarchyShareListFactory();
|
||||
|
||||
//Check if current user is shared, because if it isn't shared, then we can ignore
|
||||
//all other shared users in the tree.
|
||||
$root_user_id_shared = $hslf->getByHierarchyControlIdAndUserId( $tree_id, $user_id )->getRecordCount();
|
||||
Debug::Text( 'Root User ID: ' . $user_id . ' Shared: ' . $root_user_id_shared, __FILE__, __LINE__, __METHOD__, 10 );
|
||||
|
||||
$retarr = [];
|
||||
$retarr[] = TTUUID::castUUID( $user_id );
|
||||
foreach ( $ids as $id ) {
|
||||
|
||||
$hierarchy_share = $hslf->getByHierarchyControlIdAndUserId( $tree_id, $id )->getCurrent()->isNew();
|
||||
|
||||
if ( $root_user_id_shared == true && $hierarchy_share === false ) {
|
||||
//Debug::Text(' Node IS shared: '. $id, __FILE__, __LINE__, __METHOD__, 10);
|
||||
$retarr[] = $id;
|
||||
} //else { //Debug::Text(' Node isnt shared: '. $id, __FILE__, __LINE__, __METHOD__, 10);
|
||||
}
|
||||
|
||||
return array_unique( $retarr );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
353
classes/modules/hierarchy/HierarchyObjectTypeFactory.class.php
Normal file
353
classes/modules/hierarchy/HierarchyObjectTypeFactory.class.php
Normal file
@ -0,0 +1,353 @@
|
||||
<?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 Modules\Hierarchy
|
||||
*/
|
||||
class HierarchyObjectTypeFactory extends Factory {
|
||||
protected $table = 'hierarchy_object_type';
|
||||
protected $pk_sequence_name = 'hierarchy_object_type_id_seq'; //PK Sequence name
|
||||
|
||||
var $hierarchy_control_obj = null;
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $params
|
||||
* @return array|null
|
||||
*/
|
||||
function _getFactoryOptions( $name, $params = 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 'object_type':
|
||||
$retval = [
|
||||
//10 => TTi18n::gettext('Recurring Schedule'),
|
||||
//20 => TTi18n::gettext('Schedule Amendment'),
|
||||
//30 => TTi18n::gettext('Shift Amendment'),
|
||||
//40 => TTi18n::gettext('Pay Stub Amendment')
|
||||
//50 => TTi18n::gettext('Request'),
|
||||
|
||||
100 => TTi18n::gettext( 'Permission' ),
|
||||
80 => TTi18n::gettext( 'Exception' ),
|
||||
90 => TTi18n::gettext( 'TimeSheet' ),
|
||||
|
||||
//Add 1000 to request type_id's. Make sure no other objects pass 1000.
|
||||
1010 => TTi18n::gettext( 'Request: Missed Punch' ),
|
||||
1020 => TTi18n::gettext( 'Request: Time Adjustment' ),
|
||||
1030 => TTi18n::gettext( 'Request: Absence (incl. Vacation)' ),
|
||||
1040 => TTi18n::gettext( 'Request: Schedule Adjustment' ),
|
||||
1100 => TTi18n::gettext( 'Request: Other' ),
|
||||
];
|
||||
|
||||
if ( $product_edition_id >= 25 ) {
|
||||
$retval[200] = TTi18n::gettext( 'Expense' );
|
||||
}
|
||||
|
||||
break;
|
||||
case 'short_object_type': //Defines a short form of the names.
|
||||
$retval = [
|
||||
//10 => TTi18n::gettext('Recurring Schedule'),
|
||||
//20 => TTi18n::gettext('Schedule Amendment'),
|
||||
//30 => TTi18n::gettext('Shift Amendment'),
|
||||
//40 => TTi18n::gettext('Pay Stub Amendment')
|
||||
//50 => TTi18n::gettext('Request'),
|
||||
|
||||
100 => TTi18n::gettext( 'Permission' ),
|
||||
80 => TTi18n::gettext( 'Exception' ),
|
||||
90 => TTi18n::gettext( 'TimeSheet' ),
|
||||
|
||||
//Add 1000 to request type_id's. Make sure no other objects pass 1000.
|
||||
1010 => TTi18n::gettext( 'R:Missed Punch' ),
|
||||
1020 => TTi18n::gettext( 'R:Adjustment' ),
|
||||
1030 => TTi18n::gettext( 'R:Absence' ),
|
||||
1040 => TTi18n::gettext( 'R:Schedule' ),
|
||||
1100 => TTi18n::gettext( 'R:Other' ),
|
||||
|
||||
200 => TTi18n::gettext( 'Expense' ),
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
$retval = Misc::addSortPrefix( $retval );
|
||||
|
||||
return $retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null
|
||||
*/
|
||||
function getHierarchyControlObject() {
|
||||
if ( is_object( $this->hierarchy_control_obj ) ) {
|
||||
return $this->hierarchy_control_obj;
|
||||
} else {
|
||||
$hclf = TTnew( 'HierarchyControlListFactory' ); /** @var HierarchyControlListFactory $hclf */
|
||||
$this->hierarchy_control_obj = $hclf->getById( $this->getHierarchyControl() )->getCurrent();
|
||||
|
||||
return $this->hierarchy_control_obj;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|mixed
|
||||
*/
|
||||
function getHierarchyControl() {
|
||||
return $this->getGenericDataValue( 'hierarchy_control_id' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setHierarchyControl( $value ) {
|
||||
$value = TTUUID::castUUID( $value );
|
||||
Debug::Text( 'Hierarchy Control ID: ' . $value, __FILE__, __LINE__, __METHOD__, 10 );
|
||||
|
||||
return $this->setGenericDataValue( 'hierarchy_control_id', $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $object_type
|
||||
* @return bool
|
||||
*/
|
||||
function isUniqueObjectType( $object_type ) {
|
||||
/*
|
||||
$company_id = $this->getHierarchyControlObject()->getCompany();
|
||||
|
||||
$hotlf = TTnew( 'HierarchyObjectTypeListFactory' );
|
||||
$hotlf->getByCompanyId( $company_id );
|
||||
foreach ( $hotlf as $object_type_obj) {
|
||||
if ( $object_type_obj->getId() !== $this->getId() ) {
|
||||
$assigned_object_types[] = $object_type_obj->getObjectType();
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset($assigned_object_types) AND is_array($assigned_object_types) AND in_array( $object_type, $assigned_object_types) ) {
|
||||
return FALSE;
|
||||
}
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
function getObjectType() {
|
||||
return $this->getGenericDataValue( 'object_type_id' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setObjectType( $value ) {
|
||||
$value = (int)trim( $value );
|
||||
|
||||
return $this->setGenericDataValue( 'object_type_id', $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function Validate() {
|
||||
//
|
||||
// BELOW: Validation code moved from set*() functions.
|
||||
//
|
||||
// Hierarchy Control
|
||||
if ( $this->getHierarchyControl() == TTUUID::getZeroID() ) {
|
||||
$hclf = TTnew( 'HierarchyControlListFactory' ); /** @var HierarchyControlListFactory $hclf */
|
||||
$this->Validator->isResultSetWithRows( 'hierarchy_control_id',
|
||||
$hclf->getByID( $this->getHierarchyControl() ),
|
||||
TTi18n::gettext( 'Invalid Hierarchy Control' )
|
||||
);
|
||||
}
|
||||
// Object Type
|
||||
$this->Validator->inArrayKey( 'object_type',
|
||||
$this->getObjectType(),
|
||||
TTi18n::gettext( 'Object Type is invalid' ),
|
||||
Misc::trimSortPrefix( $this->getOptions( 'object_type' ) )
|
||||
);
|
||||
if ( $this->Validator->isError( 'object_type' ) == false ) {
|
||||
$this->Validator->isTrue( 'object_type',
|
||||
$this->isUniqueObjectType( $this->getObjectType() ),
|
||||
TTi18n::gettext( 'Object Type is already assigned to another hierarchy' )
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// ABOVE: Validation code moved from set*() functions.
|
||||
//
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function postSave() {
|
||||
$cache_id = $this->getHierarchyControlObject()->getCompany() . $this->getObjectType();
|
||||
$this->removeCache( $cache_id );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//This table doesn't have any of these columns, so overload the functions.
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getDeleted() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $bool
|
||||
* @return bool
|
||||
*/
|
||||
function setDeleted( $bool ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getCreatedDate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $epoch EPOCH
|
||||
* @return bool
|
||||
*/
|
||||
function setCreatedDate( $epoch = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getCreatedBy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setCreatedBy( $id = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getUpdatedDate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $epoch EPOCH
|
||||
* @return bool
|
||||
*/
|
||||
function setUpdatedDate( $epoch = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getUpdatedBy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setUpdatedBy( $id = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getDeletedDate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $epoch EPOCH
|
||||
* @return bool
|
||||
*/
|
||||
function setDeletedDate( $epoch = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getDeletedBy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setDeletedBy( $id = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $log_action
|
||||
* @return bool
|
||||
*/
|
||||
function addLog( $log_action ) {
|
||||
$object_type = Option::getByKey( $this->getObjectType(), Misc::TrimSortPrefix( $this->getOptions( 'object_type' ) ) );
|
||||
|
||||
return TTLog::addEntry( $this->getHierarchyControl(), $log_action, TTi18n::getText( 'Object' ) . ': ' . $object_type, null, $this->getTable() );
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,245 @@
|
||||
<?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 Modules\Hierarchy
|
||||
*/
|
||||
class HierarchyObjectTypeListFactory extends HierarchyObjectTypeFactory implements IteratorAggregate {
|
||||
|
||||
/**
|
||||
* @param int $limit Limit the number of records returned
|
||||
* @param int $page Page number of records to return for pagination
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return $this
|
||||
*/
|
||||
function getAll( $limit = null, $page = null, $where = null, $order = null ) {
|
||||
$query = '
|
||||
select *
|
||||
from ' . $this->getTable() . '
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, null, $limit, $page );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyObjectTypeListFactory
|
||||
*/
|
||||
function getById( $id, $where = null, $order = null ) {
|
||||
if ( $id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ph = [
|
||||
'id' => TTUUID::castUUID( $id ),
|
||||
];
|
||||
|
||||
|
||||
$query = '
|
||||
select *
|
||||
from ' . $this->getTable() . '
|
||||
where id = ?
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyObjectTypeListFactory
|
||||
*/
|
||||
function getByHierarchyControlId( $id, $where = null, $order = null ) {
|
||||
if ( $id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ph = [
|
||||
'id' => TTUUID::castUUID( $id ),
|
||||
];
|
||||
|
||||
|
||||
$query = '
|
||||
select *
|
||||
from ' . $this->getTable() . '
|
||||
where hierarchy_control_id = ?
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param int $object_type_id
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyObjectTypeListFactory
|
||||
*/
|
||||
function getByCompanyIdAndObjectTypeId( $id, $object_type_id, $where = null, $order = null ) {
|
||||
if ( $id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $object_type_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$cache_id = $id . $object_type_id;
|
||||
$this->rs = $this->getCache( $cache_id );
|
||||
if ( $this->rs === false ) {
|
||||
$hcf = new HierarchyControlFactory();
|
||||
$hotf = new HierarchyObjectTypeFactory();
|
||||
|
||||
$strict_order = true;
|
||||
if ( $order == null ) {
|
||||
//$order = array('b.last_name' => 'asc');
|
||||
$strict_order = false;
|
||||
}
|
||||
|
||||
$ph = [
|
||||
'id' => TTUUID::castUUID( $id ),
|
||||
'object_type_id' => (int)$object_type_id,
|
||||
];
|
||||
|
||||
$query = '
|
||||
select *
|
||||
from ' . $this->getTable() . ' as a,
|
||||
' . $hcf->getTable() . ' as b,
|
||||
' . $hotf->getTable() . ' as c
|
||||
|
||||
where a.hierarchy_control_id = b.id
|
||||
AND a.hierarchy_control_id = c.hierarchy_control_id
|
||||
AND b.company_id = ?
|
||||
AND c.object_type_id = ?
|
||||
AND b.deleted = 0
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order, $strict_order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
$this->saveCache( $this->rs, $cache_id );
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param int $limit Limit the number of records returned
|
||||
* @param int $page Page number of records to return for pagination
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyObjectTypeListFactory
|
||||
*/
|
||||
function getByCompanyId( $id, $limit = null, $page = null, $where = null, $order = null ) {
|
||||
if ( $id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$strict_order = true;
|
||||
if ( $order == null ) {
|
||||
//$order = array('b.last_name' => 'asc');
|
||||
$strict_order = false;
|
||||
}
|
||||
|
||||
$hcf = new HierarchyControlFactory();
|
||||
|
||||
$ph = [
|
||||
'id' => TTUUID::castUUID( $id ),
|
||||
];
|
||||
|
||||
|
||||
$query = '
|
||||
select *
|
||||
from ' . $this->getTable() . ' as a,
|
||||
' . $hcf->getTable() . ' as b
|
||||
|
||||
where a.hierarchy_control_id = b.id
|
||||
AND b.company_id = ?
|
||||
AND b.deleted = 0
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order, $strict_order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph, $limit, $page );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @return array
|
||||
*/
|
||||
function getByCompanyIdArray( $id ) {
|
||||
|
||||
$hotlf = new HierarchyObjectTypeListFactory();
|
||||
$hotlf->getByCompanyId( $id );
|
||||
|
||||
$object_types = [];
|
||||
foreach ( $hotlf as $object_type ) {
|
||||
$object_types[] = $object_type->getObjectType();
|
||||
}
|
||||
|
||||
return $object_types;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
227
classes/modules/hierarchy/HierarchyShareFactory.class.php
Normal file
227
classes/modules/hierarchy/HierarchyShareFactory.class.php
Normal file
@ -0,0 +1,227 @@
|
||||
<?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".
|
||||
*
|
||||
********************************************************************************/
|
||||
|
||||
/*
|
||||
CREATE TABLE hierarchy_share (
|
||||
id serial NOT NULL,
|
||||
hierarchy_control_id integer DEFAULT 0 NOT NULL,
|
||||
user_id integer DEFAULT 0 NOT NULL
|
||||
) WITHOUT OIDS;
|
||||
*/
|
||||
|
||||
/**
|
||||
* @package Modules\Hierarchy
|
||||
*/
|
||||
class HierarchyShareFactory extends Factory {
|
||||
protected $table = 'hierarchy_share';
|
||||
protected $pk_sequence_name = 'hierarchy_share_id_seq'; //PK Sequence name
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
function getHierarchyControl() {
|
||||
return $this->getGenericDataValue( 'hierarchy_control_id' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setHierarchyControl( $value ) {
|
||||
$value = TTUUID::castUUID( $value );
|
||||
|
||||
return $this->setGenericDataValue( 'hierarchy_control_id', $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
function getUser() {
|
||||
return $this->getGenericDataValue( 'user_id' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setUser( $value ) {
|
||||
$value = TTUUID::castUUID( $value );
|
||||
|
||||
return $this->setGenericDataValue( 'user_id', $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function Validate() {
|
||||
//
|
||||
// BELOW: Validation code moved from set*() functions.
|
||||
//
|
||||
// Hierarchy control
|
||||
$hclf = TTnew( 'HierarchyControlListFactory' ); /** @var HierarchyControlListFactory $hclf */
|
||||
$this->Validator->isResultSetWithRows( 'hierarchy_control',
|
||||
$hclf->getByID( $this->getHierarchyControl() ),
|
||||
TTi18n::gettext( 'Hierarchy control is invalid' )
|
||||
);
|
||||
// User
|
||||
$ulf = TTnew( 'UserListFactory' ); /** @var UserListFactory $ulf */
|
||||
$this->Validator->isResultSetWithRows( 'user',
|
||||
$ulf->getByID( $this->getUser() ),
|
||||
TTi18n::gettext( 'User is invalid' )
|
||||
);
|
||||
|
||||
//
|
||||
// ABOVE: Validation code moved from set*() functions.
|
||||
//
|
||||
return true;
|
||||
}
|
||||
|
||||
//This table doesn't have any of these columns, so overload the functions.
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getDeleted() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $bool
|
||||
* @return bool
|
||||
*/
|
||||
function setDeleted( $bool ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getCreatedDate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $epoch EPOCH
|
||||
* @return bool
|
||||
*/
|
||||
function setCreatedDate( $epoch = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getCreatedBy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setCreatedBy( $id = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getUpdatedDate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $epoch EPOCH
|
||||
* @return bool
|
||||
*/
|
||||
function setUpdatedDate( $epoch = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getUpdatedBy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setUpdatedBy( $id = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getDeletedDate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $epoch EPOCH
|
||||
* @return bool
|
||||
*/
|
||||
function setDeletedDate( $epoch = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getDeletedBy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setDeletedBy( $id = null ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
163
classes/modules/hierarchy/HierarchyShareListFactory.class.php
Normal file
163
classes/modules/hierarchy/HierarchyShareListFactory.class.php
Normal file
@ -0,0 +1,163 @@
|
||||
<?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 Modules\Hierarchy
|
||||
*/
|
||||
class HierarchyShareListFactory extends HierarchyShareFactory implements IteratorAggregate {
|
||||
|
||||
/**
|
||||
* @param int $limit Limit the number of records returned
|
||||
* @param int $page Page number of records to return for pagination
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return $this
|
||||
*/
|
||||
function getAll( $limit = null, $page = null, $where = null, $order = null ) {
|
||||
$query = '
|
||||
select *
|
||||
from ' . $this->getTable();
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, null, $limit, $page );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyShareListFactory
|
||||
*/
|
||||
function getById( $id, $where = null, $order = null ) {
|
||||
if ( $id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ph = [
|
||||
'id' => TTUUID::castUUID( $id ),
|
||||
];
|
||||
|
||||
|
||||
$query = '
|
||||
select *
|
||||
from ' . $this->getTable() . '
|
||||
where id = ?
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyShareListFactory
|
||||
*/
|
||||
function getByHierarchyControlId( $id, $where = null, $order = null ) {
|
||||
if ( $id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ph = [
|
||||
'id' => TTUUID::castUUID( $id ),
|
||||
];
|
||||
|
||||
|
||||
$query = '
|
||||
select *
|
||||
from ' . $this->getTable() . '
|
||||
where hierarchy_control_id = ?
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param string $user_id UUID
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyShareListFactory
|
||||
*/
|
||||
function getByHierarchyControlIdAndUserId( $id, $user_id, $where = null, $order = null ) {
|
||||
if ( $id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $user_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ph = [
|
||||
'id' => TTUUID::castUUID( $id ),
|
||||
'user_id' => TTUUID::castUUID( $user_id ),
|
||||
];
|
||||
|
||||
$query = '
|
||||
select *
|
||||
from ' . $this->getTable() . '
|
||||
where hierarchy_control_id = ?
|
||||
AND user_id = ?
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
336
classes/modules/hierarchy/HierarchyUserFactory.class.php
Normal file
336
classes/modules/hierarchy/HierarchyUserFactory.class.php
Normal file
@ -0,0 +1,336 @@
|
||||
<?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 Modules\Hierarchy
|
||||
*/
|
||||
class HierarchyUserFactory extends Factory {
|
||||
protected $table = 'hierarchy_user';
|
||||
protected $pk_sequence_name = 'hierarchy_user_id_seq'; //PK Sequence name
|
||||
|
||||
var $hierarchy_control_obj = null;
|
||||
var $user_obj = null;
|
||||
|
||||
/**
|
||||
* @return null
|
||||
*/
|
||||
function getHierarchyControlObject() {
|
||||
if ( is_object( $this->hierarchy_control_obj ) ) {
|
||||
return $this->hierarchy_control_obj;
|
||||
} else {
|
||||
$hclf = TTnew( 'HierarchyControlListFactory' ); /** @var HierarchyControlListFactory $hclf */
|
||||
$this->hierarchy_control_obj = $hclf->getById( $this->getHierarchyControl() )->getCurrent();
|
||||
|
||||
return $this->hierarchy_control_obj;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|null
|
||||
*/
|
||||
function getUserObject() {
|
||||
if ( is_object( $this->user_obj ) ) {
|
||||
return $this->user_obj;
|
||||
} else {
|
||||
$ulf = TTnew( 'UserListFactory' ); /** @var UserListFactory $ulf */
|
||||
$ulf->getById( $this->getUser() );
|
||||
if ( $ulf->getRecordCount() == 1 ) {
|
||||
$this->user_obj = $ulf->getCurrent();
|
||||
|
||||
return $this->user_obj;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|mixed
|
||||
*/
|
||||
function getHierarchyControl() {
|
||||
return $this->getGenericDataValue( 'hierarchy_control_id' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setHierarchyControl( $value ) {
|
||||
$value = TTUUID::castUUID( $value );
|
||||
|
||||
//This is a sub-class, need to support setting HierachyControlID before its created.
|
||||
return $this->setGenericDataValue( 'hierarchy_control_id', $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param int $exclude_id
|
||||
* @return bool
|
||||
*/
|
||||
function isUniqueUser( $id, $exclude_id = 0 ) {
|
||||
if ( $exclude_id === 0 ) {
|
||||
$exclude_id = TTUUID::getZeroID();
|
||||
}
|
||||
$hcf = TTnew( 'HierarchyControlFactory' ); /** @var HierarchyControlFactory $hcf */
|
||||
$hotf = TTnew( 'HierarchyObjectTypeFactory' ); /** @var HierarchyObjectTypeFactory $hotf */
|
||||
|
||||
$ph = [
|
||||
'hierarchy_control_id' => $this->getHierarchyControl(),
|
||||
'id' => $id,
|
||||
'exclude_id' => TTUUID::castUUID( $exclude_id ),
|
||||
];
|
||||
|
||||
//$query = 'select a.id from '. $this->getTable() .' as a, '. $pglf->getTable() .' as b where a.hierarchy_control_id = b.id AND a.user_id = ? AND b.deleted=0';
|
||||
$query = '
|
||||
select *
|
||||
from ' . $hotf->getTable() . ' as a
|
||||
LEFT JOIN ' . $this->getTable() . ' as b ON a.hierarchy_control_id = b.hierarchy_control_id
|
||||
LEFT JOIN ' . $hcf->getTable() . ' as c ON a.hierarchy_control_id = c.id
|
||||
WHERE a.object_type_id in (
|
||||
select object_type_id
|
||||
from hierarchy_object_type
|
||||
where hierarchy_control_id = ? )
|
||||
AND b.user_id = ?
|
||||
AND a.hierarchy_control_id != ?
|
||||
AND c.deleted = 0
|
||||
';
|
||||
//Debug::Query( $query, $ph, __FILE__, __LINE__, __METHOD__, 10);
|
||||
$user_id = $this->db->GetOne( $query, $ph );
|
||||
|
||||
if ( $user_id === false ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
function getUser() {
|
||||
return $this->getGenericDataValue( 'user_id' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setUser( $value ) {
|
||||
$value = TTUUID::castUUID( $value );
|
||||
|
||||
return $this->setGenericDataValue( 'user_id', $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function Validate() {
|
||||
//
|
||||
// BELOW: Validation code moved from set*() functions.
|
||||
//
|
||||
|
||||
// Hierarchy Control
|
||||
if ( $this->getHierarchyControl() == '' || $this->getHierarchyControl() == TTUUID::getZeroID() ) {
|
||||
$hclf = TTnew( 'HierarchyControlListFactory' ); /** @var HierarchyControlListFactory $hclf */
|
||||
$this->Validator->isResultSetWithRows( 'hierarchy_control_id',
|
||||
$hclf->getByID( $this->getHierarchyControl() ),
|
||||
TTi18n::gettext( 'Invalid Hierarchy Control' )
|
||||
);
|
||||
}
|
||||
|
||||
// Selected Employee
|
||||
$ulf = TTnew( 'UserListFactory' ); /** @var UserListFactory $ulf */
|
||||
$this->Validator->isResultSetWithRows( 'user',
|
||||
$ulf->getByID( $this->getUser() ),
|
||||
TTi18n::gettext( 'Selected Employee is invalid' )
|
||||
);
|
||||
/*
|
||||
//Allow superiors to be assigned as subordinates in the same hierarchy to make it easier to administer hierarchies
|
||||
//that have superiors sharing responsibility.
|
||||
//For example Super1 and Super2 look after 10 subordinates as well as each other. This would require 3 hierarchies normally,
|
||||
//but if we allow Super1 and Super2 to be subordinates in the same hierarchy, it can be done with a single hierarchy.
|
||||
//The key with this though is to have Permission->getPermissionChildren() *not* return the current user, even if they are a subordinates,
|
||||
//as that could cause a conflict with view_own and view_child permissions (as a child would imply view_own)
|
||||
AND
|
||||
$this->Validator->isNotResultSetWithRows( 'user',
|
||||
$hllf->getByHierarchyControlIdAndUserId( $this->getHierarchyControl(), $id ),
|
||||
TTi18n::gettext('Selected Employee is assigned as both a superior and subordinate')
|
||||
)
|
||||
*/
|
||||
if ( $this->Validator->isError( 'user' ) == false ) {
|
||||
$this->Validator->isTrue( 'user',
|
||||
$this->isUniqueUser( $this->getUser() ),
|
||||
TTi18n::gettext( 'Selected Employee is already assigned to another hierarchy' )
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// ABOVE: Validation code moved from set*() functions.
|
||||
//
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//This table doesn't have any of these columns, so overload the functions.
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getDeleted() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $bool
|
||||
* @return bool
|
||||
*/
|
||||
function setDeleted( $bool ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getCreatedDate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $epoch EPOCH
|
||||
* @return bool
|
||||
*/
|
||||
function setCreatedDate( $epoch = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getCreatedBy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setCreatedBy( $id = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getUpdatedDate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $epoch EPOCH
|
||||
* @return bool
|
||||
*/
|
||||
function setUpdatedDate( $epoch = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getUpdatedBy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setUpdatedBy( $id = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getDeletedDate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $epoch EPOCH
|
||||
* @return bool
|
||||
*/
|
||||
function setDeletedDate( $epoch = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
function getDeletedBy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @return bool
|
||||
*/
|
||||
function setDeletedBy( $id = null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $log_action
|
||||
* @return bool
|
||||
*/
|
||||
function addLog( $log_action ) {
|
||||
$u_obj = $this->getUserObject();
|
||||
if ( is_object( $u_obj ) ) {
|
||||
return TTLog::addEntry( $this->getHierarchyControl(), $log_action, TTi18n::getText( 'Subordinate' ) . ': ' . $u_obj->getFullName( false, true ), null, $this->getTable() );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
203
classes/modules/hierarchy/HierarchyUserListFactory.class.php
Normal file
203
classes/modules/hierarchy/HierarchyUserListFactory.class.php
Normal file
@ -0,0 +1,203 @@
|
||||
<?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 Modules\Hierarchy
|
||||
*/
|
||||
class HierarchyUserListFactory extends HierarchyUserFactory implements IteratorAggregate {
|
||||
|
||||
/**
|
||||
* @param int $limit Limit the number of records returned
|
||||
* @param int $page Page number of records to return for pagination
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return $this
|
||||
*/
|
||||
function getAll( $limit = null, $page = null, $where = null, $order = null ) {
|
||||
$query = '
|
||||
select *
|
||||
from ' . $this->getTable();
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, null, $limit, $page );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyUserListFactory
|
||||
*/
|
||||
function getById( $id, $where = null, $order = null ) {
|
||||
if ( $id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ph = [
|
||||
'id' => TTUUID::castUUID( $id ),
|
||||
];
|
||||
|
||||
|
||||
$query = '
|
||||
select *
|
||||
from ' . $this->getTable() . '
|
||||
where id = ?
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $company_id UUID
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyUserListFactory
|
||||
*/
|
||||
function getByCompanyId( $company_id, $where = null, $order = null ) {
|
||||
if ( $company_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$hcf = new HierarchyControlFactory();
|
||||
|
||||
$ph = [
|
||||
'company_id' => TTUUID::castUUID( $company_id ),
|
||||
];
|
||||
|
||||
$query = '
|
||||
select a.*
|
||||
from ' . $this->getTable() . ' as a
|
||||
LEFT JOIN ' . $hcf->getTable() . ' as b ON a.hierarchy_control_id = b.id
|
||||
where b.company_id = ?
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyUserListFactory
|
||||
*/
|
||||
function getByHierarchyControlId( $id, $where = null, $order = null ) {
|
||||
if ( $id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$hcf = new HierarchyControlFactory();
|
||||
|
||||
$ph = [
|
||||
'id' => TTUUID::castUUID( $id ),
|
||||
];
|
||||
|
||||
|
||||
$query = '
|
||||
select a.*
|
||||
from ' . $this->getTable() . ' as a,
|
||||
' . $hcf->getTable() . ' as b
|
||||
where a.hierarchy_control_id = b.id
|
||||
AND a.hierarchy_control_id = ?
|
||||
AND b.deleted = 0
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id UUID
|
||||
* @param string $user_id UUID
|
||||
* @param array $where Additional SQL WHERE clause in format of array( $column => $filter, ... ). ie: array( 'id' => 1, ... )
|
||||
* @param array $order Sort order passed to SQL in format of array( $column => 'asc', 'name' => 'desc', ... ). ie: array( 'id' => 'asc', 'name' => 'desc', ... )
|
||||
* @return bool|HierarchyUserListFactory
|
||||
*/
|
||||
function getByHierarchyControlAndUserId( $id, $user_id, $where = null, $order = null ) {
|
||||
if ( $id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $user_id == '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$hcf = new HierarchyControlFactory();
|
||||
|
||||
$ph = [
|
||||
'id' => TTUUID::castUUID( $id ),
|
||||
'user_id' => TTUUID::castUUID( $user_id ),
|
||||
];
|
||||
|
||||
$query = '
|
||||
select a.*
|
||||
from ' . $this->getTable() . ' as a,
|
||||
' . $hcf->getTable() . ' as b
|
||||
where b.id = a.hierarchy_control_id
|
||||
AND a.hierarchy_control_id = ?
|
||||
AND a.user_id = ?
|
||||
AND b.deleted = 0
|
||||
';
|
||||
$query .= $this->getWhereSQL( $where );
|
||||
$query .= $this->getSortSQL( $order );
|
||||
|
||||
$this->rs = $this->ExecuteSQL( $query, $ph );
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
Reference in New Issue
Block a user