Skip to content

Commit

Permalink
Dev: fixes for failed_emails
Browse files Browse the repository at this point in the history
LSC-267: better visible intention is_null instead of isset
LSC-267: added description to getResponseURL() and return string allways
LSC-267: adjusted tests for failed_emails
LSC-267: added responseid to failed_emails // fixed LEM replacements to be set correctly when resending failed_emails
LSC-267: renamed table to failed_emails
  • Loading branch information
ptelu committed Aug 25, 2022
1 parent 6e76533 commit 61e8ce1
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 83 deletions.
5 changes: 3 additions & 2 deletions application/controllers/FailedEmailController.php
Expand Up @@ -71,21 +71,22 @@ public function actionResend()
App()->user->setFlash('error', gT("You do not have permission to access this page."));
$this->redirect(['failedEmail/index/', 'surveyid' => $surveyId]);
}
$preserveResend = App()->request->getParam('preserveResend') ?? false;
$preserveResend = App()->request->getParam('preserveResend');
$preserveResend = !is_null($preserveResend);
$item = [App()->request->getParam('item')];
$items = json_decode(App()->request->getParam('sItems'));
$selectedItems = $items ?? $item;
$emailsByType = [];
if (!empty($selectedItems)) {
$criteria = new CDbCriteria();
$criteria->select = 'id, email_type, recipient';
$criteria->addCondition('surveyid = ' . (int) $surveyId);
$criteria->addInCondition('id', $selectedItems);
$failedEmails = FailedEmail::model()->findAll($criteria);
if (!empty($failedEmails)) {
foreach ($failedEmails as $failedEmail) {
$emailsByType[$failedEmail->email_type][] = [
'id' => $failedEmail->id,
'responseId' => $failedEmail->responseid,
'recipient' => $failedEmail->recipient,
'language' => $failedEmail->language,
];
Expand Down
6 changes: 3 additions & 3 deletions application/controllers/admin/Authentication.php
Expand Up @@ -382,7 +382,7 @@ private function redirectIfLoggedIn()
/**
* Redirect after login.
* Do a db update if any exists.
* Clean failed_email table (delete entries older then 30days)
* Clean failed_emails table (delete entries older then 30days)
*
* @return void
*/
Expand All @@ -396,7 +396,7 @@ private static function doRedirect()
}

/**
* Delete all entries from failed_email table which are older then 30days
* Delete all entries from failed_emails table which are older then 30days
*
* @return void
*/
Expand All @@ -417,7 +417,7 @@ private static function cleanFailedEmailTable()
}

/**
* Checks failed_email table for entries for this user and creates a UniqueNotification
* Checks failed_emails table for entries for this user and creates a UniqueNotification
*
* @return void
*/
Expand Down
123 changes: 70 additions & 53 deletions application/helpers/frontend_helper.php
Expand Up @@ -439,7 +439,7 @@ function submittokens($quotaexit = false)
/**
* Send a submit notification to the email address specified in the notifications tab in the survey settings
* @throws CException
* @param array $emails Emailnotifications that should be sent ['responseTo' => ['failedEmailId' => 'failedEmailId1, 'recipient' => recipient1']['language' => 'language1'][...]], 'notificationTo' => [[..., ..., ...][...]]]
* @param array $emails Emailnotifications that should be sent ['responseTo' => [['failedEmailId' => 'failedEmailId1', 'responseid' => 'responseid1', 'recipient' => 'recipient1', 'language' => 'language1'], [...]], 'notificationTo' => [[..., ..., ...][...]]]
* @param boolean $preserveResend whether previously failed emails should be kept in the FailedEmail table after a successfull resend
* @param bool $return whether the function should return values
* @param int $surveyid survey ID of currently used survey
Expand All @@ -448,28 +448,41 @@ function sendSubmitNotifications($surveyid, array $emails = [], bool $preserveRe
{
// @todo: Remove globals
global $thissurvey;

$bIsHTML = ($thissurvey['htmlemail'] === 'Y'); // Needed for ANSWERTABLE
$debug = App()->getConfig('debug');

if (!isset($_SESSION['survey_' . $surveyid]['srid'])) {
$srid = null; /* Maybe just return ? */
} else {
$srid = $_SESSION['survey_' . $surveyid]['srid'];
}
//LimeMailer instance
$mailer = \LimeMailer::getInstance(\LimeMailer::ResetComplete);
$mailer->setSurvey($surveyid);
$aReplacementVars = array();
$aReplacementVars['VIEWRESPONSEURL'] = App()->getController()->createAbsoluteUrl("responses/view/", ['surveyId' => $surveyid, 'id' => $srid]);
$aReplacementVars['EDITRESPONSEURL'] = App()->getController()->createAbsoluteUrl("/admin/dataentry/sa/editdata/subaction/edit/surveyid/{$surveyid}/id/{$srid}");
$aReplacementVars['STATISTICSURL'] = App()->getController()->createAbsoluteUrl("/admin/statistics/sa/index/surveyid/{$surveyid}");
$mailer->aUrlsPlaceholders = ['VIEWRESPONSE','EDITRESPONSE','STATISTICS'];
$aReplacementVars['ANSWERTABLE'] = '';

//emails to be sent and return values
$aEmailNotificationTo = $emails['admin_notification'] ?? [];
$aEmailResponseTo = $emails['admin_responses'] ?? [];
$failedEmailCount = 0;
$successfullEmailCount = 0;

//replacementVars for LEM
$aReplacementVars = array();
$aReplacementVars['STATISTICSURL'] = App()->getController()->createAbsoluteUrl("/admin/statistics/sa/index/surveyid/{$surveyid}");
$aReplacementVars['ANSWERTABLE'] = '';

if (!isset($_SESSION['survey_' . $surveyid]['srid'])) {
$responseId = null; /* Maybe just return ? */
} else {
//replacementVars for LEM requiring a response id
$responseId = $_SESSION['survey_' . $surveyid]['srid'];
$aReplacementVars['EDITRESPONSEURL'] = App()->getController()->createAbsoluteUrl("/admin/dataentry/sa/editdata/subaction/edit/surveyid/{$surveyid}/id/{$responseId}");
$aReplacementVars['VIEWRESPONSEURL'] = App()->getController()->createAbsoluteUrl("responses/view/", ['surveyId' => $surveyid, 'id' => $responseId]);
}

// set email language
$emailLanguage = null;
if (isset($_SESSION['survey_' . $surveyid]['s_lang'])) {
$emailLanguage = $_SESSION['survey_' . $surveyid]['s_lang'];
}

// create array of recipients for emailnotifications
if (!empty($thissurvey['emailnotificationto']) && empty($emails)) {
$aRecipient = explode(";", LimeExpressionManager::ProcessStepString($thissurvey['emailnotificationto'], array('ADMINEMAIL' => $thissurvey['adminemail']), 3, true));
foreach ($aRecipient as $sRecipient) {
Expand All @@ -479,6 +492,7 @@ function sendSubmitNotifications($surveyid, array $emails = [], bool $preserveRe
}
}
}
// // create array of recipients for emailresponses
if (!empty($thissurvey['emailresponseto']) && empty($emails)) {
$aRecipient = explode(";", LimeExpressionManager::ProcessStepString($thissurvey['emailresponseto'], array('ADMINEMAIL' => $thissurvey['adminemail']), 3, true));
foreach ($aRecipient as $sRecipient) {
Expand All @@ -488,67 +502,36 @@ function sendSubmitNotifications($surveyid, array $emails = [], bool $preserveRe
}
}
}

if (count($aEmailNotificationTo) || count($aEmailResponseTo)) {
/* Force a replacement to fill coreReplacement like {SURVEYRESOURCESURL} for example */
$reData = array('thissurvey' => $thissurvey);
templatereplace(
"{SID}",
array(), /* No tempvars update (except old Replacement like */
$reData /* Be surre to use current survey */
$reData /* Be sure to use current survey */
);
}
if (count($aEmailResponseTo)) {
// there was no token used so lets remove the token field from insertarray
if (!isset($_SESSION['survey_' . $surveyid]['token']) && $_SESSION['survey_' . $surveyid]['insertarray'][0] === 'token') {
unset($_SESSION['survey_' . $surveyid]['insertarray'][0]);
}
$aFullResponseTable = getFullResponseTable($surveyid, $_SESSION['survey_' . $surveyid]['srid'], $_SESSION['survey_' . $surveyid]['s_lang']);
$ResultTableHTML = "<table class='printouttable' >\n";
$ResultTableText = "\n\n";
Yii::import('application.helpers.viewHelper');
foreach ($aFullResponseTable as $sFieldname => $fname) {
if (substr($sFieldname, 0, 4) === 'gid_') {
$ResultTableHTML .= "\t<tr class='printanswersgroup'><td colspan='2'>" . viewHelper::flatEllipsizeText($fname[0], true, 0) . "</td></tr>\n";
$ResultTableText .= "\n{$fname[0]}\n\n";
} elseif (substr($sFieldname, 0, 4) === 'qid_') {
$ResultTableHTML .= "\t<tr class='printanswersquestionhead'><td colspan='2'>" . viewHelper::flatEllipsizeText($fname[0], true, 0) . "</td></tr>\n";
$ResultTableText .= "\n{$fname[0]}\n";
} else {
$ResultTableHTML .= "\t<tr class='printanswersquestion'><td>" . viewHelper::flatEllipsizeText("{$fname[0]} {$fname[1]}", true, 0) . "</td><td class='printanswersanswertext'>" . CHtml::encode($fname[2]) . "</td></tr>\n";
$ResultTableText .= " {$fname[0]} {$fname[1]}: {$fname[2]}\n";
}
}

$ResultTableHTML .= "</table>\n";
$ResultTableText .= "\n\n";
if ($bIsHTML) {
$aReplacementVars['ANSWERTABLE'] = $ResultTableHTML;
} else {
$aReplacementVars['ANSWERTABLE'] = $ResultTableText;
}
}

$emailLanguage = null;
if (isset($_SESSION['survey_' . $surveyid]['s_lang'])) {
$emailLanguage = $_SESSION['survey_' . $surveyid]['s_lang'];
}
LimeExpressionManager::updateReplacementFields($aReplacementVars);
if (count($aEmailNotificationTo) > 0) {
$mailer = \LimeMailer::getInstance();
$mailer->setTypeWithRaw('admin_notification', $emailLanguage);
foreach ($aEmailNotificationTo as $sRecipient) {
$notificationId = null;
$notificationRecipient = $sRecipient;
/** set mailer params for @see FailedEmailController::actionResend() */
if (!empty($emails)) {
$notificationId = $sRecipient['id'];
$responseId = $sRecipient['responseId'];
$notificationRecipient = $sRecipient['recipient'];
$emailLanguage = $sRecipient['language'];
$mailer->setTypeWithRaw('admin_notification', $emailLanguage);
}
$mailer->setTo($notificationRecipient);
if (!$mailer->SendMessage()) {
$failedEmailCount++;
saveFailedEmail($notificationId, $notificationRecipient, $surveyid, 'admin_notification', $emailLanguage, $mailer->getError());
saveFailedEmail($notificationId, $notificationRecipient, $surveyid, $responseId, 'admin_notification', $emailLanguage, $mailer->getError());
if (empty($emails) && $debug > 0 && Permission::model()->hasSurveyPermission($surveyid, 'surveysettings', 'update')) {
/* Find a better way to show email error … */
echo CHtml::tag("div",
Expand All @@ -566,21 +549,53 @@ function sendSubmitNotifications($surveyid, array $emails = [], bool $preserveRe
}

if (count($aEmailResponseTo) > 0) {
// there was no token used so lets remove the token field from insertarray
if (isset($_SESSION['survey_' . $surveyid])) {
if (!isset($_SESSION['survey_' . $surveyid]['token']) && $_SESSION['survey_' . $surveyid]['insertarray'][0] === 'token') {
unset($_SESSION['survey_' . $surveyid]['insertarray'][0]);
}
}
$mailer = \LimeMailer::getInstance();
$mailer->setTypeWithRaw('admin_responses', $emailLanguage);
foreach ($aEmailResponseTo as $sRecipient) {
$responseId = null;
$notificationId = null;
$responseRecipient = $sRecipient;
/** set mailer params for @see FailedEmailController::actionResend() */
if (!empty($emails)) {
$responseId = $sRecipient['id'];
$notificationId = $sRecipient['id'];
$responseId = $sRecipient['responseId'];
$responseRecipient = $sRecipient['recipient'];
$emailLanguage = $sRecipient['language'];
$mailer->setTypeWithRaw('admin_notification', $emailLanguage);
$mailer->setTypeWithRaw('admin_responses', $emailLanguage);
}
$aFullResponseTable = getFullResponseTable($surveyid, $responseId, $emailLanguage);
$ResultTableHTML = "<table class='printouttable' >\n";
$ResultTableText = "\n\n";
Yii::import('application.helpers.viewHelper');
foreach ($aFullResponseTable as $sFieldname => $fname) {
if (substr($sFieldname, 0, 4) === 'gid_') {
$ResultTableHTML .= "\t<tr class='printanswersgroup'><td colspan='2'>" . viewHelper::flatEllipsizeText($fname[0], true, 0) . "</td></tr>\n";
$ResultTableText .= "\n{$fname[0]}\n\n";
} elseif (substr($sFieldname, 0, 4) === 'qid_') {
$ResultTableHTML .= "\t<tr class='printanswersquestionhead'><td colspan='2'>" . viewHelper::flatEllipsizeText($fname[0], true, 0) . "</td></tr>\n";
$ResultTableText .= "\n{$fname[0]}\n";
} else {
$ResultTableHTML .= "\t<tr class='printanswersquestion'><td>" . viewHelper::flatEllipsizeText("{$fname[0]} {$fname[1]}", true, 0) . "</td><td class='printanswersanswertext'>" . CHtml::encode($fname[2]) . "</td></tr>\n";
$ResultTableText .= " {$fname[0]} {$fname[1]}: {$fname[2]}\n";
}
}
$ResultTableHTML .= "</table>\n";
$ResultTableText .= "\n\n";
if ($bIsHTML) {
$aReplacementVars['ANSWERTABLE'] = $ResultTableHTML;
} else {
$aReplacementVars['ANSWERTABLE'] = $ResultTableText;
}
LimeExpressionManager::updateReplacementFields($aReplacementVars);
$mailer->setTo($responseRecipient);
if (!$mailer->SendMessage()) {
$failedEmailCount++;
saveFailedEmail($responseId, $responseRecipient, $surveyid, 'admin_responses', $emailLanguage, $mailer->getError());
saveFailedEmail($notificationId, $responseRecipient, $surveyid, $responseId, 'admin_responses', $emailLanguage, $mailer->getError());
if (empty($emails) && $debug > 0 && Permission::model()->hasSurveyPermission($surveyid, 'surveysettings', 'update')) {
/* Find a better way to show email error … */
echo CHtml::tag("div",
Expand Down Expand Up @@ -610,12 +625,13 @@ function sendSubmitNotifications($surveyid, array $emails = [], bool $preserveRe
* @param int|null $id Id of failed email
* @param string|null $recipient
* @param int $surveyId
* @param int $responseId
* @param string|null $emailType
* @param string|null $language
* @param string $errorMessage
* @return bool
*/
function saveFailedEmail(?int $id, ?string $recipient, int $surveyId, string $emailType, ?string $language, string $errorMessage): bool
function saveFailedEmail(?int $id, ?string $recipient, int $surveyId, int $responseId, string $emailType, ?string $language, string $errorMessage): bool
{
$failedEmailModel = new FailedEmail();
if (isset($id)) {
Expand All @@ -629,6 +645,7 @@ function saveFailedEmail(?int $id, ?string $recipient, int $surveyId, string $em
}
$failedEmailModel->recipient = $recipient;
$failedEmailModel->surveyid = $surveyId;
$failedEmailModel->responseid = $responseId;
$failedEmailModel->email_type = $emailType;
$failedEmailModel->language = $language;
$failedEmailModel->error_message = $errorMessage;
Expand Down
3 changes: 2 additions & 1 deletion application/helpers/update/updates/Update_489.php
Expand Up @@ -13,10 +13,11 @@ class Update_489 extends DatabaseUpdateBase
public function up()
{
$this->db->createCommand()->createTable(
'{{failed_email}}',
'{{failed_emails}}',
[
'id' => "pk",
'surveyid' => "integer NOT NULL",
'responseid' => "integer NOT NULL",
'email_type' => "string(200) NOT NULL",
'recipient' => "string(320) NOT NULL",
'language' => "string(20) NOT NULL DEFAULT 'en'",
Expand Down
34 changes: 29 additions & 5 deletions application/models/FailedEmail.php
@@ -1,11 +1,12 @@
<?php

/**
* This is the model class for table "{{failed_email}}".
* This is the model class for table "{{failed_emails}}".
*
* The following are the available columns in table '{{failed_email}}':
* The following are the available columns in table '{{failed_emails}}':
* @property integer $id primary key
* @property integer $surveyid the surveyid this one belongs to
* @property integer $responseid the id of the participants response
* @property string $email_type the email type
* @property string $recipient the recipients email address
* @property string $language the email language
Expand All @@ -29,7 +30,7 @@ class FailedEmail extends LSActiveRecord
*/
public function tableName(): string
{
return '{{failed_email}}';
return '{{failed_emails}}';
}

/**
Expand All @@ -39,14 +40,14 @@ public function tableName(): string
public function rules(): array
{
return [
['id, surveyid, email_type, recipient, error_message, created', 'required'],
['id, surveyid, responseid, email_type, recipient, error_message, created', 'required'],
['email_type', 'length', 'max' => 200],
['recipient', 'length', 'max' => 320],
['status', 'length', 'max' => 20],
['language', 'length', 'max' => 20],
['created, updated', 'safe'],
// The following rule is used by search().
['id, email_type, recipient, language, created, error_message, status, updated', 'safe', 'on' => 'search'],
['id, responseid, email_type, recipient, language, created, error_message, status, updated', 'safe', 'on' => 'search'],
];
}

Expand Down Expand Up @@ -98,6 +99,7 @@ public function search(): CActiveDataProvider

$criteria->compare('id', $this->id);
$criteria->compare('surveyid', $this->surveyid);
$criteria->compare('responseid', $this->responseid);
$criteria->compare('email_type', $this->email_type, true);
$criteria->compare('recipient', $this->recipient, true);
$criteria->compare('language', $this->language, true);
Expand Down Expand Up @@ -145,6 +147,12 @@ public function getColumns(): array
'value' => '$data->status',
'htmlOptions' => ['class' => 'nowrap']
],
[
'header' => gT('Response ID'),
'name' => 'responseUrl',
'type' => 'raw',
'filter' => false,
],
[
'header' => gT('Created'),
'name' => 'created',
Expand Down Expand Up @@ -193,6 +201,22 @@ public function getButtons(): string
return $buttons;
}

/**
* create a link to the response if it exists, else just return the id
* @return string
*/
public function getResponseUrl(): string
{
$response = Response::model($this->surveyid)->findByPk($this->responseid);
if (!empty($response)) {
$responseUrl = App()->createUrl("responses/view/", ['surveyId' => $this->surveyid, 'id' => $this->responseid]);
$responseLink = '<a href="' . $responseUrl . '" role="button" data-toggle="tooltip" title="' . gT('View response details') . '">' . $this->responseid . '</a>';
} else {
$responseLink = (string)$this->responseid;
}
return $responseLink;
}

/**
* @return string
* @throws CException
Expand Down
Expand Up @@ -20,6 +20,6 @@
Yii::app()->createUrl("failedEmail/index/", ['surveyid' => $surveyId])
) ?>
</li>
<?php
<?php
endforeach; ?>
</ul>
3 changes: 2 additions & 1 deletion installer/create-database.php
Expand Up @@ -1159,10 +1159,11 @@ function populateDatabase($oDB)
}

$oDB->createCommand()->createTable(
'{{failed_email}}',
'{{failed_emails}}',
[
'id' => "pk",
'surveyid' => "integer NOT NULL",
'responseid' => "integer NOT NULL",
'email_type' => "string(200) NOT NULL",
'recipient' => "string(320) NOT NULL",
'language' => "string(20) NOT NULL DEFAULT 'en'",
Expand Down
Binary file not shown.

0 comments on commit 61e8ce1

Please sign in to comment.