Merge branch 'master' of github.com:civicrm/civicrm-core into code-cleanup-batch-15
[civicrm-core.git] / CRM / Mailing / Event / BAO / Delivered.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.6 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2014
32 * $Id$
33 *
34 */
35 class CRM_Mailing_Event_BAO_Delivered extends CRM_Mailing_Event_DAO_Delivered {
36
37 /**
38 * Class constructor
39 */
40 public function __construct() {
41 parent::__construct();
42 }
43
44 /**
45 * Create a new delivery event
46 *
47 * @param array $params
48 * Associative array of delivery event values.
49 *
50 * @return void
51 */
52 public static function &create(&$params) {
53 $q = &CRM_Mailing_Event_BAO_Queue::verify($params['job_id'],
54 $params['event_queue_id'],
55 $params['hash']
56 );
57
58 if (!$q) {
59 return NULL;
60 }
61 $q->free();
62
63 $delivered = new CRM_Mailing_Event_BAO_Delivered();
64 $delivered->time_stamp = date('YmdHis');
65 $delivered->copyValues($params);
66 $delivered->save();
67
68 $queue = new CRM_Mailing_Event_BAO_Queue();
69 $queue->id = $params['event_queue_id'];
70 $queue->find(TRUE);
71
72 while ($queue->fetch()) {
73 $email = new CRM_Core_BAO_Email();
74 $email->id = $queue->email_id;
75 $email->hold_date = '';
76 $email->reset_date = date('YmdHis');
77 $email->save();
78 }
79
80 return $delivered;
81 }
82
83 /**
84 * Get row count for the event selector
85 *
86 * @param int $mailing_id
87 * ID of the mailing.
88 * @param int $job_id
89 * Optional ID of a job to filter on.
90 * @param bool $is_distinct
91 * Group by queue ID?.
92 *
93 * @return int
94 * Number of rows in result set
95 */
96 public static function getTotalCount($mailing_id, $job_id = NULL, $is_distinct = FALSE, $toDate = NULL) {
97 $dao = new CRM_Core_DAO();
98
99 $delivered = self::getTableName();
100 $bounce = CRM_Mailing_Event_BAO_Bounce::getTableName();
101 $queue = CRM_Mailing_Event_BAO_Queue::getTableName();
102 $mailing = CRM_Mailing_BAO_Mailing::getTableName();
103 $job = CRM_Mailing_BAO_MailingJob::getTableName();
104
105 $query = "
106 SELECT COUNT($delivered.id) as delivered
107 FROM $delivered
108 INNER JOIN $queue
109 ON $delivered.event_queue_id = $queue.id
110 LEFT JOIN $bounce
111 ON $delivered.event_queue_id = $bounce.event_queue_id
112 INNER JOIN $job
113 ON $queue.job_id = $job.id
114 AND $job.is_test = 0
115 INNER JOIN $mailing
116 ON $job.mailing_id = $mailing.id
117 WHERE $bounce.id IS null
118 AND $mailing.id = " . CRM_Utils_Type::escape($mailing_id, 'Integer');
119
120 if (!empty($toDate)) {
121 $query .= " AND $delivered.time_stamp <= $toDate";
122 }
123
124 if (!empty($job_id)) {
125 $query .= " AND $job.id = " . CRM_Utils_Type::escape($job_id, 'Integer');
126 }
127
128 if ($is_distinct) {
129 $query .= " GROUP BY $queue.id ";
130 }
131
132 // query was missing
133 $dao->query($query);
134
135 if ($dao->fetch()) {
136 return $dao->delivered;
137 }
138
139 return NULL;
140 }
141
142 /**
143 * Get rows for the event browser
144 *
145 * @param int $mailing_id
146 * ID of the mailing.
147 * @param int $job_id
148 * Optional ID of the job.
149 * @param bool $is_distinct
150 * Group by queue id?.
151 * @param int $offset
152 * Offset.
153 * @param int $rowCount
154 * Number of rows.
155 * @param array $sort
156 * Sort array.
157 *
158 * @return array
159 * Result set
160 */
161 public static function &getRows(
162 $mailing_id, $job_id = NULL,
163 $is_distinct = FALSE, $offset = NULL, $rowCount = NULL, $sort = NULL, $is_test = 0
164 ) {
165
166 $dao = new CRM_Core_Dao();
167
168 $delivered = self::getTableName();
169 $bounce = CRM_Mailing_Event_BAO_Bounce::getTableName();
170 $queue = CRM_Mailing_Event_BAO_Queue::getTableName();
171 $mailing = CRM_Mailing_BAO_Mailing::getTableName();
172 $job = CRM_Mailing_BAO_MailingJob::getTableName();
173 $contact = CRM_Contact_BAO_Contact::getTableName();
174 $email = CRM_Core_BAO_Email::getTableName();
175
176 $query = "
177 SELECT $delivered.id as id,
178 $contact.display_name as display_name,
179 $contact.id as contact_id,
180 $email.email as email,
181 $delivered.time_stamp as date
182 FROM $contact
183 INNER JOIN $queue
184 ON $queue.contact_id = $contact.id
185 INNER JOIN $email
186 ON $queue.email_id = $email.id
187 INNER JOIN $delivered
188 ON $delivered.event_queue_id = $queue.id
189 LEFT JOIN $bounce
190 ON $bounce.event_queue_id = $queue.id
191 INNER JOIN $job
192 ON $queue.job_id = $job.id
193 AND $job.is_test = $is_test
194 INNER JOIN $mailing
195 ON $job.mailing_id = $mailing.id
196 WHERE $bounce.id IS null
197 AND $mailing.id = " . CRM_Utils_Type::escape($mailing_id, 'Integer');
198
199 if (!empty($job_id)) {
200 $query .= " AND $job.id = " . CRM_Utils_Type::escape($job_id, 'Integer');
201 }
202
203 if ($is_distinct) {
204 $query .= " GROUP BY $queue.id ";
205 }
206
207 $orderBy = "sort_name ASC, {$delivered}.time_stamp DESC";
208 if ($sort) {
209 if (is_string($sort)) {
210 $sort = CRM_Utils_Type::escape($sort, 'String');
211 $orderBy = $sort;
212 }
213 else {
214 $orderBy = trim($sort->orderBy());
215 }
216 }
217
218 $query .= " ORDER BY {$orderBy} ";
219
220 if ($offset || $rowCount) {
221 //Added "||$rowCount" to avoid displaying all records on first page
222 $query .= ' LIMIT ' . CRM_Utils_Type::escape($offset, 'Integer') . ', ' . CRM_Utils_Type::escape($rowCount, 'Integer');
223 }
224
225 $dao->query($query);
226
227 $results = array();
228
229 while ($dao->fetch()) {
230 $url = CRM_Utils_System::url('civicrm/contact/view',
231 "reset=1&cid={$dao->contact_id}"
232 );
233 $results[$dao->id] = array(
234 'contact_id' => $dao->contact_id,
235 'name' => "<a href=\"$url\">{$dao->display_name}</a>",
236 'email' => $dao->email,
237 'date' => CRM_Utils_Date::customFormat($dao->date),
238 );
239 }
240 return $results;
241 }
242
243 /**
244 * @param $eventQueueIDs
245 * @param null $time
246 */
247 public static function bulkCreate($eventQueueIDs, $time = NULL) {
248 if (!$time) {
249 $time = date('YmdHis');
250 }
251
252 // construct a bulk insert statement
253 $values = array();
254 foreach ($eventQueueIDs as $eqID) {
255 $values[] = "( $eqID, '{$time}' )";
256 }
257
258 while (!empty($values)) {
259 $input = array_splice($values, 0, CRM_Core_DAO::BULK_INSERT_COUNT);
260 $str = implode(',', $input);
261 $sql = "INSERT INTO civicrm_mailing_event_delivered ( event_queue_id, time_stamp ) VALUES $str;";
262 CRM_Core_DAO::executeQuery($sql);
263 }
264 }
265
266 /**
267 * Since we never no when a mailing really bounces (hard bounce == NOW, soft bounce == NOW to NOW + 3 days?)
268 * we cannot decide when an email address last got an email.
269 *
270 * We want to avoid putting on hold an email address which had a few bounces (mbox full) and then got quite a few
271 * successfull deliveries before starting the bounce again. The current code does not set the resetDate and hence
272 * the above scenario results in the email being put on hold
273 *
274 * This function rectifies that by considering all non-test mailing jobs which have completed between $minDays and $maxDays
275 * and setting the resetDate to the date that an email was delivered
276 *
277 * @param int $minDays
278 * Consider mailings that were completed at least $minDays ago.
279 * @param int $maxDays
280 * Consider mailings that were completed not more than $maxDays ago.
281 *
282 * @return void
283 */
284 public static function updateEmailResetDate($minDays = 3, $maxDays = 7) {
285 $dao = new CRM_Core_Dao();
286
287 $query = "
288 CREATE TEMPORARY TABLE civicrm_email_temp_values (
289 id int primary key,
290 reset_date datetime
291 ) ENGINE = HEAP;
292 ";
293 CRM_Core_DAO::executeQuery($query);
294
295 $query = "
296 INSERT INTO civicrm_email_temp_values (id, reset_date)
297 SELECT civicrm_email.id as email_id,
298 max(civicrm_mailing_event_delivered.time_stamp) as reset_date
299 FROM civicrm_mailing_event_queue
300 INNER JOIN civicrm_email ON civicrm_mailing_event_queue.email_id = civicrm_email.id
301 INNER JOIN civicrm_mailing_event_delivered ON civicrm_mailing_event_delivered.event_queue_id = civicrm_mailing_event_queue.id
302 LEFT JOIN civicrm_mailing_event_bounce ON civicrm_mailing_event_bounce.event_queue_id = civicrm_mailing_event_queue.id
303 INNER JOIN civicrm_mailing_job ON civicrm_mailing_event_queue.job_id = civicrm_mailing_job.id AND civicrm_mailing_job.is_test = 0
304 WHERE civicrm_mailing_event_bounce.id IS NULL
305 AND civicrm_mailing_job.status = 'Complete'
306 AND civicrm_mailing_job.end_date BETWEEN DATE_SUB(NOW(), INTERVAL $maxDays day) AND DATE_SUB(NOW(), INTERVAL $minDays day)
307 AND (civicrm_email.reset_date IS NULL OR civicrm_email.reset_date < civicrm_mailing_job.start_date)
308 GROUP BY civicrm_email.id
309 ";
310
311 $query = "
312 UPDATE civicrm_email e
313 INNER JOIN civicrm_email_temp_values et ON e.id = et.id
314 SET e.on_hold = 0,
315 e.hold_date = NULL,
316 e.reset_date = et.reset_date
317 ";
318 CRM_Core_DAO::executeQuery($query);
319 }
320
321 }