getOptions( 'preset' ); break; case 'level': for ( $i = 1; $i <= 100; $i++ ) { //100 Levels. $retval[$i] = $i; } break; case 'columns': $retval = [ '-1000-name' => TTi18n::gettext( 'Name' ), '-1010-description' => TTi18n::gettext( 'Description' ), '-1020-level' => TTi18n::gettext( 'Level' ), '-1030-total_users' => TTi18n::gettext( 'Employees' ), '-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( [ 'name', 'description', 'level' ], Misc::trimSortPrefix( $this->getOptions( 'columns' ) ) ); break; case 'default_display_columns': //Columns that are displayed by default. $retval = [ 'name', 'description', 'level', 'total_users', 'updated_by', 'updated_date', ]; break; case 'unique_columns': //Columns that are unique, and disabled for mass editing. $retval = [ 'name', ]; break; } return $retval; } /** * @param $data * @return array */ function _getVariableToFunctionMap( $data ) { $variable_function_map = [ 'id' => 'ID', 'company_id' => 'Company', 'name' => 'Name', 'description' => 'Description', 'level' => 'Level', 'total_users' => false, 'user' => 'User', 'permission' => 'Permission', 'deleted' => 'Deleted', ]; return $variable_function_map; } /** * @return bool */ function getCompanyObject() { return $this->getGenericObject( 'CompanyListFactory', $this->getCompany(), 'company_obj' ); } /** * @return bool|int|string */ 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'; $permission_control_id = $this->db->GetOne( $query, $ph ); Debug::Arr( $permission_control_id, 'Unique Permission Control ID: ' . $permission_control_id, __FILE__, __LINE__, __METHOD__, 10 ); if ( $permission_control_id === false ) { return true; } else { if ( $permission_control_id == $this->getId() ) { return true; } } return false; } /** * @return mixed */ function getName() { return $this->getGenericDataValue( 'name' ); } /** * @param $value * @return bool */ function setName( $value ) { $value = trim( $value ); return $this->setGenericDataValue( 'name', $value ); } /** * @return mixed */ function getDescription() { return $this->getGenericDataValue( 'description' ); } /** * @param $value * @return bool */ function setDescription( $value ) { $value = trim( $value ); return $this->setGenericDataValue( 'description', $value ); } /** * @return bool|int */ function getLevel() { return $this->getGenericDataValue( 'level' ); } /** * @param $value * @return bool */ function setLevel( $value ) { $value = (int)trim( $value ); return $this->setGenericDataValue( 'level', $value ); } /** * @return array|bool */ function getUser() { $pulf = TTnew( 'PermissionUserListFactory' ); /** @var PermissionUserListFactory $pulf */ $pulf->getByPermissionControlId( $this->getId() ); $list = []; foreach ( $pulf as $obj ) { $list[] = $obj->getUser(); } if ( empty( $list ) == false ) { return $list; } return false; } /** * @param string|string[] $ids UUID * @return bool */ function setUser( $ids ) { Debug::text( 'Setting User IDs : ', __FILE__, __LINE__, __METHOD__, 10 ); if ( !is_array( $ids ) ) { $ids = [ $ids ]; } if ( is_array( $ids ) && count( $ids ) > 0 ) { global $current_user; //Remove any of the selected employees from other permission control objects first. //So there we can switch employees from one group to another in a single action. $pulf = TTnew( 'PermissionUserListFactory' ); /** @var PermissionUserListFactory $pulf */ $pulf->getByCompanyIdAndUserIdAndNotPermissionControlId( $this->getCompany(), $ids, TTUUID::castUUID( $this->getId() ) ); if ( $pulf->getRecordCount() > 0 ) { Debug::text( 'Found User IDs assigned to another Permission Group, unassigning them!', __FILE__, __LINE__, __METHOD__, 10 ); foreach ( $pulf as $pu_obj ) { if ( !is_object( $current_user ) || ( is_object( $current_user ) && $current_user->getID() != $pu_obj->getUser() ) ) { //Not Acting on currently logged in user. $pu_obj->Delete(); } } } unset( $pulf, $pu_obj ); $tmp_ids = []; if ( !$this->isNew() ) { //If needed, delete mappings first. $pulf = TTnew( 'PermissionUserListFactory' ); /** @var PermissionUserListFactory $pulf */ $pulf->getByPermissionControlId( $this->getId() ); foreach ( $pulf as $obj ) { $id = $obj->getUser(); Debug::text( 'Permission Control ID: ' . $obj->getPermissionControl() . ' ID: ' . $id, __FILE__, __LINE__, __METHOD__, 10 ); //Delete users that are not selected. if ( !in_array( $id, $ids ) ) { if ( is_object( $current_user ) && $current_user->getID() == $id ) { //Not Acting on currently logged in user. $this->Validator->isTrue( 'user', false, TTi18n::gettext( 'Unable to remove your own record from a permission group' ) ); } else { Debug::text( 'Deleting: ' . $id, __FILE__, __LINE__, __METHOD__, 10 ); $this->tmp_previous_user_ids[] = $id; $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 ) ) { //Remove users from any other permission control object //first, otherwise there is a gap where an employee has //no permissions, this is especially bad for administrators //who are currently logged in. $puf = TTnew( 'PermissionUserFactory' ); /** @var PermissionUserFactory $puf */ $puf->setPermissionControl( $this->getId() ); $puf->setUser( $id ); $ulf->getById( $id ); if ( $ulf->getRecordCount() > 0 ) { $obj = $ulf->getCurrent(); if ( $this->Validator->isTrue( 'user', $puf->isValid(), TTi18n::gettext( 'Selected employee is already assigned to another permission group' ) . ' (' . $obj->getFullName() . ')' ) ) { $puf->save(); } } } } return true; } Debug::text( 'No User IDs to set.', __FILE__, __LINE__, __METHOD__, 10 ); return false; } /** * @return array */ function getPermissionOptions() { $product_edition = $this->getCompanyObject()->getProductEdition(); $retval = []; $pf = TTnew( 'PermissionFactory' ); /** @var PermissionFactory $pf */ $sections = $pf->getOptions( 'section' ); $names = $pf->getOptions( 'name' ); if ( is_array( $names ) ) { foreach ( $names as $section => $permission_arr ) { if ( ( $pf->isIgnore( $section, null, $product_edition ) == false ) ) { foreach ( $permission_arr as $name => $display_name ) { if ( $pf->isIgnore( $section, $name, $product_edition ) == false ) { if ( isset( $sections[$section] ) ) { $retval[$section][$name] = 0; } } } unset( $display_name ); //code standards } } } return $retval; } /** * @return array|bool */ function getPermission() { $plf = TTnew( 'PermissionListFactory' ); /** @var PermissionListFactory $plf */ $plf->getByCompanyIdAndPermissionControlId( $this->getCompany(), $this->getId() ); if ( $plf->getRecordCount() > 0 ) { $current_permissions = []; Debug::Text( 'Found Permissions: ' . $plf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10 ); foreach ( $plf as $p_obj ) { $current_permissions[$p_obj->getSection()][$p_obj->getName()] = $p_obj->getValue(); } return $current_permissions; } return false; } /** * @param $permission_arr * @param array $old_permission_arr * @return bool */ function setPermission( $permission_arr, $old_permission_arr = [] ) { if ( $this->getId() == false ) { return false; } if ( $this->Validator->getValidateOnly() == true ) { return true; } global $profiler, $config_vars; $profiler->startTimer( 'setPermission' ); //Since implementing the HTML5 Install Wizard, which uses the API, we have to check to see if the installer is enabled, and if so skip this next block of code. if ( defined( 'TIMETREX_API' ) && TIMETREX_API == true && ( isset( $config_vars['other']['installer_enabled'] ) && $config_vars['other']['installer_enabled'] != 1 ) ) { //When creating a new permission group this causes it to be really slow as it creates a record for every permission that is set to DENY. //If we do the permission diff it messes up the HTML interface. if ( !is_array( $old_permission_arr ) || ( is_array( $old_permission_arr ) && count( $old_permission_arr ) == 0 ) ) { $old_permission_arr = $this->getPermission(); //Debug::Text(' Old Permissions: '. count($old_permission_arr), __FILE__, __LINE__, __METHOD__, 10); } $permission_options = $this->getPermissionOptions(); //Debug::Arr($permission_options, ' Permission Options: '. count($permission_options), __FILE__, __LINE__, __METHOD__, 10); $permission_arr = Misc::arrayMergeRecursiveDistinct( (array)$permission_options, (array)$permission_arr ); //Debug::Text(' New Permissions: '. count($permission_arr), __FILE__, __LINE__, __METHOD__, 10); //Debug::Arr($permission_arr, ' Final Permissions: '. count($permission_arr), __FILE__, __LINE__, __METHOD__, 10); } $pf = TTnew( 'PermissionFactory' ); /** @var PermissionFactory $pf */ //Don't Delete all previous permissions, do that in the Permission class. if ( isset( $permission_arr ) && is_array( $permission_arr ) && count( $permission_arr ) > 0 ) { foreach ( $permission_arr as $section => $permissions ) { //Debug::Text(' Section: '. $section, __FILE__, __LINE__, __METHOD__, 10); foreach ( $permissions as $name => $value ) { //Debug::Text(' Name: '. $name .' - Value: '. $value, __FILE__, __LINE__, __METHOD__, 10); if ( ( !isset( $old_permission_arr[$section][$name] ) || ( isset( $old_permission_arr[$section][$name] ) && $value != $old_permission_arr[$section][$name] ) ) && $pf->isIgnore( $section, $name, $this->getCompanyObject()->getProductEdition() ) == false ) { if ( $value == 0 || $value == 1 ) { Debug::Text( ' Modifying/Adding Section: ' . $section . ' Permission: ' . $name . ' - Value: ' . $value, __FILE__, __LINE__, __METHOD__, 10 ); $tmp_pf = TTnew( 'PermissionFactory' ); /** @var PermissionFactory $tmp_pf */ $tmp_pf->setEnableSectionAndNameValidation( false ); //Disable error checking for performance optimization, as we know they are correct. $tmp_pf->setCompany( $this->getCompanyObject()->getId() ); $tmp_pf->setPermissionControl( $this->getId() ); $tmp_pf->setSection( $section ); $tmp_pf->setName( $name ); $tmp_pf->setValue( (int)$value ); if ( $tmp_pf->isValid() ) { $tmp_pf->save(); } } } //else { //Debug::Text(' Permission didnt change... Skipping', __FILE__, __LINE__, __METHOD__, 10); } } } $profiler->stopTimer( 'setPermission' ); return true; } /** * Quick way to touch the updated_date, updated_by when adding/removing employees from the UserFactory. * @param string $permission_control_id UUID * @return bool * @throws DBError */ function touchUpdatedByAndDate( $permission_control_id = null ) { global $current_user; if ( is_object( $current_user ) ) { $user_id = $current_user->getID(); } else { return false; } $ph = [ 'updated_date' => TTDate::getTime(), 'updated_by' => $user_id, 'id' => ( $permission_control_id == '' ) ? TTUUID::castUUID( $this->getID() ) : TTUUID::castUUID( $permission_control_id ), ]; $query = 'update ' . $this->getTable() . ' set updated_date = ?, updated_by = ? where id = ?'; $this->ExecuteSQL( $query, $ph ); return true; } /** * @return bool */ function Validate() { // // BELOW: Validation code moved from set*() functions. // // Company $clf = TTnew( 'CompanyListFactory' ); /** @var CompanyListFactory $clf */ $this->Validator->isResultSetWithRows( 'company', $clf->getByID( $this->getCompany() ), TTi18n::gettext( 'Company is invalid' ) ); // Name $this->Validator->isLength( 'name', $this->getName(), TTi18n::gettext( 'Name is invalid' ), 2, 50 ); 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, 255 ); } // Level $this->Validator->inArrayKey( 'level', $this->getLevel(), TTi18n::gettext( 'Incorrect Level' ), $this->getOptions( 'level' ) ); // // ABOVE: Validation code moved from set*() functions. // //Don't allow deleting permissions groups with users assigned to them, to prevent locking themselves out. if ( $this->getDeleted() == true ) { $users = $this->getUser(); if ( is_array( $users ) && count( $users ) > 0 ) { $this->Validator->isTRUE( 'in_use', false, TTi18n::gettext( 'This permission group is currently in use by employees' ) ); } unset( $users ); //Also check for users assigned by way of Terminated Permission Group $ulf = TTnew( 'UserListFactory' ); $ulf->getByCompanyIdAndTerminatedPermissionControl( $this->getCompany(), $this->getId(), 1 ); //Limit=1 if ( $ulf->getRecordCount() > 0 ) { $this->Validator->isTRUE( 'in_use', false, TTi18n::gettext( 'This permission group is currently in use by employees as their Terminated Permissions' ) ); } } return true; } /** * @return bool */ function preSave() { if ( $this->getLevel() == '' || $this->getLevel() == 0 ) { $this->setLevel( 1 ); } return true; } function postSave() { $this->removeCache( $this->getID() ); $this->removeCache( $this->getCompany() . $this->getID() ); //Used in PermissionControlListFactory::getByIdAndCompanyId() $pf = TTnew( 'PermissionFactory' ); /** @var PermissionFactory $pf */ $clear_cache_user_ids = array_merge( (array)$this->getUser(), (array)$this->tmp_previous_user_ids ); foreach ( $clear_cache_user_ids as $user_id ) { $pf->clearCache( $user_id, $this->getCompany() ); } if ( $this->getDeleted() == true ) { //Remove from permission group from any New Hire Defaults. $udlf = TTNew( 'UserDefaultListFactory' ); $udlf->getByCompanyId( $this->getCompany() ); if ( $udlf->getRecordCount() > 0 ) { foreach ( $udlf as $ud_obj ) { $update_record = false; if ( $ud_obj->getPermissionControl() == $this->getId() ) { $ud_obj->setPermissionControl( TTUUID::getZeroID() ); $update_record = true; } if ( $ud_obj->getTerminatedPermissionControl() == $this->getId() ) { $ud_obj->setTerminatedPermissionControl( TTUUID::getZeroID() ); $update_record = true; } if ( $update_record == true && $ud_obj->isValid() ) { $ud_obj->Save(); } } } unset( $udlf, $ud_obj ); } } /** * Support setting created_by, updated_by especially for importing data. * Make sure data is set based on the getVariableToFunctionMap order. * @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 ) { case 'total_users': $data[$variable] = $this->getColumn( $variable ); 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( 'Permission Group' ) . ': ' . $this->getName(), null, $this->getTable(), $this ); } } ?>