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