commiting uncommited changes on live site
[weblabels.fsf.org.git] / crm.fsf.org / 20131203 / files / sites / all / modules-old / civicrm / CRM / Mailing / Selector / Browse.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.6 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2015 |
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-2015
32 * $Id$
33 *
34 */
35
36 /**
37 * This class is used to browse past mailings.
38 */
39 class CRM_Mailing_Selector_Browse extends CRM_Core_Selector_Base implements CRM_Core_Selector_API {
40
41 /**
42 * Array of supported links, currenly null
43 *
44 * @var array
45 */
46 static $_links = NULL;
47
48 /**
49 * We use desc to remind us what that column is, name is used in the tpl
50 *
51 * @var array
52 */
53 static $_columnHeaders;
54
55 protected $_parent;
56
57 /**
58 * Class constructor.
59 *
60 *
61 * @return \CRM_Mailing_Selector_Browse
62 */
63 public function __construct() {
64 }
65
66 /**
67 * This method returns the links that are given for each search row.
68 *
69 * @return array
70 */
71 public static function &links() {
72 return self::$_links;
73 }
74
75 /**
76 * Getter for array of the parameters required for creating pager.
77 *
78 * @param $action
79 * @param array $params
80 */
81 public function getPagerParams($action, &$params) {
82 $params['csvString'] = NULL;
83 $params['rowCount'] = CRM_Utils_Pager::ROWCOUNT;
84 $params['status'] = ts('Mailings %%StatusMessage%%');
85 $params['buttonTop'] = 'PagerTopButton';
86 $params['buttonBottom'] = 'PagerBottomButton';
87 }
88
89 /**
90 * Returns the column headers as an array of tuples:
91 * (name, sortName (key to the sort array))
92 *
93 * @param string $action
94 * The action being performed.
95 * @param string $output
96 * What should the result set include (web/email/csv).
97 *
98 * @return array
99 * the column headers that need to be displayed
100 */
101 public function &getColumnHeaders($action = NULL, $output = NULL) {
102 $mailing = CRM_Mailing_BAO_Mailing::getTableName();
103 $job = CRM_Mailing_BAO_MailingJob::getTableName();
104 if (!isset(self::$_columnHeaders)) {
105 $completedOrder = NULL;
106
107 // Set different default sort depending on type of mailings (CRM-7652)
108 $unscheduledOrder = $scheduledOrder = $archivedOrder = CRM_Utils_Sort::DONTCARE;
109 if ($this->_parent->get('unscheduled')) {
110 $unscheduledOrder = CRM_Utils_Sort::DESCENDING;
111 }
112 elseif ($this->_parent->get('scheduled')) {
113 $scheduledOrder = CRM_Utils_Sort::DESCENDING;
114 }
115 else {
116 // sort by completed date for archived and undefined get
117 $completedOrder = CRM_Utils_Sort::DESCENDING;
118 }
119 $nameHeaderLabel = ($this->_parent->get('sms')) ? ts('SMS Name') : ts('Mailing Name');
120
121 self::$_columnHeaders = array(
122 array(
123 'name' => $nameHeaderLabel,
124 'sort' => 'name',
125 'direction' => CRM_Utils_Sort::DONTCARE,
126 ),
127 array(
128 'name' => ts('Status'),
129 'sort' => 'status',
130 'direction' => CRM_Utils_Sort::DONTCARE,
131 ),
132 array(
133 'name' => ts('Created By'),
134 'sort' => 'created_by',
135 'direction' => CRM_Utils_Sort::DONTCARE,
136 ),
137 array(
138 'name' => ts('Created Date'),
139 'sort' => 'created_date',
140 'direction' => $unscheduledOrder,
141 ),
142 array(
143 'name' => ts('Sent By'),
144 'sort' => 'scheduled_by',
145 'direction' => CRM_Utils_Sort::DONTCARE,
146 ),
147 array(
148 'name' => ts('Scheduled'),
149 'sort' => 'scheduled_date',
150 'direction' => $scheduledOrder,
151 ),
152 array(
153 'name' => ts('Started'),
154 'sort' => 'start_date',
155 'direction' => CRM_Utils_Sort::DONTCARE,
156 ),
157 array(
158 'name' => ts('Completed'),
159 'sort' => 'end_date',
160 'direction' => $completedOrder,
161 ),
162 );
163
164 if (CRM_Campaign_BAO_Campaign::isCampaignEnable()) {
165 self::$_columnHeaders[] = array(
166 'name' => ts('Campaign'),
167 'sort' => 'campaign_id',
168 'direction' => CRM_Utils_Sort::DONTCARE,
169 );
170 }
171
172 if ($output != CRM_Core_Selector_Controller::EXPORT) {
173 self::$_columnHeaders[] = array('name' => ts('Action'));
174 }
175 }
176 return self::$_columnHeaders;
177 }
178
179 /**
180 * Returns total number of rows for the query.
181 *
182 * @param
183 *
184 * @return int
185 * Total number of rows
186 */
187 public function getTotalCount($action) {
188 $job = CRM_Mailing_BAO_MailingJob::getTableName();
189 $mailing = CRM_Mailing_BAO_Mailing::getTableName();
190 $mailingACL = CRM_Mailing_BAO_Mailing::mailingACL();
191
192 //get the where clause.
193 $params = array();
194 $whereClause = "$mailingACL AND " . $this->whereClause($params);
195
196 // CRM-11919 added addition ON clauses to mailing_job to match getRows
197 $query = "
198 SELECT COUNT( DISTINCT $mailing.id ) as count
199 FROM $mailing
200 LEFT JOIN $job ON ( $mailing.id = $job.mailing_id AND civicrm_mailing_job.is_test = 0 AND civicrm_mailing_job.parent_id IS NULL )
201 LEFT JOIN civicrm_contact createdContact ON ( $mailing.created_id = createdContact.id )
202 LEFT JOIN civicrm_contact scheduledContact ON ( $mailing.scheduled_id = scheduledContact.id )
203 WHERE $whereClause";
204
205 return CRM_Core_DAO::singleValueQuery($query, $params);
206 }
207
208 /**
209 * Returns all the rows in the given offset and rowCount.
210 *
211 * @param string $action
212 * The action being performed.
213 * @param int $offset
214 * The row number to start from.
215 * @param int $rowCount
216 * The number of rows to return.
217 * @param string $sort
218 * The sql string that describes the sort order.
219 * @param string $output
220 * What should the result set include (web/email/csv).
221 *
222 * @return int
223 * the total number of rows for this action
224 */
225 public function &getRows($action, $offset, $rowCount, $sort, $output = NULL) {
226 static $actionLinks = NULL;
227 if (empty($actionLinks)) {
228 $cancelExtra = ts('Are you sure you want to cancel this mailing?');
229 $deleteExtra = ts('Are you sure you want to delete this mailing?');
230 $archiveExtra = ts('Are you sure you want to archive this mailing?');
231
232 $actionLinks = array(
233 CRM_Core_Action::ENABLE => array(
234 'name' => ts('Approve/Reject'),
235 'url' => 'civicrm/mailing/approve',
236 'qs' => 'mid=%%mid%%&reset=1',
237 'title' => ts('Approve/Reject Mailing'),
238 ),
239 CRM_Core_Action::VIEW => array(
240 'name' => ts('Report'),
241 'url' => 'civicrm/mailing/report',
242 'qs' => 'mid=%%mid%%&reset=1',
243 'title' => ts('View Mailing Report'),
244 ),
245 CRM_Core_Action::UPDATE => array(
246 'name' => ts('Re-Use'),
247 'url' => 'civicrm/mailing/send',
248 'qs' => 'mid=%%mid%%&reset=1',
249 'title' => ts('Re-Send Mailing'),
250 ),
251 CRM_Core_Action::DISABLE => array(
252 'name' => ts('Cancel'),
253 'url' => 'civicrm/mailing/browse',
254 'qs' => 'action=disable&mid=%%mid%%&reset=1',
255 'extra' => 'onclick="if (confirm(\'' . $cancelExtra . '\')) this.href+=\'&amp;confirmed=1\'; else return false;"',
256 'title' => ts('Cancel Mailing'),
257 ),
258 CRM_Core_Action::PREVIEW => array(
259 'name' => ts('Continue'),
260 'url' => 'civicrm/mailing/send',
261 'qs' => 'mid=%%mid%%&continue=true&reset=1',
262 'title' => ts('Continue Mailing'),
263 ),
264 CRM_Core_Action::DELETE => array(
265 'name' => ts('Delete'),
266 'url' => 'civicrm/mailing/browse',
267 'qs' => 'action=delete&mid=%%mid%%&reset=1',
268 'extra' => 'onclick="if (confirm(\'' . $deleteExtra . '\')) this.href+=\'&amp;confirmed=1\'; else return false;"',
269 'title' => ts('Delete Mailing'),
270 ),
271 CRM_Core_Action::RENEW => array(
272 'name' => ts('Archive'),
273 'url' => 'civicrm/mailing/browse/archived',
274 'qs' => 'action=renew&mid=%%mid%%&reset=1',
275 'extra' => 'onclick="if (confirm(\'' . $archiveExtra . '\')) this.href+=\'&amp;confirmed=1\'; else return false;"',
276 'title' => ts('Archive Mailing'),
277 ),
278 );
279 }
280
281 $allAccess = TRUE;
282 $workFlow = $showApprovalLinks = $showScheduleLinks = $showCreateLinks = FALSE;
283 if (CRM_Mailing_Info::workflowEnabled()) {
284 $allAccess = FALSE;
285 $workFlow = TRUE;
286 //supercedes all permission
287 if (CRM_Core_Permission::check('access CiviMail')) {
288 $allAccess = TRUE;
289 }
290
291 if (CRM_Core_Permission::check('approve mailings')) {
292 $showApprovalLinks = TRUE;
293 }
294
295 if (CRM_Core_Permission::check('create mailings')) {
296 $showCreateLinks = TRUE;
297 }
298
299 if (CRM_Core_Permission::check('schedule mailings')) {
300 $showScheduleLinks = TRUE;
301 }
302 }
303 $mailing = new CRM_Mailing_BAO_Mailing();
304
305 $params = array();
306
307 $whereClause = ' AND ' . $this->whereClause($params);
308
309 if (empty($params)) {
310 $this->_parent->assign('isSearch', 0);
311 }
312 else {
313 $this->_parent->assign('isSearch', 1);
314 }
315 $rows = &$mailing->getRows($offset, $rowCount, $sort, $whereClause, $params);
316
317 //get the search base mailing Ids, CRM-3711.
318 $searchMailings = $mailing->searchMailingIDs();
319
320 //check for delete CRM-4418
321 $allowToDelete = CRM_Core_Permission::check('delete in CiviMail');
322
323 if ($output != CRM_Core_Selector_Controller::EXPORT) {
324
325 //create the appropriate $op to use for hook_civicrm_links
326 $pageTypes = array('view', 'mailing', 'browse');
327 if ($this->_parent->_unscheduled) {
328 $pageTypes[] = 'unscheduled';
329 }
330 if ($this->_parent->_scheduled) {
331 $pageTypes[] = 'scheduled';
332 }
333 if ($this->_parent->_archived) {
334 $pageTypes[] = 'archived';
335 }
336 $opString = implode('.', $pageTypes);
337
338 foreach ($rows as $key => $row) {
339 $actionMask = NULL;
340 if ($row['sms_provider_id']) {
341 $actionLinks[CRM_Core_Action::PREVIEW]['url'] = 'civicrm/sms/send';
342 }
343
344 if (!($row['status'] == 'Not scheduled') && !$row['sms_provider_id']) {
345 if ($allAccess || $showCreateLinks) {
346 $actionMask = CRM_Core_Action::VIEW;
347 }
348
349 if (!in_array($row['id'], $searchMailings)) {
350 if ($allAccess || $showCreateLinks) {
351 $actionMask |= CRM_Core_Action::UPDATE;
352 }
353 }
354 }
355 else {
356 if ($allAccess || ($showCreateLinks || $showScheduleLinks)) {
357 $actionMask = CRM_Core_Action::PREVIEW;
358 }
359 }
360 if (in_array($row['status'], array(
361 'Scheduled',
362 'Running',
363 'Paused',
364 ))) {
365 if ($allAccess ||
366 ($showApprovalLinks && $showCreateLinks && $showScheduleLinks)
367 ) {
368
369 $actionMask |= CRM_Core_Action::DISABLE;
370 }
371 if ($row['status'] == 'Scheduled' &&
372 empty($row['approval_status_id'])
373 ) {
374 if ($workFlow && ($allAccess || $showApprovalLinks)) {
375 $actionMask |= CRM_Core_Action::ENABLE;
376 }
377 }
378 }
379
380 if (in_array($row['status'], array('Complete', 'Canceled')) &&
381 !$row['archived']
382 ) {
383 if ($allAccess || $showCreateLinks) {
384 $actionMask |= CRM_Core_Action::RENEW;
385 }
386 }
387
388 //check for delete permission.
389 if ($allowToDelete) {
390 $actionMask |= CRM_Core_Action::DELETE;
391 }
392
393 if ($actionMask == NULL) {
394 $actionMask = CRM_Core_Action::ADD;
395 }
396 //get status strings as per locale settings CRM-4411.
397 $rows[$key]['status'] = CRM_Mailing_BAO_MailingJob::status($row['status']);
398
399 $rows[$key]['action'] = CRM_Core_Action::formLink($actionLinks,
400 $actionMask,
401 array('mid' => $row['id']),
402 "more",
403 FALSE,
404 $opString,
405 "Mailing",
406 $row['id']
407 );
408
409 //unset($rows[$key]['id']);
410 // if the scheduled date is 0, replace it with an empty string
411 if ($rows[$key]['scheduled_iso'] == '0000-00-00 00:00:00') {
412 $rows[$key]['scheduled'] = '';
413 }
414 unset($rows[$key]['scheduled_iso']);
415 }
416 }
417
418 // also initialize the AtoZ pager
419 $this->pagerAtoZ();
420 return $rows;
421 }
422
423 /**
424 * Name of export file.
425 *
426 * @param string $output
427 * Type of output.
428 *
429 * @return string
430 * name of the file
431 */
432 public function getExportFileName($output = 'csv') {
433 return ts('CiviMail Mailings');
434 }
435
436 /**
437 * @param $parent
438 */
439 public function setParent($parent) {
440 $this->_parent = $parent;
441 }
442
443 /**
444 * @param array $params
445 * @param bool $sortBy
446 *
447 * @return int|string
448 */
449 public function whereClause(&$params, $sortBy = TRUE) {
450 $values = $clauses = array();
451 $isFormSubmitted = $this->_parent->get('hidden_find_mailings');
452
453 $title = $this->_parent->get('mailing_name');
454 if ($title) {
455 $clauses[] = 'name LIKE %1';
456 if (strpos($title, '%') !== FALSE) {
457 $params[1] = array($title, 'String', FALSE);
458 }
459 else {
460 $params[1] = array($title, 'String', TRUE);
461 }
462 }
463
464 $dateClause1 = $dateClause2 = array();
465 $from = $this->_parent->get('mailing_from');
466 if (!CRM_Utils_System::isNull($from)) {
467 if ($this->_parent->get('unscheduled')) {
468 $dateClause1[] = 'civicrm_mailing.created_date >= %2';
469 }
470 else {
471 $dateClause1[] = 'civicrm_mailing_job.start_date >= %2';
472 $dateClause2[] = 'civicrm_mailing_job.scheduled_date >= %2';
473 }
474 $params[2] = array($from, 'String');
475 }
476
477 $to = $this->_parent->get('mailing_to');
478 if (!CRM_Utils_System::isNull($to)) {
479 if ($this->_parent->get('unscheduled')) {
480 $dateClause1[] = ' civicrm_mailing.created_date <= %3 ';
481 }
482 else {
483 $dateClause1[] = 'civicrm_mailing_job.start_date <= %3';
484 $dateClause2[] = 'civicrm_mailing_job.scheduled_date <= %3';
485 }
486 $params[3] = array($to, 'String');
487 }
488
489 $dateClauses = array();
490 if (!empty($dateClause1)) {
491 $dateClauses[] = implode(' AND ', $dateClause1);
492 }
493 if (!empty($dateClause2)) {
494 $dateClauses[] = implode(' AND ', $dateClause2);
495 }
496 $dateClauses = implode(' OR ', $dateClauses);
497 if (!empty($dateClauses)) {
498 $clauses[] = "({$dateClauses})";
499 }
500
501 if ($this->_parent->get('sms')) {
502 $clauses[] = "civicrm_mailing.sms_provider_id IS NOT NULL";
503 }
504 else {
505 $clauses[] = "civicrm_mailing.sms_provider_id IS NULL";
506 }
507
508 // get values submitted by form
509 $isDraft = $this->_parent->get('status_unscheduled');
510 $isArchived = $this->_parent->get('is_archived');
511 $mailingStatus = $this->_parent->get('mailing_status');
512
513 if (!$isFormSubmitted && $this->_parent->get('scheduled')) {
514 // mimic default behavior for scheduled screen
515 $isArchived = 0;
516 $mailingStatus = array('Scheduled' => 1, 'Complete' => 1, 'Running' => 1, 'Canceled' => 1);
517 }
518 if (!$isFormSubmitted && $this->_parent->get('archived')) {
519 // mimic default behavior for archived screen
520 $isArchived = 1;
521 }
522 if (!$isFormSubmitted && $this->_parent->get('unscheduled')) {
523 // mimic default behavior for draft screen
524 $isDraft = 1;
525 }
526
527 $statusClauses = array();
528 if ($isDraft) {
529 $statusClauses[] = "civicrm_mailing.scheduled_id IS NULL";
530 }
531 if (!empty($mailingStatus)) {
532 $statusClauses[] = "civicrm_mailing_job.status IN ('" . implode("', '", array_keys($mailingStatus)) . "')";
533 }
534 if (!empty($statusClauses)) {
535 $clauses[] = "(" . implode(' OR ', $statusClauses) . ")";
536 }
537
538 if (isset($isArchived)) {
539 if ($isArchived) {
540 $clauses[] = "civicrm_mailing.is_archived = 1";
541 }
542 else {
543 $clauses[] = "(civicrm_mailing.is_archived IS NULL OR civicrm_mailing.is_archived = 0)";
544 }
545 }
546
547 if ($sortBy &&
548 $this->_parent->_sortByCharacter !== NULL
549 ) {
550 $clauses[] = "name LIKE '" . strtolower(CRM_Core_DAO::escapeWildCardString($this->_parent->_sortByCharacter)) . "%'";
551 }
552
553 // dont do a the below assignement when doing a
554 // AtoZ pager clause
555 if ($sortBy) {
556 if (count($clauses) > 1) {
557 $this->_parent->assign('isSearch', 1);
558 }
559 else {
560 $this->_parent->assign('isSearch', 0);
561 }
562 }
563
564 $createOrSentBy = $this->_parent->get('sort_name');
565 if (!CRM_Utils_System::isNull($createOrSentBy)) {
566 $clauses[] = '(createdContact.sort_name LIKE %4 OR scheduledContact.sort_name LIKE %4)';
567 $params[4] = array('%' . $createOrSentBy . '%', 'String');
568 }
569
570 $createdId = $this->_parent->get('createdId');
571 if ($createdId) {
572 $clauses[] = "(created_id = {$createdId})";
573 $params[5] = array($createdId, 'Integer');
574 }
575
576 $campainIds = $this->_parent->get('campaign_id');
577 if (!CRM_Utils_System::isNull($campainIds)) {
578 if (!is_array($campainIds)) {
579 $campaignIds = array($campaignIds);
580 }
581 $clauses[] = '( campaign_id IN ( ' . implode(' , ', array_values($campainIds)) . ' ) )';
582 }
583
584 if (empty($clauses)) {
585 return 1;
586 }
587
588 return implode(' AND ', $clauses);
589 }
590
591 public function pagerAtoZ() {
592
593 $params = array();
594 $whereClause = $this->whereClause($params, FALSE);
595
596 $query = "
597 SELECT DISTINCT UPPER(LEFT(name, 1)) as sort_name
598 FROM civicrm_mailing
599 LEFT JOIN civicrm_mailing_job ON (civicrm_mailing_job.mailing_id = civicrm_mailing.id)
600 LEFT JOIN civicrm_contact createdContact ON ( civicrm_mailing.created_id = createdContact.id )
601 LEFT JOIN civicrm_contact scheduledContact ON ( civicrm_mailing.scheduled_id = scheduledContact.id )
602 WHERE $whereClause
603 ORDER BY LEFT(name, 1)
604 ";
605
606 $dao = CRM_Core_DAO::executeQuery($query, $params);
607
608 $aToZBar = CRM_Utils_PagerAToZ::getAToZBar($dao, $this->_parent->_sortByCharacter, TRUE);
609 $this->_parent->assign('aToZ', $aToZBar);
610 }
611
612 }