PageRenderTime 54ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/administrator/components/com_acymailing/helpers/queue.php

https://github.com/Shigaru/shigaru
PHP | 323 lines | 319 code | 0 blank | 4 comment | 58 complexity | 69391da2c7e2c872b7bfb849ee11395f MD5 | raw file
  1. <?php
  2. /**
  3. * @copyright Copyright (C) 2009-2010 ACYBA SARL - All rights reserved.
  4. * @license http://www.gnu.org/licenses/gpl-3.0.html GNU/GPL
  5. */
  6. defined('_JEXEC') or die('Restricted access');
  7. ?>
  8. <?php
  9. class queueHelper{
  10. var $mailid = 0;
  11. var $report = true;
  12. var $send_limit = 0;
  13. var $finish = false;
  14. var $error = false;
  15. var $nbprocess = 0;
  16. var $start = 0;
  17. var $stoptime = 0;
  18. var $successSend =0;
  19. var $errorSend=0;
  20. var $consecutiveError=0;
  21. var $messages = array();
  22. var $pause = 0;
  23. var $config;
  24. var $listsubClass;
  25. var $subClass;
  26. function queueHelper(){
  27. $this->config = acymailing::config();
  28. $this->subClass = acymailing::get('class.subscriber');
  29. $this->listsubClass = acymailing::get('class.listsub');
  30. $this->listsubClass->checkAccess = false;
  31. $this->listsubClass->sendNotif = false;
  32. $this->listsubClass->sendConf = false;
  33. $this->send_limit = $this->config->get('queue_nbmail',60);
  34. acymailing::increasePerf();
  35. @ini_set('default_socket_timeout',10);
  36. @ignore_user_abort(true);
  37. $timelimit = ini_get('max_execution_time');
  38. if(!empty($timelimit)){
  39. $this->stoptime = time()+$timelimit-4;
  40. }
  41. $this->db =& JFactory::getDBO();
  42. }
  43. function process(){
  44. $queueClass = acymailing::get('class.queue');
  45. $queueElements = $queueClass->getReady($this->send_limit,$this->mailid);
  46. if(empty($queueElements)){
  47. $this->finish = true;
  48. return true;
  49. }
  50. if($this->report){
  51. if(!headers_sent() AND ob_get_level() > 0){
  52. ob_end_flush();
  53. }
  54. $disp = "<div style='position:fixed; top:3px;left:3px;background-color : white;border : 1px solid grey; padding : 3px;'>";
  55. $disp.= JText::_('SEND_PROCESS');
  56. $disp.= ':  <span id="counter"/>'.$this->start.'</span> / '. $this->total;
  57. $disp.= '</div>';
  58. $disp.= "<div id='divinfo' style='display:none; position:fixed; bottom:3px;left:3px;background-color : white; border : 1px solid grey; padding : 3px;'>";
  59. $disp.= '</div>';
  60. $disp .= '<br/>';
  61. $disp.= '<script type="text/javascript" language="javascript">';
  62. $disp.= 'var mycounter = document.getElementById("counter");';
  63. $disp.= 'var divinfo = document.getElementById("divinfo");';
  64. $disp.= "function setInfo(message){ divinfo.style.display = 'block';divinfo.innerHTML=message; }";
  65. $disp.= 'function setCounter(val){ mycounter.innerHTML=val;}';
  66. $disp.= '</script>';
  67. echo $disp;
  68. if(function_exists('ob_flush')) @ob_flush();
  69. @flush();
  70. }//endifreport
  71. $mailHelper = acymailing::get('helper.mailer');
  72. $mailHelper->report = false;
  73. if($this->config->get('smtp_keepalive',0)) $mailHelper->SMTPKeepAlive = true;
  74. $queueDelete = array();
  75. $queueUpdate = array();
  76. $statsAdd = array();
  77. $actionSubscriber = array();
  78. $maxTry = $this->config->get('queue_try',0);
  79. $currentMail = $this->start;
  80. $this->nbprocess = 0;
  81. if(count($queueElements) < $this->send_limit){
  82. $this->finish = true;
  83. }
  84. foreach($queueElements as $oneQueue){
  85. $currentMail++; $this->nbprocess++;
  86. if($this->report){
  87. echo '<script type="text/javascript" language="javascript">setCounter('. $currentMail .')</script>';
  88. if(function_exists('ob_flush')) @ob_flush();
  89. @flush();
  90. }
  91. $result = $mailHelper->sendOne($oneQueue->mailid,$oneQueue->subid);
  92. $queueDeleteOk = true;
  93. $otherMessage = '';
  94. if($result){
  95. $this->successSend ++;
  96. $this->consecutiveError = 0;
  97. $queueDelete[$oneQueue->mailid][] = $oneQueue->subid;
  98. $statsAdd[$oneQueue->mailid][1][(int)$mailHelper->sendHTML][] = $oneQueue->subid;
  99. $queueDeleteOk = $this->_deleteQueue($queueDelete);
  100. $queueDelete = array();
  101. if($this->nbprocess%10 == 0){
  102. $this->_statsAdd($statsAdd);
  103. $this->_queueUpdate($queueUpdate);
  104. $statsAdd = array();
  105. $queueUpdate = array();
  106. }
  107. }else{
  108. $this->errorSend ++;
  109. $newtry = false;
  110. if(in_array($mailHelper->errorNumber,$mailHelper->errorNewTry)){
  111. if(empty($maxTry) OR $oneQueue->try < $maxTry-1){
  112. $newtry = true;
  113. $otherMessage = JText::sprintf('QUEUE_NEXT_TRY',round($this->config->get('queue_delay')/60));
  114. }
  115. if($mailHelper->errorNumber == 1) $this->consecutiveError ++;
  116. }
  117. if(!$newtry){
  118. $queueDelete[$oneQueue->mailid][] = $oneQueue->subid;
  119. $statsAdd[$oneQueue->mailid][0][(int)@$mailHelper->sendHTML][] = $oneQueue->subid;
  120. if($mailHelper->errorNumber == 1 AND $this->config->get('bounce_action_maxtry')){
  121. $queueDeleteOk = $this->_deleteQueue($queueDelete);
  122. $queueDelete = array();
  123. $otherMessage .= $this->_subscriberAction($oneQueue->subid);
  124. }
  125. }else{
  126. $queueUpdate[$oneQueue->mailid][] = $oneQueue->subid;
  127. }
  128. }
  129. $messageOnScreen = '['.$oneQueue->mailid.'] '.$mailHelper->reportMessage;
  130. if(!empty($otherMessage)) $messageOnScreen .= ' => '.$otherMessage;
  131. $this->_display($messageOnScreen,$result,$currentMail);
  132. if(!$queueDeleteOk){
  133. $this->_display(JText::_('QUEUE_DOUBLE',true));
  134. $this->finish = true;
  135. break;
  136. }
  137. if(!empty($this->stoptime) AND $this->stoptime < time()){
  138. $this->_display(JText::_('SEND_REFRESH_TIMEOUT',true));
  139. if($this->nbprocess < count($queueElements)) $this->finish = false;
  140. break;
  141. }
  142. if($this->consecutiveError > 2 AND $this->successSend>3){
  143. $this->_display(JText::_('SEND_REFRESH_CONNECTION',true));
  144. break;
  145. }
  146. if($this->consecutiveError > 5 OR connection_aborted()){
  147. $this->finish = true;
  148. break;
  149. }
  150. }
  151. $this->_deleteQueue($queueDelete);
  152. $this->_statsAdd($statsAdd);
  153. $this->_queueUpdate($queueUpdate);
  154. if($this->config->get('smtp_keepalive',0)) $mailHelper->SmtpClose();
  155. if(!empty($this->total) AND $currentMail >= $this->total){
  156. $this->finish = true;
  157. }
  158. if($this->consecutiveError>5){
  159. $this->_handleError();
  160. return false;
  161. }
  162. if($this->report && !$this->finish && !empty($this->pause) && (empty($this->stoptime) || $this->stoptime > time())){
  163. $pause = $this->pause;
  164. $this->_display($pause);
  165. while($pause>0){
  166. sleep(1);
  167. $this->_display($pause);
  168. $pause--;
  169. if(!empty($this->stoptime) && $this->stoptime < time()){
  170. $this->_display(JText::_('SEND_REFRESH_TIMEOUT',true));
  171. break;
  172. }
  173. }
  174. }
  175. return true;
  176. }
  177. function _deleteQueue($queueDelete){
  178. if(empty($queueDelete)) return true;
  179. $status = true;
  180. foreach($queueDelete as $mailid => $subscribers){
  181. $nbsub = count($subscribers);
  182. $query = 'DELETE FROM '.acymailing::table('queue').' WHERE mailid = '.intval($mailid).' AND subid IN ('.implode(',',$subscribers).') LIMIT '.$nbsub;
  183. $this->db->setQuery($query);
  184. $this->db->query();
  185. $nbdeleted = $this->db->getAffectedRows();
  186. if($nbdeleted != $nbsub){
  187. $status = false;
  188. }
  189. }
  190. return $status;
  191. }
  192. function _statsAdd($statsAdd){
  193. $time = time();
  194. if(empty($statsAdd)) return true;
  195. foreach($statsAdd as $mailid => $infos){
  196. $mailid = intval($mailid);
  197. foreach($infos as $status => $infosSub){
  198. foreach($infosSub as $html => $subscribers){
  199. $query = 'INSERT IGNORE INTO '.acymailing::table('userstats').' (mailid,subid,html,sent,senddate) VALUES ('.$mailid.','.implode(','.$html.',0,'.$time.'),('.$mailid.',',$subscribers).','.$html.',0,'.$time.')';
  200. $this->db->setQuery($query);
  201. $this->db->query();
  202. if($status){
  203. $query = 'UPDATE '.acymailing::table('userstats').' SET html = '.$html.',sent = sent +1,senddate = '.$time.' WHERE mailid = '.$mailid.' AND subid IN ('.implode(',',$subscribers).')';
  204. }else{
  205. $query = 'UPDATE '.acymailing::table('userstats').' SET html = '.$html.',senddate = '.$time.', fail = fail +1 WHERE mailid = '.$mailid.' AND subid IN ('.implode(',',$subscribers).')';
  206. }
  207. $this->db->setQuery($query);
  208. $this->db->query();
  209. }
  210. }
  211. $nbhtml = empty($infos[1][1]) ? 0 : count($infos[1][1]);
  212. $nbtext = empty($infos[1][0]) ? 0 : count($infos[1][0]);
  213. $nbfail = 0;
  214. if(!empty($infos[0][0])) $nbfail += count($infos[0][0]);
  215. if(!empty($infos[0][1])) $nbfail += count($infos[0][1]);
  216. $query = 'UPDATE '.acymailing::table('stats').' SET senthtml = senthtml + '.$nbhtml.', senttext = senttext + '.$nbtext.', fail = fail + '.$nbfail.', senddate = '.$time.' WHERE mailid = '.$mailid.' LIMIT 1';
  217. $this->db->setQuery($query);
  218. $this->db->query();
  219. if(!$this->db->getAffectedRows()){
  220. $query = 'INSERT INTO '.acymailing::table('stats').' (mailid,senthtml,senttext,fail,senddate) VALUES ('.$mailid.','.$nbhtml.', '.$nbtext.', '.$nbfail.', '.$time.')';
  221. $this->db->setQuery($query);
  222. $this->db->query();
  223. }
  224. }
  225. }
  226. function _queueUpdate($queueUpdate){
  227. if(empty($queueUpdate)) return true;
  228. $delay = $this->config->get('queue_delay',3600);
  229. foreach($queueUpdate as $mailid => $subscribers){
  230. $query = 'UPDATE '.acymailing::table('queue').' SET senddate = senddate + '.$delay.', try = try +1 WHERE mailid = '.$mailid.' AND subid IN ('.implode(',',$subscribers).')';
  231. $this->db->setQuery($query);
  232. $this->db->query();
  233. }
  234. }
  235. function _handleError(){
  236. $this->finish = true;
  237. $message = JText::_('SEND_STOPED',true);
  238. $message .= '<br/>';
  239. $message .= JText::_('SEND_KEPT_ALL',true);
  240. $message .= '<br/>';
  241. if($this->report){
  242. if(empty($this->successSend) AND empty($this->start)){
  243. $message .= JText::_('SEND_CHECKONE',true);
  244. $message .= '<br/>';
  245. $message .= JText::_('SEND_ADVISE_LIMITATION',true);
  246. }else{
  247. $message .= JText::_('SEND_REFUSE',true);
  248. $message .= '<br/>';
  249. if(!acymailing::level(1)){
  250. $message .= JText::_('SEND_CONTINUE_COMMERCIAL',true);
  251. }else{
  252. $message .= JText::_('SEND_CONTINUE_AUTO',true);
  253. }
  254. }
  255. }
  256. $this->_display($message);
  257. }
  258. function _display($message,$status = '',$num = ''){
  259. $this->messages[] = $message;
  260. if(!$this->report) return;
  261. if(!empty($num)){
  262. $color = $status ? 'green' : 'red';
  263. echo '<br/>'.$num.' : <font color="'.$color.'">'.$message.'</font>';
  264. }else{
  265. echo '<script type="text/javascript" language="javascript">setInfo(\''. $message .'\')</script>';
  266. }
  267. if(function_exists('ob_flush')) @ob_flush();
  268. @flush();
  269. }
  270. function _subscriberAction($subid){
  271. if($this->config->get('bounce_action_maxtry') == 'delete'){
  272. $this->subClass->delete($subid);
  273. return ' user '.$subid.' deleted';
  274. }
  275. $listId = 0;
  276. if(in_array($this->config->get('bounce_action_maxtry'),array('sub','remove','unsub'))){
  277. $status = $this->subClass->getSubscriptionStatus($subid);
  278. }
  279. $message = '';
  280. switch($this->config->get('bounce_action_maxtry')){
  281. case 'sub' :
  282. $listId = $this->config->get('bounce_action_lists_maxtry');
  283. if(!empty($listId)){
  284. $message .= ' user '.$subid.' subscribed to '.$listId;
  285. if(empty($status[$listId])){
  286. $this->listsubClass->addSubscription($subid,array('1' => array($listId)));
  287. }elseif($status[$listId]->status != 1){
  288. $this->listsubClass->updateSubscription($subid,array('1' => array($listId)));
  289. }
  290. }
  291. case 'remove' :
  292. $unsubLists = array_diff(array_keys($status),array($listId));
  293. if(!empty($unsubLists)){
  294. $message .= ' | user '.$subid.' removed from lists '.implode(',',$unsubLists);
  295. $this->listsubClass->removeSubscription($subid,$unsubLists);
  296. }else{
  297. $message .= ' | user '.$subid.' not subscribed';
  298. }
  299. break;
  300. case 'unsub' :
  301. $unsubLists = array_diff(array_keys($status),array($listId));
  302. if(!empty($unsubLists)){
  303. $message .= ' | user '.$subid.' unsubscribed from lists '.implode(',',$unsubLists);
  304. $this->listsubClass->updateSubscription($subid,array('-1' => $unsubLists));
  305. }else{
  306. $message .= ' | user '.$subid.' not subscribed';
  307. }
  308. break;
  309. case 'delete' :
  310. $message .= ' | user '.$subid.' deleted';
  311. $this->subClass->delete($subid);
  312. break;
  313. case 'block' :
  314. $message .= ' | user '.$subid.' blocked';
  315. $this->db->setQuery('UPDATE `#__acymailing_subscriber` SET `enabled` = 0 WHERE `subid` = '.intval($subid));
  316. $this->db->query();
  317. $this->db->setQuery('DELETE FROM `#__acymailing_queue` WHERE `subid` = '.intval($subid));
  318. $this->db->query();
  319. break;
  320. }
  321. return $message;
  322. }
  323. }