TimeTrex/classes/modules/message/MessageFactory.class.php

670 lines
18 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\Message
*/
class MessageFactory extends Factory {
protected $table = 'message';
protected $pk_sequence_name = 'message_id_seq'; //PK Sequence name
protected $obj_handler = null;
/**
* @param $name
* @param null $parent
* @return array|null
*/
function _getFactoryOptions( $name, $parent = null ) {
$retval = null;
switch ( $name ) {
case 'type':
$retval = [
5 => 'email',
//10 => 'default_schedule',
//20 => 'schedule_amendment',
//30 => 'shift_amendment',
40 => 'authorization',
50 => 'request',
60 => 'job',
70 => 'job_item',
80 => 'client',
90 => 'timesheet',
100 => 'user' //For notes assigned to users?
];
break;
case 'object_name':
$retval = [
5 => TTi18n::gettext( 'Email' ), //Email from user to another
10 => TTi18n::gettext( 'Recurring Schedule' ),
20 => TTi18n::gettext( 'Schedule Amendment' ),
30 => TTi18n::gettext( 'Shift Amendment' ),
40 => TTi18n::gettext( 'Authorization' ),
50 => TTi18n::gettext( 'Request' ),
60 => TTi18n::gettext( 'Job' ),
70 => TTi18n::gettext( 'Task' ),
80 => TTi18n::gettext( 'Client' ),
90 => TTi18n::gettext( 'TimeSheet' ),
100 => TTi18n::gettext( 'Employee' ) //For notes assigned to users?
];
break;
case 'folder':
$retval = [
10 => TTi18n::gettext( 'Inbox' ),
20 => TTi18n::gettext( 'Sent' ),
];
break;
case 'status':
$retval = [
10 => TTi18n::gettext( 'UNREAD' ),
20 => TTi18n::gettext( 'READ' ),
];
break;
case 'priority':
$retval = [
10 => TTi18n::gettext( 'LOW' ),
50 => TTi18n::gettext( 'NORMAL' ),
100 => TTi18n::gettext( 'HIGH' ),
110 => TTi18n::gettext( 'URGENT' ),
];
break;
}
return $retval;
}
/**
* @return bool|mixed
*/
function getParent() {
return $this->getGenericDataValue( 'parent_id' );
}
/**
* @param string $value UUID
* @return bool
*/
function setParent( $value ) {
$value = TTUUID::castUUID( $value );
return $this->setGenericDataValue( 'parent_id', $value );
}
/**
* @return null|object
*/
function getObjectHandler() {
if ( is_object( $this->obj_handler ) ) {
return $this->obj_handler;
} else {
switch ( $this->getObjectType() ) {
case 5:
case 100:
$this->obj_handler = TTnew( 'UserListFactory' );
break;
case 40:
$this->obj_handler = TTnew( 'AuthorizationListFactory' );
break;
case 50:
$this->obj_handler = TTnew( 'RequestListFactory' );
break;
case 90:
$this->obj_handler = TTnew( 'PayPeriodTimeSheetVerifyListFactory' );
break;
}
return $this->obj_handler;
}
}
/**
* @return bool|int
*/
function getObjectType() {
return $this->getGenericDataValue( 'object_type_id' );
}
/**
* @param $value
* @return bool
*/
function setObjectType( $value ) {
$value = (int)trim( $value );
return $this->setGenericDataValue( 'object_type_id', $value );
}
/**
* @return bool|mixed
*/
function getObject() {
return $this->getGenericDataValue( 'object_id' );
}
/**
* @param string $value UUID
* @return bool
*/
function setObject( $value ) {
$value = TTUUID::castUUID( $value );
return $this->setGenericDataValue( 'object_id', $value );
}
/**
* @return bool|int
*/
function getPriority() {
return $this->getGenericDataValue( 'priority_id' );
}
/**
* @param null $value
* @return bool
*/
function setPriority( $value = null ) {
$value = (int)trim( $value );
if ( empty( $value ) ) {
$value = 50;
}
return $this->setGenericDataValue( 'priority_id', $value );
}
/**
* @return bool|int
*/
function getStatus() {
return $this->getGenericDataValue( 'status_id' );
}
/**
* @param $value
* @return bool
*/
function setStatus( $value ) {
$value = (int)trim( $value );
$this->setStatusDate();
return $this->setGenericDataValue( 'status_id', $value );
}
/**
* @return bool|mixed
*/
function getStatusDate() {
return $this->getGenericDataValue( 'status_date' );
}
/**
* @param int $value EPOCH
* @return bool
*/
function setStatusDate( $value = null ) {
$value = ( !is_int( $value ) && $value !== null ) ? trim( $value ) : $value;//Dont trim integer values, as it changes them to strings.
if ( $value == null ) {
$value = TTDate::getTime();
}
return $this->setGenericDataValue( 'status_date', $value );
}
/**
* @return bool|mixed
*/
function getSubject() {
return $this->getGenericDataValue( 'subject' );
}
/**
* @param $value
* @return bool
*/
function setSubject( $value ) {
$value = trim( $value );
return $this->setGenericDataValue( 'subject', $value );
}
/**
* @return bool|mixed
*/
function getBody() {
return $this->getGenericDataValue( 'body' );
}
/**
* @param $value
* @return bool
*/
function setBody( $value ) {
$value = trim( $value );
return $this->setGenericDataValue( 'body', $value );
}
/**
* @return bool
*/
function isAck() {
if ( $this->getRequireAck() == true && $this->getAckDate() == '' ) {
return false;
}
return true;
}
/**
* @return bool
*/
function getRequireAck() {
return $this->fromBool( $this->getGenericDataValue( 'require_ack' ) );
}
/**
* @param $value
* @return bool
*/
function setRequireAck( $value ) {
return $this->setGenericDataValue( 'require_ack', $this->toBool( $value ) );
}
/**
* @return bool
*/
function getAck() {
return $this->fromBool( $this->getGenericDataValue( 'ack' ) );
}
/**
* @param $value
* @return bool
*/
function setAck( $value ) {
$this->setGenericDataValue( 'ack', $this->toBool( $value ) );
if ( $this->getAck() == true ) {
$this->setAckDate();
$this->setAckBy();
}
return true;
}
/**
* @return bool|mixed
*/
function getAckDate() {
return $this->getGenericDataValue( 'ack_date' );
}
/**
* @param int $value EPOCH
* @return bool
*/
function setAckDate( $value = null ) {
$value = ( !is_int( $value ) && $value !== null ) ? trim( $value ) : $value;//Dont trim integer values, as it changes them to strings.
if ( $value == null ) {
$value = TTDate::getTime();
}
return $this->setGenericDataValue( 'ack_date', $value );
}
/**
* @return bool|mixed
*/
function getAckBy() {
return $this->getGenericDataValue( 'ack_by' );
}
/**
* @param string $value UUID
* @return bool
*/
function setAckBy( $value = null ) {
$value = trim( $value );
if ( empty( $value ) ) {
global $current_user;
if ( is_object( $current_user ) ) {
$value = $current_user->getID();
} else {
return false;
}
}
return $this->setGenericDataValue( 'ack_by', $value );
}
/**
* @return array|bool
*/
function getEmailMessageAddresses() {
$olf = $this->getObjectHandler();
if ( is_object( $olf ) ) {
$user_ids = [];
$olf->getById( $this->getObject() );
if ( $olf->getRecordCount() > 0 ) {
$obj = $olf->getCurrent();
switch ( $this->getObjectType() ) {
case 5:
case 100:
Debug::Text( 'Email Object Type... Parent ID: ' . $this->getParent(), __FILE__, __LINE__, __METHOD__, 10 );
if ( $this->getParent() == TTUUID::getZeroID() ) {
$user_ids[] = $obj->getId();
} else {
$mlf = TTnew( 'MessageListFactory' ); /** @var MessageListFactory $mlf */
$mlf->getById( $this->getParent() );
if ( $mlf->getRecordCount() > 0 ) {
$m_obj = $mlf->getCurrent();
$user_ids[] = $m_obj->getCreatedBy();
}
Debug::Text( 'cEmail Object Type... Parent ID: ' . $this->getParent(), __FILE__, __LINE__, __METHOD__, 10 );
}
break;
case 40:
$user_ids[] = $obj->getId();
break;
case 50: //Request
//Get all users who have contributed to the thread.
$mlf = TTnew( 'MessageListFactory' ); /** @var MessageListFactory $mlf */
$mlf->getMessagesInThreadById( $this->getId() );
Debug::Text( ' Messages In Thread: ' . $mlf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10 );
if ( $mlf->getRecordCount() > 0 ) {
foreach ( $mlf as $m_obj ) {
$user_ids[] = $m_obj->getCreatedBy();
}
}
unset( $mlf, $m_obj );
//Debug::Arr($user_ids, 'User IDs in Thread: ', __FILE__, __LINE__, __METHOD__, 10);
//Only alert direct supervisor to request at this point. Because we need to take into account
//if the request was authorized or not to determine if we should email the next higher level in the hierarchy.
if ( $this->getParent() == TTUUID::getZeroID() ) {
//Get direct parent in hierarchy.
$u_obj = $obj->getUserObject();
$hlf = TTnew( 'HierarchyListFactory' ); /** @var HierarchyListFactory $hlf */
$user_ids[] = $hlf->getHierarchyParentByCompanyIdAndUserIdAndObjectTypeID( $u_obj->getCompany(), $u_obj->getId(), $this->getObjectType(), true, false );
unset( $hlf );
}
global $current_user;
if ( isset( $current_user ) && is_object( $current_user ) && isset( $user_ids ) && is_array( $user_ids ) ) {
$user_ids = array_unique( $user_ids );
$current_user_key = array_search( $current_user->getId(), $user_ids );
Debug::Text( ' Current User Key: ' . $current_user_key, __FILE__, __LINE__, __METHOD__, 10 );
if ( $current_user_key !== false ) {
Debug::Text( ' Removing Current User From Recipient List...' . $current_user->getId(), __FILE__, __LINE__, __METHOD__, 10 );
unset( $user_ids[$current_user_key] );
}
} else {
Debug::Text( ' Current User Object not available...', __FILE__, __LINE__, __METHOD__, 10 );
}
unset( $current_user_key );
break;
case 90:
$user_ids[] = $obj->getUser();
break;
}
}
if ( empty( $user_ids ) == false ) {
//Get user preferences and determine if they accept email notifications.
Debug::Arr( $user_ids, 'Recipient User Ids: ', __FILE__, __LINE__, __METHOD__, 10 );
$uplf = TTnew( 'UserPreferenceListFactory' ); /** @var UserPreferenceListFactory $uplf */
$uplf->getByUserId( $user_ids );
if ( $uplf->getRecordCount() > 0 ) {
$retarr = [];
foreach ( $uplf as $up_obj ) {
if ( $up_obj->getEnableEmailNotificationMessage() == true && $up_obj->getUserObject()->getStatus() == 10 ) {
if ( $up_obj->getUserObject()->getWorkEmail() != '' ) {
$retarr[] = Misc::formatEmailAddress( $up_obj->getUserObject()->getWorkEmail(), $up_obj->getUserObject() );
}
if ( $up_obj->getEnableEmailNotificationHome() && $up_obj->getUserObject()->getHomeEmail() != '' ) {
$retarr[] = Misc::formatEmailAddress( $up_obj->getUserObject()->getHomeEmail(), $up_obj->getUserObject() );
}
}
}
if ( empty( $retarr ) == false ) {
Debug::Arr( $retarr, 'Recipient Email Addresses: ', __FILE__, __LINE__, __METHOD__, 10 );
return $retarr;
}
}
}
}
return false;
}
/**
* @return bool
*/
function emailMessage() {
Debug::Text( 'emailMessage: ', __FILE__, __LINE__, __METHOD__, 10 );
$email_to_arr = $this->getEmailMessageAddresses();
if ( $email_to_arr == false ) {
return false;
}
$from = $reply_to = '"' . APPLICATION_NAME . ' - ' . TTi18n::gettext( 'Message' ) . '" <' . Misc::getEmailLocalPart() . '@' . Misc::getEmailDomain() . '>';
global $current_user;
if ( is_object( $current_user ) && $current_user->getWorkEmail() != '' ) {
$reply_to = Misc::formatEmailAddress( $current_user->getWorkEmail(), $current_user );
}
Debug::Text( 'From: ' . $from . ' Reply-To: ' . $reply_to, __FILE__, __LINE__, __METHOD__, 10 );
$to = array_shift( $email_to_arr );
Debug::Text( 'To: ' . $to, __FILE__, __LINE__, __METHOD__, 10 );
if ( is_array( $email_to_arr ) && count( $email_to_arr ) > 0 ) {
$bcc = implode( ',', $email_to_arr );
} else {
$bcc = null;
}
$email_subject = TTi18n::gettext( 'New message waiting in' ) . ' ' . APPLICATION_NAME;
$email_body = TTi18n::gettext( '*DO NOT REPLY TO THIS EMAIL - PLEASE USE THE LINK BELOW INSTEAD*' ) . "\n\n";
$email_body .= TTi18n::gettext( 'You have a new message waiting for you in' ) . ' ' . APPLICATION_NAME . "\n";
if ( $this->getSubject() != '' ) {
$email_body .= TTi18n::gettext( 'Subject' ) . ': ' . $this->getSubject() . "\n";
}
$email_body .= TTi18n::gettext( 'Link' ) . ': <a href="' . Misc::getURLProtocol() . '://' . Misc::getHostName() . Environment::getDefaultInterfaceBaseURL() . '">' . APPLICATION_NAME . ' ' . TTi18n::getText( 'Login' ) . '</a>';
//Define subject/body variables here.
$search_arr = [
'#employee_first_name#',
'#employee_last_name#',
];
$replace_arr = [
null,
null,
];
$subject = str_replace( $search_arr, $replace_arr, $email_subject );
Debug::Text( 'Subject: ' . $subject, __FILE__, __LINE__, __METHOD__, 10 );
$headers = [
'From' => $from,
'Subject' => $subject,
'Bcc' => $bcc,
//Reply-To/Return-Path are handled in TTMail.
];
$body = '<pre>' . str_replace( $search_arr, $replace_arr, $email_body ) . '</pre>';
Debug::Text( 'Body: ' . $body, __FILE__, __LINE__, __METHOD__, 10 );
$mail = new TTMail();
$mail->setTo( $to );
$mail->setHeaders( $headers );
@$mail->getMIMEObject()->setHTMLBody( $body );
$mail->setBody( $mail->getMIMEObject()->get( $mail->default_mime_config ) );
$retval = $mail->Send();
if ( $retval == true ) {
TTLog::addEntry( $this->getId(), 500, TTi18n::getText( 'Email Message to' ) . ': ' . $to . ' Bcc: ' . $headers['Bcc'], null, $this->getTable() );
return true;
}
return true; //Always return true
}
/**
* @return bool
*/
function Validate() {
//
// BELOW: Validation code moved from set*() functions.
//
// Parent
if ( $this->getParent() != TTUUID::getZeroID() ) {
$mlf = TTnew( 'MessageListFactory' ); /** @var MessageListFactory $mlf */
$this->Validator->isResultSetWithRows( 'parent',
$mlf->getByID( $this->getParent() ),
TTi18n::gettext( 'Parent is invalid' )
);
}
// Object Type
$this->Validator->inArrayKey( 'object_type',
$this->getObjectType(),
TTi18n::gettext( 'Object Type is invalid' ),
$this->getOptions( 'type' )
);
// Object ID
$this->Validator->isResultSetWithRows( 'object',
$this->getObjectHandler()->getByID( $this->getObject() ),
TTi18n::gettext( 'Object ID is invalid' )
);
// Priority
$this->Validator->inArrayKey( 'priority',
$this->getPriority(),
TTi18n::gettext( 'Invalid Priority' ),
$this->getOptions( 'priority' )
);
// Status
$this->Validator->inArrayKey( 'status',
$this->getStatus(),
TTi18n::gettext( 'Incorrect Status' ),
$this->getOptions( 'status' )
);
// Date
$this->Validator->isDate( 'status_date',
$this->getStatusDate(),
TTi18n::gettext( 'Incorrect Date' )
);
// Subject
if ( $this->getSubject() != '' ) {
$this->Validator->isLength( 'subject',
$this->getSubject(),
TTi18n::gettext( 'Invalid Subject length' ),
2,
100
);
}
// Body
$this->Validator->isLength( 'body',
$this->getBody(),
TTi18n::gettext( 'Invalid Body length' ),
2, //Allow the word: "ok", or "done" to at least be a response.
1024
);
// Acknowledge Date
$this->Validator->isDate( 'ack_date',
$this->getAckDate(),
TTi18n::gettext( 'Invalid Acknowledge Date' )
);
// User
$ulf = TTnew( 'UserListFactory' ); /** @var UserListFactory $ulf */
$this->Validator->isResultSetWithRows( 'ack_by',
$ulf->getByID( $this->getAckBy() ),
TTi18n::gettext( 'Incorrect User' )
);
//
// ABOVE: Validation code moved from set*() functions.
//
return true;
}
/**
* @return bool
*/
function postSave() {
//Only email message notifications when they are not deleted and UNREAD still. Other it may email when a message is marked as read as well.
//Don't email messages when they are being deleted.
if ( $this->getDeleted() == false && $this->getStatus() == 10 ) {
$this->emailMessage();
}
if ( $this->getStatus() == 20 ) {
global $current_user;
$this->removeCache( $current_user->getId() );
}
return true;
}
}
?>