456 lines
17 KiB
PHP
456 lines
17 KiB
PHP
<?php
|
|
/*********************************************************************************
|
|
*
|
|
* TimeTrex is a Workforce Management program developed by
|
|
* TimeTrex Software Inc. Copyright (C) 2003 - 2021 TimeTrex Software Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it under
|
|
* the terms of the GNU Affero General Public License version 3 as published by
|
|
* the Free Software Foundation with the addition of the following permission
|
|
* added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
|
|
* WORK IN WHICH THE COPYRIGHT IS OWNED BY TIMETREX, TIMETREX DISCLAIMS THE
|
|
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
* details.
|
|
*
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License along
|
|
* with this program; if not, see http://www.gnu.org/licenses or write to the Free
|
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
* 02110-1301 USA.
|
|
*
|
|
*
|
|
* You can contact TimeTrex headquarters at Unit 22 - 2475 Dobbin Rd. Suite
|
|
* #292 West Kelowna, BC V4T 2E9, Canada or at email address info@timetrex.com.
|
|
*
|
|
*
|
|
* The interactive user interfaces in modified source and object code versions
|
|
* of this program must display Appropriate Legal Notices, as required under
|
|
* Section 5 of the GNU Affero General Public License version 3.
|
|
*
|
|
*
|
|
* In accordance with Section 7(b) of the GNU Affero General Public License
|
|
* version 3, these Appropriate Legal Notices must retain the display of the
|
|
* "Powered by TimeTrex" logo. If the display of the logo is not reasonably
|
|
* feasible for technical reasons, the Appropriate Legal Notices must display
|
|
* the words "Powered by TimeTrex".
|
|
*
|
|
********************************************************************************/
|
|
|
|
|
|
/**
|
|
* @package 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;
|
|
}
|
|
}
|
|
|
|
?>
|