Commit e79d0f15 authored by Denis Chenu's avatar Denis Chenu
Browse files

A plugin for LimeSurvey to send all token in one click

parents
#Send token email via Ajax#
Allow to send token email one by one with one click.
## Installation
### Via GIT
- Go to your LimeSurvey Directory (version up to 2.05)
- Clone in plugins/sendMailAjax directory
### Via ZIP dowload
- Get the file and uncompress it
- Move the file included to plugins/sendMailAjax directory
##Home page & Copyright
- HomePage <http://extensions.sondages.pro/>
- Copyright © 2015 Denis Chenu <http://sondages.pro>
- Licence : GNU General Affero Public License <https://www.gnu.org/licenses/agpl-3.0.html>
##Support
- Issues <https://gitlab.com/Shnoulle-LimeSurvey-plugin/sendMailAjax/issues>
- Professional support <http://extensions.sondages.pro/1>
/*
.dialog-sendmailajax{
max-width:100;
min-width:20em;
}
*/
.sendmailajax-list{padding:0;margin:0;list-style:none;height:7em;overflow-y:scroll;}
.sendmailajax-list li{
list-style:none;padding:0;margin:0 0 2px;
}
#sendmailajax .alert{margin:2px 0}
$(document).on('click','a.popup-sendmailajax',function(event){
event.preventDefault();
// Start by save settings
/*
delay=$("#plugin\\[sendMailAjax\\]\\[mindelay\\]").val();
maxmail=$("#plugin\\[sendMailAjax\\]\\[maxemail\\]").val();
*/
dialogName = '#dialogsendmailajax';
contentUrl=$(this).attr('href');
dialogTitle=$(this).text();
$('#sendmailajax').dialog('destroy').remove();
$("<div id='sendmailajax'>").dialog({
modal: true,
open: function ()
{
$(this).load(contentUrl);
},
title: dialogTitle,
dialogClass: "dialog-sendmailajax",
buttons: { Cancel: function() { $(this).dialog("close"); } },
close: function () {
$(this).remove();
}
});
});
$(document).on('click','a#launch-email',function(event){
var jsonurl=$(this).attr('rel');
$(this).closest('li').text($(this).text());
loopSendEmail(jsonurl,0);
});
/*
* Used to update response one by one
* @param {string} jsonurl : The json Url to request
* @param {integer} tokenid : The token id
*/
function loopSendEmail(jsonurl,tokenid) {
if($("#sendmailajax").length>0)// Don't send if user click on 'Cancel'
{
$.ajax({
url: jsonurl,
dataType : 'json',
data : {'tokenid': tokenid},
success: function (data) {
$("#sendmailajax .sendmailajax-list").prepend("<li style='display:none'>"+data.message+"</li>");
$("#sendmailajax .sendmailajax-list :first-child").slideDown(500);
//$("#sendmailajax .sendmailajax-list :nth-child(6)").slideUp(500,function() { });
if (data.next) {
loopSendEmail(jsonurl,data.next);
} else {
$("#sendmailajax").closest(".ui-dialog").find(" .ui-dialog-buttonset .ui-button-text").html("Done");
$("#sendmailajax .sendmailajax-list").prepend("<li><strong>Done</strong></li>");
}
},
});
}
}
<?php
/**
* sendMailAjax Plugin for LimeSurvey
*
* @author Denis Chenu <denis@sondages.pro>
* @copyright 2015 Denis Chenu <http://sondages.pro>
* @license AGPL v3
* @version 0.1
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 General Public License for more details.
*
*/
#use ls\pluginmanager\PluginBase;
class sendMailAjax extends PluginBase {
protected $storage = 'DbStorage';
static protected $description = 'Send email one by one with ajax.';
static protected $name = 'sendMailAjax';
public function __construct(PluginManager $manager, $id) {
parent::__construct($manager, $id);
$this->subscribe('newDirectRequest');
$this->subscribe('beforeSurveySettings');
$this->subscribe('newSurveySettings');
}
private $iSurveyId;
public function newDirectRequest()
{
//~ Yii::app()->db->schema->getTables();
//~ Yii::app()->db->schema->refresh();
$oEvent = $this->event;
$sFunction=$oEvent->get('function');
if ($oEvent->get('target') != get_class())
return;
//~ $this->surveyId=$this->api->getRequest('surveyid');
//~ tracevar($this->navData);
$this->iSurveyId=$iSurveyId=$this->api->getRequest()->getParam('surveyid');
$oSurvey=Survey::model()->findByPK($iSurveyId);
if(!$oSurvey)
throw new CHttpException(404, gt("The survey does not seem to exist."));
if(!Permission::model()->hasSurveyPermission($iSurveyId, 'tokens', 'update'))
throw new CHttpException(401, gt("You do not have sufficient rights to access this page."));
if(!tableExists('{{tokens_' . $iSurveyId . '}}'))
throw new CHttpException(404, gt("Token table don't exist."));
if($oSurvey->active!="Y")
throw new CHttpException(404, gt("The survey seem’s inactive."));
$sType=$sType=$this->api->getRequest()->getParam('type');
if(!in_array($sType,array('remind','invite')))
throw new CHttpException(500, gt("Unknow type"));
switch ($sFunction)
{
case "confirm":
$this->actionConfirm($sType);
break;
case "send":
$this->actionSend($sType);
break;
default:
throw new CHttpException(500, gt("Unknow action"));
}
}
public function beforeSurveySettings()
{
$oEvent = $this->event;
$iSurveyId=$oEvent->get('survey');
$oSurvey=Survey::model()->findByPk($iSurveyId);
if(tableExists('{{tokens_' . $iSurveyId . '}}') && Permission::model()->hasSurveyPermission($iSurveyId, 'tokens', 'update') && $oSurvey->active=="Y")
{
$jsUrl = Yii::app()->assetManager->publish(dirname(__FILE__) . '/assets/sendMailAjax.js');
App()->getClientScript()->registerScriptFile($jsUrl);
$cssUrl = Yii::app()->assetManager->publish(dirname(__FILE__) . '/assets/sendMailAjax.css');
App()->getClientScript()->registerCssFile($cssUrl);
$oEvent->set("surveysettings.{$this->id}", array(
'name' => get_class($this),
'settings' => array(
'mindaydelay'=>array(
'type'=>'int',// float is not fixed in 2.05
'label'=>'Minimum day after last email (invite or remind).',
'current' => $this->get('mindaydelay', 'Survey', $iSurveyId,'1'),
),
'maxremind'=>array(
'type'=>'int',
'label'=>'Don’t send remind if user have already receive X reminder',
'current' => $this->get('maxremind', 'Survey', $iSurveyId,''),
),
'launchinvite'=>array(
'type'=>'link',
'label'=>gt('Send email invitation'),
'htmlOptions'=>array(
'title'=>gt('Send email invitation'),
),
'class'=>'popup-sendmailajax',
'link'=>$this->api->createUrl('plugins/direct', array('plugin' => get_class(),'surveyid'=>$iSurveyId,'function' => 'confirm','type'=>'invite'))
),
'launchremind'=>array(
'type'=>'link',
'label'=>gt('Send email reminder'),
'class'=>'popup-sendmailajax',
'htmlOptions'=>array(
'title'=>gt('Send email reminder'),
),
'link'=>$this->api->createUrl('plugins/direct', array('plugin' => get_class(),'surveyid'=>$iSurveyId,'function' => 'confirm','type'=>'remind'))
),
)
));
}
}
public function newSurveySettings()
{
$event = $this->event;
$aSettings=$event->get('settings');
$aSettings['mindaydelay']=(isset($aSettings['mindaydelay']) && intval($aSettings['mindaydelay'])>=0) ? intval($aSettings['mindaydelay']) : 1;
$aSettings['maxremind']=(isset($aSettings['maxremind']) && intval($aSettings['maxremind'])>=0) ? intval($aSettings['maxremind']) : 0;
foreach ($aSettings as $name => $value)
{
$this->set($name, $value, 'Survey', $event->get('survey'));
}
}
private function actionConfirm($sType)
{
$oEvent=$this->event;
Yii::app()->controller->layout='bare'; // bare don't have any HTML
Yii::setPathOfAlias('sendmailajaxViews', dirname(__FILE__) . '/views/');
//~ die(Yii::getPathOfAlias('sendmailajaxViews'));
$oCriteria=$this->getBaseCriteria($sType);
$renderData['count']=TokenDynamic::model($this->iSurveyId)->count($oCriteria);
switch ($sType)
{
case 'invite':
$renderData['confirminfo']=gt('Send email invitation');
$renderData['buttonText']=gt('Send Invitations');
break;
case 'remind':
$renderData['confirminfo']=gt('Send email reminder');
$renderData['confirminfo'].=CHtml::tag('ul',array('class'=>'alert alert-info'),"",false);
$renderData['confirminfo'].=CHtml::tag('li',array(),sprintf(gt('Minimum day after last email : %s'),$this->get('mindaydelay', 'Survey', $this->iSurveyId,'1')));
$renderData['confirminfo'].=CHtml::tag('li',array(),sprintf(gt('Don’t send remind if user have already receive %s reminder'),$this->get('maxremind', 'Survey', $this->iSurveyId,'0')));
$renderData['confirminfo'].=CHtml::closeTag('ul');
$renderData['buttonText']=gt('Send Reminders');
break;
default:
throw new CHttpException(404, gt("Unknow action"));
}
$renderData['sendUrl']=$this->api->createUrl('plugins/direct', array('plugin' => get_class(),'surveyid'=>$this->iSurveyId,'function' => 'send','type'=>$sType));
$content=Yii::app()->controller->renderPartial("sendmailajaxViews.popup",$renderData);
echo $content;
}
private function actionSend($sType)
{
$iNextToken=$this->api->getRequest()->getParam('tokenid');
$oSendCriteria=$this->getBaseCriteria($sType);
$oNextCriteria=$this->getBaseCriteria($sType);
$oNextCriteria->order='tid ASC';
$aData=array(
'status'=>'',
'message'=>'',
'next'=>'',
);
if($iNextToken)
{
$oSendCriteria->compare('tid',$iNextToken);
$oNextCriteria->compare('tid',">".$iNextToken);
}
else
{
$oSendCriteria->order='tid ASC';
}
$oToken=TokenDynamic::model($this->iSurveyId)->find($oSendCriteria);
if($oToken)
{
$aData=array_replace($aData,$this->sendMail($oToken,$sType));
if(!$iNextToken)
$oNextCriteria->compare('tid',">".$oToken->tid);
}
else
{
$aData['message']="No token with this id";
}
$oNextToken=TokenDynamic::model($this->iSurveyId)->find($oNextCriteria);
if($oNextToken)
$aData['next']=$oNextToken->tid;
$this->renderJson($aData);
}
private function renderJson($aData)
{
Yii::import('application.helpers.viewHelper');
viewHelper::disableHtmlLogging();
header('Content-type: application/json');
echo json_encode($aData);
Yii::app()->end();
}
private function getBaseCriteria($sType)
{
$oCriteria= new CDbCriteria();
$oCriteria->condition="email IS NOT NULL and email != '' ";
$oCriteria->addCondition("token IS NOT NULL and token != ''");
$oCriteria->addCondition("completed ='N' or completed=''");
$oCriteria->compare('emailstatus',"OK");
$dToday=dateShift(date("Y-m-d H:i:s"),"Y-m-d H:i:s", Yii::app()->getConfig("timeadjust"));
$oCriteria->addCondition("validfrom < :validfrom OR validfrom='' or validfrom IS NULL");
$oCriteria->addCondition("validuntil > :validuntil OR validuntil='' or validuntil IS NULL");
$oCriteria->compare('usesleft',">0");
$oCriteria->addCondition("blacklisted IS NULL OR blacklisted='' ");
//~ $oCriteria->compare('validuntil',"<".$dToday);
switch ($sType)
{
case 'invite':
$oCriteria->addCondition("sent ='N' or sent=''");
break;
case 'remind':
$oCriteria->addCondition("sent !='N' or sent!=''");
$iMinDayDelay=intval($this->get('mindaydelay', 'Survey', $this->iSurveyId,'1'));
$iMaxRemind=intval($this->get('maxremind', 'Survey', $this->iSurveyId,null));
//~ if($iMinDayDelay>0)
//~ {
//~ $dDateCompare = dateShift(
//~ date("Y-m-d H:i:s", time() - 86400 * $iMinDayDelay),
//~ "Y-m-d H:i:s", Yii::app()->getConfig("timeadjust")
//~ );
//~ $oCriteria->addCondition("(remindersent !='N' AND sent < :dateSent) OR remindersent < :dateReminder");
//~ $oCriteria->params=array_merge($oCriteria->params,
//~ array(
//~ ':dateSent'=>$dDateCompare,
//~ ':dateReminder'=>$dDateCompare,
//~ )
//~ );
//~ }
if($iMaxRemind>0)
{
$oCriteria->addCondition("remindercount < :remindercount");
$oCriteria->params=array_merge($oCriteria->params,
array(
':remindercount'=>$iMaxRemind,
)
);
}
break;
}
$oCriteria->params=array_merge($oCriteria->params,
array(
':validfrom'=>$dToday,
':validuntil'=>$dToday,
)
);
return $aCriteria[$sType]=$oCriteria;
}
private function sendMail($oToken,$sType)
{
$returnData=array(
'status'=>'',
'message'=>'',
);
$oSurvey=Survey::model()->findByPk($this->iSurveyId);
$aSurveyLangs = $oSurvey->getAllLanguages();
$aTokenFields = getTokenFieldsAndNames($this->iSurveyId, true);
$bHtml = $oSurvey->htmlemail=='Y';
if(in_array($oToken->language,$aSurveyLangs))
$sLang=$oToken->language;
else
$sLang=$oSurvey->language;
$oSurveyLanguage=SurveyLanguageSetting::model()->find("surveyls_survey_id = :sid AND surveyls_language = :language",array(':sid'=>$this->iSurveyId,':language'=>$sLang));
switch ($sType)
{
case 'invite':
$sSubject=$oSurveyLanguage->surveyls_email_invite_subj;
$sMessage=$oSurveyLanguage->surveyls_email_invite;
break;
case 'remind':
$sSubject=$oSurveyLanguage->surveyls_email_remind_subj;
$sMessage=$oSurveyLanguage->surveyls_email_remind;
break;
default:
throw new CHttpException(500);
}
$sSubject=preg_replace("/{TOKEN:([A-Z0-9_]+)}/","{"."$1"."}",$sSubject);
$sMessage=preg_replace("/{TOKEN:([A-Z0-9_]+)}/","{"."$1"."}",$sMessage);
if ($bHtml)
$sMessage = html_entity_decode($sMessage, ENT_QUOTES, Yii::app()->getConfig("emailcharset"));
$to = array();
$aEmailaddresses = explode(';', $oToken->email);
foreach ($aEmailaddresses as $sEmailaddress)
{
$to[] = "{$oToken->firstname} {$oToken->lastname} <{$sEmailaddress}>";
}
$from = "{$oSurvey->admin} <{$oSurvey->adminemail}>";
$aReplace=array();
foreach($oToken->attributes as $key=>$value)
{
$aReplace[strtoupper($key)]=$value;
}
$aReplace["ADMINNAME"] = $oSurvey->admin;
$aReplace["ADMINEMAIL"] = $oSurvey->adminemail;
$aReplace["SURVEYNAME"] = $oSurveyLanguage->surveyls_title;
$aReplace["SURVEYDESCRIPTION"] = $oSurveyLanguage->surveyls_description;
$aReplace["EXPIRY"] = $oSurvey->expires;
$aReplace["OPTOUTURL"] = Yii::app()->getController()
->createAbsoluteUrl("/optout/tokens",array('langcode'=> $oToken->language,'surveyid'=>$this->iSurveyId,'token'=>$oToken->token));
$aReplace["OPTINURL"] = Yii::app()->getController()
->createAbsoluteUrl("/optin/tokens",array('langcode'=> $oToken->language,'surveyid'=>$this->iSurveyId,'token'=>$oToken->token));
$aReplace["SURVEYURL"] = Yii::app()->getController()
->createAbsoluteUrl("/survey/index",array('sid'=>$this->iSurveyId,'token'=>$oToken->token,'lang'=>$oToken->language));
$aBareBone=array();
foreach(array('OPTOUT', 'OPTIN', 'SURVEY') as $key)
{
$url = $aReplace["{$key}URL"];
if ($bHtml) $aReplace["{$key}URL"] = "<a href='{$url}'>" . htmlspecialchars($url) . '</a>';
$aBareBone["@@{$key}URL@@"]=$url;
}
$aRelevantAttachments = array();
if(!empty($oSurveyLanguage->attachments))
{
$aTemplateAttachments = unserialize($oSurveyLanguage->attachments);
switch($sType)
{
case 'invite':
$aAttachments=isset($aTemplateAttachments['invitation']) ? $aTemplateAttachments['invitation'] : null;
break;
case 'remind':
$aAttachments=isset($aTemplateAttachments['reminder']) ? $aTemplateAttachments['reminder'] : null;
break;
default:
break;
}
if(!empty($aAttachments))
{
LimeExpressionManager::singleton()->loadTokenInformation($this->iSurveyId, $oToken->token);
foreach($aAttachments as $aAttachment)
{
if (LimeExpressionManager::singleton()->ProcessRelevance($aAttachment['relevance']))
{
$aRelevantAttachments[] = $aAttachment['url'];
}
}
// Why not use LimeExpressionManager::ProcessString($sSubject, NULL, $aReplace, false, 2, 1, false, false, true); ?
}
}
$sSubject=LimeExpressionManager::ProcessString($sSubject, NULL, $aReplace, false, 2, 1, false, false, true);
$sMessage=LimeExpressionManager::ProcessString($sMessage, NULL, $aReplace, false, 2, 1, false, false, true);
$sSubject=str_replace (array_keys($aBareBone),$aBareBone,$sSubject);
$sMessage=str_replace (array_keys($aBareBone),$aBareBone,$sMessage);
$aCustomHeaders = array(
'1' => "X-surveyid: " . $this->iSurveyId,
'2' => "X-tokenid: " . $oToken->token
);
global $maildebug;
$event = new PluginEvent('beforeTokenEmail');
$event->set('type', $sType);
$event->set('subject', $sSubject);
$event->set('to', $to);
$event->set('body', $sMessage);
$event->set('from', $from);
$event->set('bounce', getBounceEmail($this->iSurveyId));
$event->set('token', $oToken->attributes);
App()->getPluginManager()->dispatchEvent($event);
$sSubject = $event->get('subject');
$sMessage = $event->get('body');
$to = $event->get('to');
$from = $event->get('from');
if ($event->get('send', true) == false)
{
// This is some ancient global used for error reporting instead of a return value from the actual mail function..
$maildebug = $event->get('error', $maildebug);
$success = $event->get('error') == null;
}
else
{
$success = SendEmailMessage($sMessage, $sSubject, $to, $from, Yii::app()->getConfig("sitename"), $bHtml, getBounceEmail($this->iSurveyId), $aRelevantAttachments, $aCustomHeaders);
}
if ($success)
{
$returnData['status']='success';
switch($sType)
{
case 'invite':
$returnData['message']=gT("Invitation sent to:")." {$oToken->tid} : {$oToken->firstname} {$oToken->lastname} <{$oToken->email}>";
$oToken->sent = dateShift(date("Y-m-d H:i:s"), "Y-m-d H:i", Yii::app()->getConfig("timeadjust"));
break;
case 'remind':
$returnData['message']=gT("Reminder sent to:")." {$oToken->tid} : {$oToken->firstname} {$oToken->lastname} <{$oToken->email}>";
$oToken->remindersent = dateShift(date("Y-m-d H:i:s"), "Y-m-d H:i", Yii::app()->getConfig("timeadjust"));
$oToken->remindercount++;
break;
default:
}
$oToken->save();
}
else
{
$returnData['status']='error';
$returnData['message']=LimeExpressionManager::ProcessString(gT("Email to {FIRSTNAME} {LASTNAME} ({EMAIL}) failed. Error Message:") . "<pre>" . $maildebug . "</pre>", NULL, $aReplace, false, 2, 1, false, false, true);
}
return $returnData;
}
}
<p class='alert alert-info'><?php echo $confirminfo; ?></p>
<p class='alert'><?php echo gt('Number of tokens')." : ".$count; ?></p>
<ul class="sendmailajax-list">
<li><a id='launch-email' class='btn' rel='<?php echo $sendUrl; ?>'><?php echo $buttonText ?><a></li>
</ul>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment