2017-02-23 22:04:56 -05:00
< ? php
namespace BusinessLogic\Emails ;
use BusinessLogic\Exceptions\EmailTemplateNotFoundException ;
use BusinessLogic\Exceptions\InvalidEmailTemplateException ;
2018-03-02 12:25:37 -05:00
use BusinessLogic\Security\UserContext ;
2017-02-24 22:01:54 -05:00
use BusinessLogic\Statuses\DefaultStatusForAction ;
2017-02-23 22:04:56 -05:00
use BusinessLogic\Tickets\Ticket ;
2017-02-24 22:01:54 -05:00
use Core\Constants\Priority ;
use DataAccess\Categories\CategoryGateway ;
2018-03-02 12:25:37 -05:00
use DataAccess\Logging\LoggingGateway ;
2017-02-26 21:52:12 -05:00
use DataAccess\Security\UserGateway ;
2017-02-23 22:04:56 -05:00
use DataAccess\Statuses\StatusGateway ;
2017-09-11 21:03:03 -04:00
class EmailTemplateParser extends \BaseClass {
2017-02-23 22:04:56 -05:00
/**
* @ var $statusGateway StatusGateway
*/
private $statusGateway ;
2017-02-24 22:01:54 -05:00
/**
* @ var $categoryGateway CategoryGateway
*/
private $categoryGateway ;
2017-02-26 21:52:12 -05:00
/**
* @ var $userGateway UserGateway
*/
private $userGateway ;
2017-03-02 22:05:28 -05:00
/**
* @ var $emailTemplateRetriever EmailTemplateRetriever
*/
private $emailTemplateRetriever ;
2018-03-02 12:25:37 -05:00
/**
* @ var $logger LoggingGateway
*/
private $logger ;
2017-09-07 20:31:57 -04:00
function __construct ( StatusGateway $statusGateway ,
CategoryGateway $categoryGateway ,
UserGateway $userGateway ,
2018-03-02 12:25:37 -05:00
EmailTemplateRetriever $emailTemplateRetriever ,
LoggingGateway $loggingGateway ) {
2017-02-23 22:04:56 -05:00
$this -> statusGateway = $statusGateway ;
2017-02-24 22:01:54 -05:00
$this -> categoryGateway = $categoryGateway ;
2017-02-26 21:52:12 -05:00
$this -> userGateway = $userGateway ;
2017-03-02 22:05:28 -05:00
$this -> emailTemplateRetriever = $emailTemplateRetriever ;
2018-03-02 12:25:37 -05:00
$this -> logger = $loggingGateway ;
2017-02-23 22:04:56 -05:00
}
/**
2017-03-02 22:05:28 -05:00
* @ param $templateId int
2017-03-03 22:05:41 -05:00
* @ param $languageCode string
2017-02-23 22:04:56 -05:00
* @ param $ticket Ticket
2017-03-02 22:05:28 -05:00
* @ param $heskSettings array
* @ param $modsForHeskSettings array
* @ return ParsedEmailProperties
* @ throws InvalidEmailTemplateException
2017-09-07 20:31:57 -04:00
* @ throws \Exception
2017-02-23 22:04:56 -05:00
*/
2017-03-03 22:05:41 -05:00
function getFormattedEmailForLanguage ( $templateId , $languageCode , $ticket , $heskSettings , $modsForHeskSettings ) {
2017-03-12 01:06:50 -05:00
global $hesklang ;
2017-03-02 22:05:28 -05:00
$emailTemplate = $this -> emailTemplateRetriever -> getTemplate ( $templateId );
2017-02-23 22:04:56 -05:00
2017-03-02 22:05:28 -05:00
if ( $emailTemplate === null ) {
throw new InvalidEmailTemplateException ( $templateId );
}
2017-03-03 22:05:41 -05:00
$template = self :: getFromFileSystem ( $emailTemplate -> fileName , $languageCode , false );
$htmlTemplate = self :: getFromFileSystem ( $emailTemplate -> fileName , $languageCode , true );
2017-03-12 01:06:50 -05:00
$subject = $hesklang [ $emailTemplate -> languageKey ];
2017-02-23 22:04:56 -05:00
2017-05-01 22:05:21 -04:00
$fullLanguageName = null ;
foreach ( $heskSettings [ 'languages' ] as $key => $value ) {
if ( $value [ 'folder' ] === $languageCode ) {
$fullLanguageName = $key ;
break ;
}
}
if ( $fullLanguageName === null ) {
2017-09-11 21:17:34 -04:00
throw new \BaseException ( " Language code { $languageCode } did not return any valid HESK languages! " );
2017-05-01 22:05:21 -04:00
}
2017-09-11 21:17:34 -04:00
$subject = $this -> parseSubject ( $subject , $ticket , $fullLanguageName , $heskSettings , $modsForHeskSettings );
2017-05-01 22:05:21 -04:00
$message = $this -> parseMessage ( $template , $ticket , $fullLanguageName , $emailTemplate -> forStaff , $heskSettings , $modsForHeskSettings , false );
$htmlMessage = $this -> parseMessage ( $htmlTemplate , $ticket , $fullLanguageName , $emailTemplate -> forStaff , $heskSettings , $modsForHeskSettings , true );
2017-02-28 22:03:08 -05:00
return new ParsedEmailProperties ( $subject , $message , $htmlMessage );
2017-02-23 22:04:56 -05:00
}
2017-02-26 21:52:12 -05:00
/**
* @ param $template string
* @ param $language string
* @ param $html bool
* @ return string The template
* @ throws EmailTemplateNotFoundException If the template was not found in the filesystem for the provided language
*/
private function getFromFileSystem ( $template , $language , $html )
2017-02-23 22:04:56 -05:00
{
2017-02-26 21:52:12 -05:00
$htmlFolder = $html ? 'html/' : '' ;
2017-02-23 22:04:56 -05:00
/* Get email template */
2017-02-26 21:52:12 -05:00
$file = " language/ { $language } /emails/ { $htmlFolder } { $template } .txt " ;
2017-02-23 22:04:56 -05:00
$absoluteFilePath = __DIR__ . '/../../../' . $file ;
if ( file_exists ( $absoluteFilePath )) {
return file_get_contents ( $absoluteFilePath );
} else {
throw new EmailTemplateNotFoundException ( $template , $language );
}
}
2017-02-24 22:01:54 -05:00
/**
* @ param $subjectTemplate string
* @ param $ticket Ticket
* @ param $language string
* @ param $heskSettings array
* @ return string
2017-02-26 21:52:12 -05:00
* @ throws \Exception if common . inc . php isn ' t loaded
2017-02-24 22:01:54 -05:00
*/
2017-09-11 21:17:34 -04:00
private function parseSubject ( $subjectTemplate , $ticket , $language , $heskSettings , $modsForHeskSettings ) {
2017-02-24 22:01:54 -05:00
global $hesklang ;
2017-02-26 21:52:12 -05:00
if ( ! function_exists ( 'hesk_msgToPlain' )) {
2017-09-11 21:17:34 -04:00
throw new \BaseException ( " common.inc.php not loaded! " );
2017-02-26 21:52:12 -05:00
}
2017-02-23 22:04:56 -05:00
if ( $ticket === null ) {
return $subjectTemplate ;
}
2017-02-24 22:01:54 -05:00
// Status name and category name
$defaultStatus = $this -> statusGateway -> getStatusForDefaultAction ( DefaultStatusForAction :: NEW_TICKET , $heskSettings );
2018-03-02 12:25:37 -05:00
if ( key_exists ( $language , $defaultStatus -> localizedNames )) {
$statusName = $defaultStatus -> localizedNames [ $language ];
} elseif ( key_exists ( 'English' , $defaultStatus -> localizedNames )) {
$statusName = $defaultStatus -> localizedNames [ 'English' ];
$this -> logger -> logWarning ( 'EmailTemplateParser' , " No localized status found for status ' { $defaultStatus -> id } ' and language ' { $language } '. Defaulted to English. " , " " , new UserContext (), $heskSettings );
} else {
$statusName = " [ERROR: No localized status found for status ' { $defaultStatus -> id } '] " ;
$this -> logger -> logError ( 'EmailTemplateParser' , " No localized status found for status ' { $defaultStatus -> id } ' " , " " , new UserContext (), $heskSettings );
}
2017-09-11 21:17:34 -04:00
$categories = $this -> categoryGateway -> getAllCategories ( $heskSettings , $modsForHeskSettings );
$category = null ;
foreach ( $categories as $innerCategory ) {
if ( $innerCategory -> id === $ticket -> categoryId ) {
$category = $innerCategory ;
break ;
}
}
2017-02-24 22:01:54 -05:00
switch ( $ticket -> priorityId ) {
case Priority :: CRITICAL :
$priority = $hesklang [ 'critical' ];
break ;
case Priority :: HIGH :
$priority = $hesklang [ 'high' ];
break ;
case Priority :: MEDIUM :
$priority = $hesklang [ 'medium' ];
break ;
case Priority :: LOW :
$priority = $hesklang [ 'low' ];
break ;
default :
$priority = 'PRIORITY NOT FOUND' ;
break ;
}
// Special tags
2017-02-26 21:52:12 -05:00
$subject = str_replace ( '%%SUBJECT%%' , $ticket -> subject , $subjectTemplate );
$subject = str_replace ( '%%TRACK_ID%%' , $ticket -> trackingId , $subject );
$subject = str_replace ( '%%CATEGORY%%' , $category -> id , $subject );
$subject = str_replace ( '%%PRIORITY%%' , $priority , $subject );
$subject = str_replace ( '%%STATUS%%' , $statusName , $subject );
return $subject ;
}
/**
* @ param $messageTemplate string
* @ param $ticket Ticket
* @ param $language string
* @ param $heskSettings array
* @ return string
* @ throws \Exception if common . inc . php isn ' t loaded
*/
2017-02-28 22:03:08 -05:00
private function parseMessage ( $messageTemplate , $ticket , $language , $admin , $heskSettings , $modsForHeskSettings , $html ) {
2017-02-26 21:52:12 -05:00
global $hesklang ;
if ( ! function_exists ( 'hesk_msgToPlain' )) {
2017-09-11 21:17:34 -04:00
throw new \BaseException ( " common.inc.php not loaded! " );
2017-02-26 21:52:12 -05:00
}
if ( $ticket === null ) {
return $messageTemplate ;
}
$heskSettings [ 'site_title' ] = hesk_msgToPlain ( $heskSettings [ 'site_title' ], 1 );
// Is email required to view ticket (for customers only)?
2017-05-04 16:15:11 +00:00
$heskSettings [ 'e_param' ] = $heskSettings [ 'email_view_ticket' ] ? '&e=' . rawurlencode ( implode ( ';' , $ticket -> email )) : '' ;
2017-02-26 21:52:12 -05:00
/* Generate the ticket URLs */
$trackingURL = $heskSettings [ 'hesk_url' ];
$trackingURL .= $admin ? '/' . $heskSettings [ 'admin_dir' ] . '/admin_ticket.php' : '/ticket.php' ;
2017-02-27 21:24:24 -05:00
$trackingURL .= '?track=' . $ticket -> trackingId . ( $admin ? '' : $heskSettings [ 'e_param' ]) . '&Refresh=' . rand ( 10000 , 99999 );
2017-02-26 21:52:12 -05:00
// Status name and category name
$defaultStatus = $this -> statusGateway -> getStatusForDefaultAction ( DefaultStatusForAction :: NEW_TICKET , $heskSettings );
2017-05-01 22:05:21 -04:00
$statusName = hesk_msgToPlain ( $defaultStatus -> localizedNames [ $language ]);
2017-09-11 21:17:34 -04:00
$categories = $this -> categoryGateway -> getAllCategories ( $heskSettings , $modsForHeskSettings );
$category = null ;
foreach ( $categories as $innerCategory ) {
if ( $innerCategory -> id === $ticket -> categoryId ) {
$category = $innerCategory ;
break ;
}
}
$category = hesk_msgToPlain ( $category -> name );
2017-07-30 15:05:53 -04:00
$owner = $this -> userGateway -> getUserById ( $ticket -> ownerId , $heskSettings );
$ownerName = $owner === null ? $hesklang [ 'unas' ] : hesk_msgToPlain ( $owner -> name );
2017-02-26 21:52:12 -05:00
switch ( $ticket -> priorityId ) {
case Priority :: CRITICAL :
$priority = $hesklang [ 'critical' ];
break ;
case Priority :: HIGH :
$priority = $hesklang [ 'high' ];
break ;
case Priority :: MEDIUM :
$priority = $hesklang [ 'medium' ];
break ;
case Priority :: LOW :
$priority = $hesklang [ 'low' ];
break ;
default :
$priority = 'PRIORITY NOT FOUND' ;
break ;
}
// Special tags
$msg = str_replace ( '%%NAME%%' , $ticket -> name , $messageTemplate );
2017-02-27 21:24:24 -05:00
$msg = str_replace ( '%%SUBJECT%%' , $ticket -> subject , $msg );
$msg = str_replace ( '%%TRACK_ID%%' , $ticket -> trackingId , $msg );
2017-02-26 21:52:12 -05:00
$msg = str_replace ( '%%TRACK_URL%%' , $trackingURL , $msg );
2017-02-27 21:24:24 -05:00
$msg = str_replace ( '%%SITE_TITLE%%' , $heskSettings [ 'site_title' ], $msg );
$msg = str_replace ( '%%SITE_URL%%' , $heskSettings [ 'site_url' ], $msg );
$msg = str_replace ( '%%CATEGORY%%' , $category , $msg );
$msg = str_replace ( '%%PRIORITY%%' , $priority , $msg );
2017-07-30 15:05:53 -04:00
$msg = str_replace ( '%%OWNER%%' , $ownerName , $msg );
2017-02-27 21:24:24 -05:00
$msg = str_replace ( '%%STATUS%%' , $statusName , $msg );
2017-09-25 21:50:11 -04:00
$msg = str_replace ( '%%EMAIL%%' , implode ( ';' , $ticket -> email ), $msg );
2017-02-27 21:24:24 -05:00
$msg = str_replace ( '%%CREATED%%' , $ticket -> dateCreated , $msg );
$msg = str_replace ( '%%UPDATED%%' , $ticket -> lastChanged , $msg );
$msg = str_replace ( '%%ID%%' , $ticket -> id , $msg );
2017-11-20 22:16:46 -05:00
$msg = str_replace ( '%%TIME_WORKED%%' , $ticket -> timeWorked , $msg );
$lastReplyBy = '' ;
// Get the last reply by
if ( ! empty ( $ticket -> lastReplier )) {
2017-11-21 12:58:04 -05:00
$lastReplyBy = $ticket -> lastReplier ;
2017-11-20 22:16:46 -05:00
} else {
$lastReplyBy = $ticket -> name ;
}
$msg = str_replace ( '%%LAST_REPLY_BY%%' , $lastReplyBy , $msg );
2017-02-27 21:24:24 -05:00
2017-02-28 22:03:08 -05:00
/* All custom fields */
for ( $i = 1 ; $i <= 50 ; $i ++ ) {
$k = 'custom' . $i ;
2017-05-01 22:05:21 -04:00
if ( isset ( $heskSettings [ 'custom_fields' ][ $k ]) && isset ( $ticket -> customFields [ $i ])) {
2017-02-28 22:03:08 -05:00
$v = $heskSettings [ 'custom_fields' ][ $k ];
switch ( $v [ 'type' ]) {
case 'checkbox' :
$ticket -> customFields [ $i ] = str_replace ( " <br> " , " \n " , $ticket -> customFields [ $i ]);
break ;
case 'date' :
$ticket -> customFields [ $i ] = hesk_custom_date_display_format ( $ticket -> customFields [ $i ], $v [ 'value' ][ 'date_format' ]);
break ;
}
$msg = str_replace ( '%%' . strtoupper ( $k ) . '%%' , stripslashes ( $ticket -> customFields [ $i ]), $msg );
} else {
$msg = str_replace ( '%%' . strtoupper ( $k ) . '%%' , '' , $msg );
}
}
// Is message tag in email template?
if ( strpos ( $msg , '%%MESSAGE%%' ) !== false ) {
// Replace message
if ( $html ) {
2017-05-04 16:15:11 +00:00
$htmlMessage = html_entity_decode ( $ticket -> message );
$htmlMessage = nl2br ( $htmlMessage );
2017-02-28 22:03:08 -05:00
$msg = str_replace ( '%%MESSAGE%%' , $htmlMessage , $msg );
} else {
$plainTextMessage = $ticket -> message ;
$messageHtml = $ticket -> usesHtml ;
if ( count ( $ticket -> replies ) > 0 ) {
$lastReply = end ( $ticket -> replies );
$messageHtml = $lastReply -> usesHtml ;
}
if ( $messageHtml ) {
if ( ! function_exists ( 'convert_html_to_text' )) {
require ( __DIR__ . '/../../../inc/html2text/html2text.php' );
}
$plainTextMessage = convert_html_to_text ( $plainTextMessage );
$plainTextMessage = fix_newlines ( $plainTextMessage );
}
$msg = str_replace ( '%%MESSAGE%%' , $plainTextMessage , $msg );
}
// Add direct links to any attachments at the bottom of the email message
if ( $heskSettings [ 'attachments' ][ 'use' ] && isset ( $ticket -> attachments ) && count ( $ticket -> attachments ) > 0 ) {
if ( ! $modsForHeskSettings [ 'attachments' ]) {
if ( $html ) {
$msg .= " <br><br><br> " . $hesklang [ 'fatt' ];
} else {
$msg .= " \n \n \n " . $hesklang [ 'fatt' ];
}
foreach ( $ticket -> attachments as $attachment ) {
if ( $html ) {
$msg .= " <br><br> { $attachment -> fileName } <br> " ;
} else {
$msg .= " \n \n { $attachment -> fileName } \n " ;
}
$msg .= " { $heskSettings [ 'hesk_url' ] } /download_attachment.php?att_id= { $attachment -> id } &track= { $ticket -> trackingId } { $heskSettings [ 'e_param' ] } " ;
}
}
}
// For customer notifications: if we allow email piping/pop 3 fetching and
// stripping quoted replies add an "reply above this line" tag
if ( ! $admin && ( $heskSettings [ 'email_piping' ] || $heskSettings [ 'pop3' ]) && $heskSettings [ 'strip_quoted' ]) {
$msg = $hesklang [ 'EMAIL_HR' ] . " \n \n " . $msg ;
}
} elseif ( strpos ( $msg , '%%MESSAGE_NO_ATTACHMENTS%%' ) !== false ) {
if ( $html ) {
$htmlMessage = nl2br ( $ticket -> message );
$msg = str_replace ( '%%MESSAGE_NO_ATTACHMENTS%%' , $htmlMessage , $msg );
} else {
$plainTextMessage = $ticket -> message ;
$messageHtml = $ticket -> usesHtml ;
if ( count ( $ticket -> replies ) > 0 ) {
$lastReply = end ( $ticket -> replies );
$messageHtml = $lastReply -> usesHtml ;
}
if ( $messageHtml ) {
if ( ! function_exists ( 'convert_html_to_text' )) {
require ( __DIR__ . '/../../../inc/html2text/html2text.php' );
}
$plainTextMessage = convert_html_to_text ( $plainTextMessage );
$plainTextMessage = fix_newlines ( $plainTextMessage );
}
$msg = str_replace ( '%%MESSAGE_NO_ATTACHMENTS%%' , $plainTextMessage , $msg );
}
}
2017-02-27 21:24:24 -05:00
return $msg ;
2017-02-23 22:04:56 -05:00
}
}