Import from SVN (r45945, r596)
[civicrm-core.git] / CRM / Mailing / Form / Group.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.3 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
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-2013
32 * $Id$
33 *
34 */
35
36/**
37 * Choose include / exclude groups and mailings
38 *
39 */
40class CRM_Mailing_Form_Group extends CRM_Contact_Form_Task {
41
42 /**
43 * the mailing ID of the mailing if we are resuming a mailing
44 *
45 * @var integer
46 */
47 protected $_mailingID;
48
49 /**
50 * Function to set variables up before form is built
51 *
52 * @return void
53 * @access public
54 */
55 public function preProcess() {
56 if (CRM_Core_BAO_MailSettings::defaultDomain() == "EXAMPLE.ORG") {
57 CRM_Core_Error::fatal(ts('The <a href="%1">default mailbox</a> has not been configured. You will find <a href="%2">more info in our online user and administrator guide.</a>', array(1 => CRM_Utils_System::url('civicrm/admin/mailSettings', 'reset=1'), 2 => "http://book.civicrm.org/user/initial-set-up/email-system-configuration")));
58 }
59
60 $this->_mailingID = CRM_Utils_Request::retrieve('mid', 'Integer', $this, FALSE, NULL);
61
62 // when user come from search context.
63 $this->_searchBasedMailing = CRM_Contact_Form_Search::isSearchContext($this->get('context'));
64 if ($this->_searchBasedMailing) {
65 $searchParams = $this->controller->exportValues();
66 // number of records that were selected - All or Few.
67 $this->_resultSelectOption = $searchParams['radio_ts'];
68 if (CRM_Utils_Array::value('task', $searchParams) == 20) {
69 parent::preProcess();
70 }
71 }
72
73 $session = CRM_Core_Session::singleton();
74 if ($this->_searchBasedMailing) {
75 $config = CRM_Core_Config::singleton();
76 $path = CRM_Utils_Array::value($config->userFrameworkURLVar, $_GET);
77 $qfKey = CRM_Utils_Array::value('qfKey', $_GET);
78 if ($qfKey) {
79 $session->pushUserContext(CRM_Utils_System::url($path, "qfKey=$qfKey"));
80 }
81 else {
82 $session->pushUserContext(CRM_Utils_System::url('civicrm/mailing', 'reset=1'));
83 }
84 }
85 elseif (strpos($session->readUserContext(), 'civicrm/mailing') === FALSE) {
86 // use previous context unless mailing is not schedule, CRM-4290
87 $session->pushUserContext(CRM_Utils_System::url('civicrm/mailing', 'reset=1'));
88 }
89 }
90
91 /**
92 * This function sets the default values for the form.
93 * the default values are retrieved from the database
94 *
95 * @access public
96 *
97 * @return None
98 */
99 function setDefaultValues() {
100 $continue = CRM_Utils_Request::retrieve('continue', 'String', $this, FALSE, NULL);
101
102 $defaults = array();
103 if ($this->_mailingID) {
104 // check that the user has permission to access mailing id
105 CRM_Mailing_BAO_Mailing::checkPermission($this->_mailingID);
106
107 $mailing = new CRM_Mailing_DAO_Mailing();
108 $mailing->id = $this->_mailingID;
109 $mailing->addSelect('name', 'campaign_id');
110 $mailing->find(TRUE);
111
112 $defaults['name'] = $mailing->name;
113 if (!$continue) {
114 $defaults['name'] = ts('Copy of %1', array(1 => $mailing->name));
115 }
116 else {
117 // CRM-7590, reuse same mailing ID if we are continuing
118 $this->set('mailing_id', $this->_mailingID);
119 }
120
121 $defaults['campaign_id'] = $mailing->campaign_id;
122 $defaults['dedupe_email'] = $mailing->dedupe_email;
123
124 $dao = new CRM_Mailing_DAO_Group();
125
126 $mailingGroups = array(
127 'civicrm_group' => array( ),
128 'civicrm_mailing' => array( )
129 );
130 $dao->mailing_id = $this->_mailingID;
131 $dao->find();
132 while ($dao->fetch()) {
133 // account for multi-lingual
134 // CRM-11431
135 $entityTable = 'civicrm_group';
136 if (substr($dao->entity_table, 0, 15) == 'civicrm_mailing') {
137 $entityTable = 'civicrm_mailing';
138 }
139 $mailingGroups[$entityTable][$dao->group_type][] = $dao->entity_id;
140 }
141
142 $defaults['includeGroups'] = $mailingGroups['civicrm_group']['Include'];
143 $defaults['excludeGroups'] = CRM_Utils_Array::value('Exclude', $mailingGroups['civicrm_group']);
144
145 if (!empty($mailingGroups['civicrm_mailing'])) {
146 $defaults['includeMailings'] = CRM_Utils_Array::value('Include', $mailingGroups['civicrm_mailing']);
147 $defaults['excludeMailings'] = CRM_Utils_Array::value('Exclude', $mailingGroups['civicrm_mailing']);
148 }
149 }
150
151 //when the context is search hide the mailing recipients.
152 $showHide = new CRM_Core_ShowHideBlocks();
153 $showGroupSelector = TRUE;
154 if ($this->_searchBasedMailing) {
155 $showGroupSelector = FALSE;
156 $formElements = array('includeGroups', 'excludeGroups', 'includeMailings', 'excludeMailings');
157 $formValues = $this->controller->exportValues($this->_name);
158 foreach ($formElements as $element) {
159 if (!empty($formValues[$element])) {
160 $showGroupSelector = TRUE;
161 break;
162 }
163 }
164 }
165
166 if ($showGroupSelector) {
167 $showHide->addShow("id-additional");
168 $showHide->addHide("id-additional-show");
169 }
170 else {
171 $showHide->addShow("id-additional-show");
172 $showHide->addHide("id-additional");
173 }
174 $showHide->addToTemplate();
175
176 return $defaults;
177 }
178
179 /**
180 * Function to actually build the form
181 *
182 * @return None
183 * @access public
184 */
185 public function buildQuickForm() {
186
187 //get the context
188 $context = $this->get('context');
189 if ($this->_searchBasedMailing) {
190 $context = 'search';
191 }
192 $this->assign('context', $context);
193
194 $this->add('text', 'name', ts('Name Your Mailing'),
195 CRM_Core_DAO::getAttribute('CRM_Mailing_DAO_Mailing', 'name'),
196 TRUE
197 );
198
199 $hiddenMailingGroup = NULL;
200 $campaignId = NULL;
201
202 //CRM-7362 --add campaigns.
203 if ($this->_mailingID) {
204 $campaignId = CRM_Core_DAO::getFieldValue('CRM_Mailing_DAO_Mailing', $this->_mailingID, 'campaign_id');
205 $hiddenMailingGroup = CRM_Mailing_BAO_Mailing::hiddenMailingGroup($this->_mailingID);
206 }
207 CRM_Campaign_BAO_Campaign::addCampaign($this, $campaignId);
208
209 //dedupe on email option
210 $this->addElement('checkbox', 'dedupe_email', ts('Remove duplicate emails?'));
211
212 //get the mailing groups.
213 $groups = CRM_Core_PseudoConstant::group('Mailing');
214 if ($hiddenMailingGroup) {
215 $groups[$hiddenMailingGroup] =
216 CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $hiddenMailingGroup, 'title');
217 }
218
219 $mailings = CRM_Mailing_PseudoConstant::completed();
220 if (!$mailings) {
221 $mailings = array();
222 }
223
224 // run the groups through a hook so users can trim it if needed
225 CRM_Utils_Hook::mailingGroups($this, $groups, $mailings);
226
227 //when the context is search add base group's.
228 if ($this->_searchBasedMailing) {
229 //get the static groups
230 $staticGroups = CRM_Core_PseudoConstant::staticGroup(FALSE, 'Mailing');
231 $this->add('select', 'baseGroup',
232 ts('Unsubscription Group'),
233 array(
234 '' => ts('- select -')) + $staticGroups,
235 TRUE
236 );
237 }
238
239 $inG = &$this->addElement('advmultiselect', 'includeGroups',
240 ts('Include Group(s)') . ' ',
241 $groups,
242 array(
243 'size' => 5,
244 'style' => 'width:240px',
245 'class' => 'advmultiselect',
246 )
247 );
248
249 //as we are having hidden smart group so no need.
250 if (!$this->_searchBasedMailing) {
251 $this->addRule('includeGroups', ts('Please select a group to be mailed.'), 'required');
252 }
253
254 $outG = &$this->addElement('advmultiselect', 'excludeGroups',
255 ts('Exclude Group(s)') . ' ',
256 $groups,
257 array(
258 'size' => 5,
259 'style' => 'width:240px',
260 'class' => 'advmultiselect',
261 )
262 );
263
264 $inG->setButtonAttributes('add', array('value' => ts('Add >>')));
265 $outG->setButtonAttributes('add', array('value' => ts('Add >>')));
266 $inG->setButtonAttributes('remove', array('value' => ts('<< Remove')));
267 $outG->setButtonAttributes('remove', array('value' => ts('<< Remove')));
268
269 $inM = &$this->addElement('advmultiselect', 'includeMailings',
270 ts('INCLUDE Recipients of These Mailing(s)') . ' ',
271 $mailings,
272 array(
273 'size' => 5,
274 'style' => 'width:240px',
275 'class' => 'advmultiselect',
276 )
277 );
278 $outM = &$this->addElement('advmultiselect', 'excludeMailings',
279 ts('EXCLUDE Recipients of These Mailing(s)') . ' ',
280 $mailings,
281 array(
282 'size' => 5,
283 'style' => 'width:240px',
284 'class' => 'advmultiselect',
285 )
286 );
287
288 $inM->setButtonAttributes('add', array('value' => ts('Add >>')));
289 $outM->setButtonAttributes('add', array('value' => ts('Add >>')));
290 $inM->setButtonAttributes('remove', array('value' => ts('<< Remove')));
291 $outM->setButtonAttributes('remove', array('value' => ts('<< Remove')));
292
293 $urls = array('' => ts('- select -'), -1 => ts('CiviCRM Search'),
294 ) + CRM_Contact_Page_CustomSearch::info();
295
296 $this->addFormRule(array('CRM_Mailing_Form_Group', 'formRule'));
297
298 $buttons = array(
299 array('type' => 'next',
300 'name' => ts('Next >>'),
301 'spacing' => '&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;',
302 'isDefault' => TRUE,
303 ),
304 array(
305 'type' => 'submit',
306 'name' => ts('Save & Continue Later'),
307 ),
308 array(
309 'type' => 'cancel',
310 'name' => ts('Cancel'),
311 ),
312 );
313
314 $this->addButtons($buttons);
315
316 $this->assign('groupCount', count($groups));
317 $this->assign('mailingCount', count($mailings));
318 }
319
320 public function postProcess() {
321 $values = $this->controller->exportValues($this->_name);
322
323 //build hidden smart group. when user want to send mailing
324 //through search contact-> more action -> send Mailing. CRM-3711
325 $groups = array();
326 if ($this->_searchBasedMailing && $this->_contactIds) {
327 $session = CRM_Core_Session::singleton();
328
329 if ($this->_resultSelectOption == 'ts_sel') {
330 // create a static grp if only a subset of result set was selected:
331
332 $randID = md5(time());
333 $grpTitle = "Hidden Group {$randID}";
334 $grpID = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $grpTitle, 'id', 'title');
335
336 if (!$grpID) {
337 $groupParams = array(
338 'title' => $grpTitle,
339 'is_active' => 1,
340 'is_hidden' => 1,
341 'group_type' => array('2' => 1),
342 );
343
344 $group = CRM_Contact_BAO_Group::create($groupParams);
345 $grpID = $group->id;
346
347 CRM_Contact_BAO_GroupContact::addContactsToGroup($this->_contactIds, $group->id);
348
349 $newGroupTitle = "Hidden Group {$grpID}";
350 $groupParams = array(
351 'id' => $grpID,
352 'name' => CRM_Utils_String::titleToVar($newGroupTitle),
353 'title' => $newGroupTitle,
354 'group_type' => array('2' => 1),
355 );
356 $group = CRM_Contact_BAO_Group::create($groupParams);
357 }
358
359 // note at this point its a static group
360 $smartGroupId = $grpID;
361 }
362 else {
363 //get the hidden smart group id.
364 $ssId = $this->get('ssID');
365 $hiddenSmartParams = array('group_type' => array('2' => 1),
366 'form_values' => $this->get('formValues'),
367 'saved_search_id' => $ssId,
368 'search_custom_id' => $this->get('customSearchID'),
369 'search_context' => $this->get('context'),
370 );
371
372 list($smartGroupId, $savedSearchId) = CRM_Contact_BAO_Group::createHiddenSmartGroup($hiddenSmartParams);
373
374 //set the saved search id.
375 if (!$ssId) {
376 if ($savedSearchId) {
377 $this->set('ssID', $savedSearchId);
378 }
379 else {
380 CRM_Core_Error::fatal();
381 }
382 }
383 }
384
385 //get the base group for this mailing, CRM-3711
386 $groups['base'] = array($values['baseGroup']);
387 $values['includeGroups'][] = $smartGroupId;
388 }
389
390 foreach (
391 array('name', 'group_id', 'search_id', 'search_args', 'campaign_id', 'dedupe_email') as $n
392 ) {
393 if (CRM_Utils_Array::value($n, $values)) {
394 $params[$n] = $values[$n];
395 }
396 }
397
398
399 $qf_Group_submit = $this->controller->exportValue($this->_name, '_qf_Group_submit');
400 $this->set('name', $params['name']);
401
402 $inGroups = $values['includeGroups'];
403 $outGroups = $values['excludeGroups'];
404 $inMailings = $values['includeMailings'];
405 $outMailings = $values['excludeMailings'];
406
407 if (is_array($inGroups)) {
408 foreach ($inGroups as $key => $id) {
409 if ($id) {
410 $groups['include'][] = $id;
411 }
412 }
413 }
414 if (is_array($outGroups)) {
415 foreach ($outGroups as $key => $id) {
416 if ($id) {
417 $groups['exclude'][] = $id;
418 }
419 }
420 }
421
422 $mailings = array();
423 if (is_array($inMailings)) {
424 foreach ($inMailings as $key => $id) {
425 if ($id) {
426 $mailings['include'][] = $id;
427 }
428 }
429 }
430 if (is_array($outMailings)) {
431 foreach ($outMailings as $key => $id) {
432 if ($id) {
433 $mailings['exclude'][] = $id;
434 }
435 }
436 }
437
438 $session = CRM_Core_Session::singleton();
439 $params['groups'] = $groups;
440 $params['mailings'] = $mailings;
441 $ids = array();
442 if ($this->get('mailing_id')) {
443
444 // don't create a new mailing if already exists
445 $ids['mailing_id'] = $this->get('mailing_id');
446
447 $groupTableName = CRM_Contact_BAO_Group::getTableName();
448 $mailingTableName = CRM_Mailing_BAO_Mailing::getTableName();
449
450 // delete previous includes/excludes, if mailing already existed
451 foreach (array('groups', 'mailings') as $entity) {
452 $mg = new CRM_Mailing_DAO_Group();
453 $mg->mailing_id = $ids['mailing_id'];
454 $mg->entity_table = ($entity == 'groups') ? $groupTableName : $mailingTableName;
455 $mg->find();
456 while ($mg->fetch()) {
457 $mg->delete();
458 }
459 }
460 }
461 else {
462 // new mailing, so lets set the created_id
463 $session = CRM_Core_Session::singleton();
464 $params['created_id'] = $session->get('userID');
465 $params['created_date'] = date('YmdHis');
466 }
467
468 $mailing = CRM_Mailing_BAO_Mailing::create($params, $ids);
469 $this->set('mailing_id', $mailing->id);
470
471 $dedupeEmail = FALSE;
472 if (isset($params['dedupe_email'])) {
473 $dedupeEmail = $params['dedupe_email'];
474 }
475
476 // also compute the recipients and store them in the mailing recipients table
477 CRM_Mailing_BAO_Mailing::getRecipients(
478 $mailing->id,
479 $mailing->id,
480 NULL,
481 NULL,
482 TRUE,
483 $dedupeEmail
484 );
485
486 $count = CRM_Mailing_BAO_Recipients::mailingSize($mailing->id);
487 $this->set('count', $count);
488 $this->assign('count', $count);
489 $this->set('groups', $groups);
490 $this->set('mailings', $mailings);
491
492 if ($qf_Group_submit) {
493 //when user perform mailing from search context
494 //redirect it to search result CRM-3711.
495 $ssID = $this->get('ssID');
496 $context = $this->get('context');
497 if ($ssID && $this->_searchBasedMailing) {
498 if ($this->_action == CRM_Core_Action::BASIC) {
499 $fragment = 'search';
500 }
501 elseif ($this->_action == CRM_Core_Action::PROFILE) {
502 $fragment = 'search/builder';
503 }
504 elseif ($this->_action == CRM_Core_Action::ADVANCED) {
505 $fragment = 'search/advanced';
506 }
507 else {
508 $fragment = 'search/custom';
509 }
510
511 $context = $this->get('context');
512 if (!CRM_Contact_Form_Search::isSearchContext($context)) {
513 $context = 'search';
514 }
515 $urlParams = "force=1&reset=1&ssID={$ssID}&context={$context}";
516
517 $qfKey = CRM_Utils_Request::retrieve('qfKey', 'String', $this);
518 if (CRM_Utils_Rule::qfKey($qfKey)) {
519 $urlParams .= "&qfKey=$qfKey";
520 }
521
522 $draftURL = CRM_Utils_System::url('civicrm/mailing/browse/unscheduled', 'scheduled=false&reset=1');
523 $status = ts("You can continue later by clicking the 'Continue' action to resume working on it.<br />From <a href='%1'>Draft and Unscheduled Mailings</a>.", array(1 => $draftURL));
524
525 // Redirect user to search.
526 $url = CRM_Utils_System::url('civicrm/contact/' . $fragment, $urlParams);
527 }
528 else {
529 $status = ts("Click the 'Continue' action to resume working on it.");
530 $url = CRM_Utils_System::url('civicrm/mailing/browse/unscheduled', 'scheduled=false&reset=1');
531 }
532 CRM_Core_Session::setStatus($status, ts('Mailing Saved'), 'success');
533 return $this->controller->setDestination($url);
534 }
535 }
536
537 /**
538 * Display Name of the form
539 *
540 * @access public
541 *
542 * @return string
543 */
544 public function getTitle() {
545 return ts('Select Recipients');
546 }
547
548 /**
549 * global validation rules for the form
550 *
551 * @param array $fields posted values of the form
552 *
553 * @return array list of errors to be posted back to the form
554 * @static
555 * @access public
556 */
557 static function formRule($fields) {
558 $errors = array();
559 if (isset($fields['includeGroups']) &&
560 is_array($fields['includeGroups']) &&
561 isset($fields['excludeGroups']) &&
562 is_array($fields['excludeGroups'])
563 ) {
564 $checkGroups = array();
565 $checkGroups = array_intersect($fields['includeGroups'], $fields['excludeGroups']);
566 if (!empty($checkGroups)) {
567 $errors['excludeGroups'] = ts('Cannot have same groups in Include Group(s) and Exclude Group(s).');
568 }
569 }
570
571 if (isset($fields['includeMailings']) &&
572 is_array($fields['includeMailings']) &&
573 isset($fields['excludeMailings']) &&
574 is_array($fields['excludeMailings'])
575 ) {
576 $checkMailings = array();
577 $checkMailings = array_intersect($fields['includeMailings'], $fields['excludeMailings']);
578 if (!empty($checkMailings)) {
579 $errors['excludeMailings'] = ts('Cannot have same mail in Include mailing(s) and Exclude mailing(s).');
580 }
581 }
582
583 if (!empty($fields['search_id']) &&
584 empty($fields['group_id'])
585 ) {
586 $errors['group_id'] = ts('You must select a group to filter on');
587 }
588
589 if (empty($fields['search_id']) &&
590 !empty($fields['group_id'])
591 ) {
592 $errors['search_id'] = ts('You must select a search to filter');
593 }
594
595 return empty($errors) ? TRUE : $errors;
596 }
597}
598