3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.4 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
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. |
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. |
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 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2013
37 * Choose include / exclude groups and mailings
40 class CRM_Mailing_Form_Group
extends CRM_Contact_Form_Task
{
43 * the mailing ID of the mailing if we are resuming a mailing
47 protected $_mailingID;
50 * Function to set variables up before form is built
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/advanced-configuration/email-system-configuration/")));
60 $this->_mailingID
= CRM_Utils_Request
::retrieve('mid', 'Integer', $this, FALSE, NULL);
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) {
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);
79 $session->pushUserContext(CRM_Utils_System
::url($path, "qfKey=$qfKey"));
82 $session->pushUserContext(CRM_Utils_System
::url('civicrm/mailing', 'reset=1'));
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'));
92 * This function sets the default values for the form.
93 * the default values are retrieved from the database
99 function setDefaultValues() {
100 $continue = CRM_Utils_Request
::retrieve('continue', 'String', $this, FALSE, NULL);
103 if ($this->_mailingID
) {
104 // check that the user has permission to access mailing id
105 CRM_Mailing_BAO_Mailing
::checkPermission($this->_mailingID
);
107 $mailing = new CRM_Mailing_DAO_Mailing();
108 $mailing->id
= $this->_mailingID
;
109 $mailing->addSelect('name', 'campaign_id');
110 $mailing->find(TRUE);
112 $defaults['name'] = $mailing->name
;
114 $defaults['name'] = ts('Copy of %1', array(1 => $mailing->name
));
117 // CRM-7590, reuse same mailing ID if we are continuing
118 $this->set('mailing_id', $this->_mailingID
);
121 $defaults['campaign_id'] = $mailing->campaign_id
;
122 $defaults['dedupe_email'] = $mailing->dedupe_email
;
124 $dao = new CRM_Mailing_DAO_MailingGroup();
126 $mailingGroups = array(
127 'civicrm_group' => array( ),
128 'civicrm_mailing' => array( )
130 $dao->mailing_id
= $this->_mailingID
;
132 while ($dao->fetch()) {
133 // account for multi-lingual
135 $entityTable = 'civicrm_group';
136 if (substr($dao->entity_table
, 0, 15) == 'civicrm_mailing') {
137 $entityTable = 'civicrm_mailing';
139 $mailingGroups[$entityTable][$dao->group_type
][] = $dao->entity_id
;
142 $defaults['includeGroups'] = $mailingGroups['civicrm_group']['Include'];
143 $defaults['excludeGroups'] = CRM_Utils_Array
::value('Exclude', $mailingGroups['civicrm_group']);
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']);
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;
166 if ($showGroupSelector) {
167 $showHide->addShow("id-additional");
168 $showHide->addHide("id-additional-show");
171 $showHide->addShow("id-additional-show");
172 $showHide->addHide("id-additional");
174 $showHide->addToTemplate();
180 * Function to actually build the form
185 public function buildQuickForm() {
188 $context = $this->get('context');
189 if ($this->_searchBasedMailing
) {
192 $this->assign('context', $context);
194 $this->add('text', 'name', ts('Name Your Mailing'),
195 CRM_Core_DAO
::getAttribute('CRM_Mailing_DAO_Mailing', 'name'),
199 $hiddenMailingGroup = NULL;
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
);
207 CRM_Campaign_BAO_Campaign
::addCampaign($this, $campaignId);
209 //dedupe on email option
210 $this->addElement('checkbox', 'dedupe_email', ts('Remove duplicate emails?'));
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');
219 $mailings = CRM_Mailing_PseudoConstant
::completed();
224 // run the groups through a hook so users can trim it if needed
225 CRM_Utils_Hook
::mailingGroups($this, $groups, $mailings);
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'),
234 '' => ts('- select -')) +
$staticGroups,
239 if (count($groups) <= 10) {
240 // setting minimum height to 2 since widget looks strange when size (height) is 1
241 $groupSize = max(count($groups), 2);
246 $inG = &$this->addElement('advmultiselect', 'includeGroups',
247 ts('Include Group(s)') . ' ',
250 'size' => $groupSize,
251 'style' => 'width:auto; min-width:240px;',
252 'class' => 'advmultiselect',
256 //as we are having hidden smart group so no need.
257 if (!$this->_searchBasedMailing
) {
258 $this->addRule('includeGroups', ts('Please select a group to be mailed.'), 'required');
261 $outG = &$this->addElement('advmultiselect', 'excludeGroups',
262 ts('Exclude Group(s)') . ' ',
265 'size' => $groupSize,
266 'style' => 'width:auto; min-width:240px;',
267 'class' => 'advmultiselect',
271 $inG->setButtonAttributes('add', array('value' => ts('Add >>')));
272 $outG->setButtonAttributes('add', array('value' => ts('Add >>')));
273 $inG->setButtonAttributes('remove', array('value' => ts('<< Remove')));
274 $outG->setButtonAttributes('remove', array('value' => ts('<< Remove')));
276 if (count($mailings) <= 10) {
277 // setting minimum height to 2 since widget looks strange when size (height) is 1
278 $mailingSize = max(count($mailings), 2);
283 $inM = &$this->addElement('advmultiselect', 'includeMailings',
284 ts('INCLUDE Recipients of These Mailing(s)') . ' ',
287 'size' => $mailingSize,
288 'style' => 'width:auto; min-width:240px;',
289 'class' => 'advmultiselect',
292 $outM = &$this->addElement('advmultiselect', 'excludeMailings',
293 ts('EXCLUDE Recipients of These Mailing(s)') . ' ',
296 'size' => $mailingSize,
297 'style' => 'width:auto; min-width:240px;',
298 'class' => 'advmultiselect',
302 $inM->setButtonAttributes('add', array('value' => ts('Add >>')));
303 $outM->setButtonAttributes('add', array('value' => ts('Add >>')));
304 $inM->setButtonAttributes('remove', array('value' => ts('<< Remove')));
305 $outM->setButtonAttributes('remove', array('value' => ts('<< Remove')));
307 $urls = array('' => ts('- select -'), -1 => ts('CiviCRM Search'),
308 ) + CRM_Contact_Page_CustomSearch
::info();
310 $this->addFormRule(array('CRM_Mailing_Form_Group', 'formRule'));
313 array('type' => 'next',
314 'name' => ts('Next >>'),
315 'spacing' => ' ',
320 'name' => ts('Save & Continue Later'),
324 'name' => ts('Cancel'),
328 $this->addButtons($buttons);
330 $this->assign('groupCount', count($groups));
331 $this->assign('mailingCount', count($mailings));
332 if(count($groups) == 0 && count($mailings) == 0 && !$this->_searchBasedMailing
) {
333 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");
337 public function postProcess() {
338 $values = $this->controller
->exportValues($this->_name
);
340 //build hidden smart group. when user want to send mailing
341 //through search contact-> more action -> send Mailing. CRM-3711
343 if ($this->_searchBasedMailing
&& $this->_contactIds
) {
344 $session = CRM_Core_Session
::singleton();
346 if ($this->_resultSelectOption
== 'ts_sel') {
347 // create a static grp if only a subset of result set was selected:
349 $randID = md5(time());
350 $grpTitle = "Hidden Group {$randID}";
351 $grpID = CRM_Core_DAO
::getFieldValue('CRM_Contact_DAO_Group', $grpTitle, 'id', 'title');
354 $groupParams = array(
355 'title' => $grpTitle,
358 'group_type' => array('2' => 1),
361 $group = CRM_Contact_BAO_Group
::create($groupParams);
364 CRM_Contact_BAO_GroupContact
::addContactsToGroup($this->_contactIds
, $group->id
);
366 $newGroupTitle = "Hidden Group {$grpID}";
367 $groupParams = array(
369 'name' => CRM_Utils_String
::titleToVar($newGroupTitle),
370 'title' => $newGroupTitle,
371 'group_type' => array('2' => 1),
373 $group = CRM_Contact_BAO_Group
::create($groupParams);
376 // note at this point its a static group
377 $smartGroupId = $grpID;
380 //get the hidden smart group id.
381 $ssId = $this->get('ssID');
382 $hiddenSmartParams = array('group_type' => array('2' => 1),
383 'form_values' => $this->get('formValues'),
384 'saved_search_id' => $ssId,
385 'search_custom_id' => $this->get('customSearchID'),
386 'search_context' => $this->get('context'),
389 list($smartGroupId, $savedSearchId) = CRM_Contact_BAO_Group
::createHiddenSmartGroup($hiddenSmartParams);
391 //set the saved search id.
393 if ($savedSearchId) {
394 $this->set('ssID', $savedSearchId);
397 CRM_Core_Error
::fatal();
402 //get the base group for this mailing, CRM-3711
403 $groups['base'] = array($values['baseGroup']);
404 $values['includeGroups'][] = $smartGroupId;
408 array('name', 'group_id', 'search_id', 'search_args', 'campaign_id', 'dedupe_email') as $n
410 if (!empty($values[$n])) {
411 $params[$n] = $values[$n];
416 $qf_Group_submit = $this->controller
->exportValue($this->_name
, '_qf_Group_submit');
417 $this->set('name', $params['name']);
419 $inGroups = $values['includeGroups'];
420 $outGroups = $values['excludeGroups'];
421 $inMailings = $values['includeMailings'];
422 $outMailings = $values['excludeMailings'];
424 if (is_array($inGroups)) {
425 foreach ($inGroups as $key => $id) {
427 $groups['include'][] = $id;
431 if (is_array($outGroups)) {
432 foreach ($outGroups as $key => $id) {
434 $groups['exclude'][] = $id;
440 if (is_array($inMailings)) {
441 foreach ($inMailings as $key => $id) {
443 $mailings['include'][] = $id;
447 if (is_array($outMailings)) {
448 foreach ($outMailings as $key => $id) {
450 $mailings['exclude'][] = $id;
455 $session = CRM_Core_Session
::singleton();
456 $params['groups'] = $groups;
457 $params['mailings'] = $mailings;
459 if ($this->get('mailing_id')) {
461 // don't create a new mailing if already exists
462 $ids['mailing_id'] = $this->get('mailing_id');
464 $groupTableName = CRM_Contact_BAO_Group
::getTableName();
465 $mailingTableName = CRM_Mailing_BAO_Mailing
::getTableName();
467 // delete previous includes/excludes, if mailing already existed
468 foreach (array('groups', 'mailings') as $entity) {
469 $mg = new CRM_Mailing_DAO_MailingGroup();
470 $mg->mailing_id
= $ids['mailing_id'];
471 $mg->entity_table
= ($entity == 'groups') ?
$groupTableName : $mailingTableName;
473 while ($mg->fetch()) {
479 // new mailing, so lets set the created_id
480 $session = CRM_Core_Session
::singleton();
481 $params['created_id'] = $session->get('userID');
482 $params['created_date'] = date('YmdHis');
485 $mailing = CRM_Mailing_BAO_Mailing
::create($params, $ids);
486 $this->set('mailing_id', $mailing->id
);
488 $dedupeEmail = FALSE;
489 if (isset($params['dedupe_email'])) {
490 $dedupeEmail = $params['dedupe_email'];
493 // mailing id should be added to the form object
494 $this->_mailingID
= $mailing->id
;
496 // also compute the recipients and store them in the mailing recipients table
497 CRM_Mailing_BAO_Mailing
::getRecipients(
506 $count = CRM_Mailing_BAO_Recipients
::mailingSize($mailing->id
);
507 $this->set('count', $count);
508 $this->assign('count', $count);
509 $this->set('groups', $groups);
510 $this->set('mailings', $mailings);
512 if ($qf_Group_submit) {
513 //when user perform mailing from search context
514 //redirect it to search result CRM-3711.
515 $ssID = $this->get('ssID');
516 $context = $this->get('context');
517 if ($ssID && $this->_searchBasedMailing
) {
518 if ($this->_action
== CRM_Core_Action
::BASIC
) {
519 $fragment = 'search';
521 elseif ($this->_action
== CRM_Core_Action
::PROFILE
) {
522 $fragment = 'search/builder';
524 elseif ($this->_action
== CRM_Core_Action
::ADVANCED
) {
525 $fragment = 'search/advanced';
528 $fragment = 'search/custom';
531 $context = $this->get('context');
532 if (!CRM_Contact_Form_Search
::isSearchContext($context)) {
535 $urlParams = "force=1&reset=1&ssID={$ssID}&context={$context}";
537 $qfKey = CRM_Utils_Request
::retrieve('qfKey', 'String', $this);
538 if (CRM_Utils_Rule
::qfKey($qfKey)) {
539 $urlParams .= "&qfKey=$qfKey";
542 $draftURL = CRM_Utils_System
::url('civicrm/mailing/browse/unscheduled', 'scheduled=false&reset=1');
543 $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));
545 // Redirect user to search.
546 $url = CRM_Utils_System
::url('civicrm/contact/' . $fragment, $urlParams);
549 $status = ts("Click the 'Continue' action to resume working on it.");
550 $url = CRM_Utils_System
::url('civicrm/mailing/browse/unscheduled', 'scheduled=false&reset=1');
552 CRM_Core_Session
::setStatus($status, ts('Mailing Saved'), 'success');
553 return $this->controller
->setDestination($url);
558 * Display Name of the form
564 public function getTitle() {
565 return ts('Select Recipients');
569 * global validation rules for the form
571 * @param array $fields posted values of the form
573 * @return array list of errors to be posted back to the form
577 static function formRule($fields) {
579 if (isset($fields['includeGroups']) &&
580 is_array($fields['includeGroups']) &&
581 isset($fields['excludeGroups']) &&
582 is_array($fields['excludeGroups'])
584 $checkGroups = array();
585 $checkGroups = array_intersect($fields['includeGroups'], $fields['excludeGroups']);
586 if (!empty($checkGroups)) {
587 $errors['excludeGroups'] = ts('Cannot have same groups in Include Group(s) and Exclude Group(s).');
591 if (isset($fields['includeMailings']) &&
592 is_array($fields['includeMailings']) &&
593 isset($fields['excludeMailings']) &&
594 is_array($fields['excludeMailings'])
596 $checkMailings = array();
597 $checkMailings = array_intersect($fields['includeMailings'], $fields['excludeMailings']);
598 if (!empty($checkMailings)) {
599 $errors['excludeMailings'] = ts('Cannot have same mail in Include mailing(s) and Exclude mailing(s).');
603 if (!empty($fields['search_id']) &&
604 empty($fields['group_id'])
606 $errors['group_id'] = ts('You must select a group to filter on');
609 if (empty($fields['search_id']) &&
610 !empty($fields['group_id'])
612 $errors['search_id'] = ts('You must select a search to filter');
615 return empty($errors) ?
TRUE : $errors;