Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CRM-21260: CiviMail compose UI very slow to initialize, CRM-21316: Refactor getRecipients fn #11142

Merged
merged 3 commits into from
Jan 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
693 changes: 256 additions & 437 deletions CRM/Mailing/BAO/Mailing.php

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CRM/Mailing/BAO/MailingAB.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public static function del($id) {
* @param CRM_Mailing_DAO_MailingAB $dao
*/
public static function distributeRecipients(CRM_Mailing_DAO_MailingAB $dao) {
CRM_Mailing_BAO_Mailing::getRecipients($dao->mailing_id_a, $dao->mailing_id_a, TRUE);
CRM_Mailing_BAO_Mailing::getRecipients($dao->mailing_id_a);

//calculate total number of random recipients for mail C from group_percentage selected
$totalCount = CRM_Mailing_BAO_Recipients::mailingSize($dao->mailing_id_a);
Expand Down
6 changes: 2 additions & 4 deletions CRM/Mailing/BAO/MailingJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,8 @@ static public function create($params) {
$job->scheduled_date = $params['scheduled_date'];
$job->is_test = $params['is_test'];
$job->save();
$mailing = new CRM_Mailing_BAO_Mailing();
$mailing->id = $params['mailing_id'];
if ($mailing->id && $mailing->find(TRUE)) {
$mailing->getRecipients($job->id, $params['mailing_id'], TRUE, $mailing->dedupe_email);
if ($params['mailing_id']) {
CRM_Mailing_BAO_Mailing::getRecipients($params['mailing_id']);
return $job;
}
else {
Expand Down
7 changes: 1 addition & 6 deletions CRM/SMS/Form/Group.php
Original file line number Diff line number Diff line change
Expand Up @@ -266,12 +266,7 @@ public function postProcess() {
$this->set('mailing_id', $mailing->id);

// also compute the recipients and store them in the mailing recipients table
CRM_Mailing_BAO_Mailing::getRecipients($mailing->id,
$mailing->id,
TRUE,
FALSE,
'sms'
);
CRM_Mailing_BAO_Mailing::getRecipients($mailing->id);

$count = CRM_Mailing_BAO_Recipients::mailingSize($mailing->id);
$this->set('count', $count);
Expand Down
32 changes: 31 additions & 1 deletion CRM/Utils/SQL/Select.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ class CRM_Utils_SQL_Select implements ArrayAccess {

private $mode = NULL;
private $insertInto = NULL;
private $insertVerb = 'INSERT INTO ';
private $insertIntoFields = array();
private $selects = array();
private $from;
Expand Down Expand Up @@ -403,6 +404,34 @@ public function insertInto($table, $fields = array()) {
return $this;
}

/**
* Wrapper function of insertInto fn but sets insertVerb = "INSERT IGNORE INTO "
*
* @param string $table
* The name of the other table (which receives new data).
* @param array $fields
* The fields to fill in the other table (in order).
* @return CRM_Utils_SQL_Select
*/
public function insertIgnoreInto($table, $fields = array()) {
$this->insertVerb = "INSERT IGNORE INTO ";
return $this->insertInto($table, $fields);
}

/**
* Wrapper function of insertInto fn but sets insertVerb = "REPLACE INTO "
*
* @param string $table
* The name of the other table (which receives new data).
* @param array $fields
* The fields to fill in the other table (in order).
*/
public function replaceInto($table, $fields = array()) {
$this->insertVerb = "REPLACE INTO ";
return $this->insertInto($table, $fields);
}


/**
* @param array $fields
* The fields to fill in the other table (in order).
Expand Down Expand Up @@ -550,10 +579,11 @@ public function escapeString($value) {
public function toSQL() {
$sql = '';
if ($this->insertInto) {
$sql .= 'INSERT INTO ' . $this->insertInto . ' (';
$sql .= $this->insertVerb . $this->insertInto . ' (';
$sql .= implode(', ', $this->insertIntoFields);
$sql .= ")\n";
}

if ($this->selects) {
$sql .= 'SELECT ' . $this->distinct . implode(', ', $this->selects) . "\n";
}
Expand Down
3 changes: 3 additions & 0 deletions ang/crmMailing/Recipients.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@
mids.push(dv.entity_id);
}
}
if (gids.length === 0) {
return;
}

CRM.api3('Group', 'getlist', { params: { id: { IN: gids }, options: { limit: 0 } }, extra: ["is_hidden"] } ).then(
function(glist) {
Expand Down
19 changes: 8 additions & 11 deletions ang/crmMailing/services.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,12 +270,13 @@
else {
// Protect against races in saving and previewing by chaining create+preview.
var params = angular.extend({}, mailing, mailing.recipients, {
options: {force_rollback: 1},
id: mailing.id,
'api.Mailing.preview': {
id: '$value.id'
}
});
delete params.recipients; // the content was merged in
params._skip_evil_bao_auto_recipients_ = 1; // skip recipient rebuild on mail preview
return qApi('Mailing', 'create', params).then(function(result) {
mailing.modified_date = result.values[result.id].modified_date;
// changes rolled back, so we don't care about updating mailing
Expand All @@ -290,11 +291,8 @@
previewRecipients: function previewRecipients(mailing, previewLimit) {
// To get list of recipients, we tentatively save the mailing and
// get the resulting recipients -- then rollback any changes.
var params = angular.extend({}, mailing, mailing.recipients, {
name: 'placeholder', // for previewing recipients on new, incomplete mailing
subject: 'placeholder', // for previewing recipients on new, incomplete mailing
options: {force_rollback: 1},
'api.mailing_job.create': 1, // note: exact match to API default
var params = angular.extend({}, mailing.recipients, {
id: mailing.id,
'api.MailingRecipients.get': {
mailing_id: '$value.id',
options: {limit: previewLimit},
Expand All @@ -317,10 +315,7 @@
// To get list of recipients, we tentatively save the mailing and
// get the resulting recipients -- then rollback any changes.
var params = angular.extend({}, mailing, mailing.recipients, {
name: 'placeholder', // for previewing recipients on new, incomplete mailing
subject: 'placeholder', // for previewing recipients on new, incomplete mailing
options: {force_rollback: 1},
'api.mailing_job.create': 1, // note: exact match to API default
id: mailing.id,
'api.MailingRecipients.getcount': {
mailing_id: '$value.id'
}
Expand Down Expand Up @@ -373,7 +368,7 @@
delete params.jobs;

delete params.recipients; // the content was merged in

params._skip_evil_bao_auto_recipients_ = 1; // skip recipient rebuild on simple save
return qApi('Mailing', 'create', params).then(function(result) {
if (result.id && !mailing.id) {
mailing.id = result.id;
Expand Down Expand Up @@ -427,6 +422,8 @@

delete params.recipients; // the content was merged in

params._skip_evil_bao_auto_recipients_ = 1; // skip recipient rebuild while sending test mail

return qApi('Mailing', 'create', params).then(function (result) {
if (result.id && !mailing.id) {
mailing.id = result.id;
Expand Down
15 changes: 10 additions & 5 deletions tests/phpunit/CiviTest/CiviUnitTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -1018,12 +1018,13 @@ public function organizationCreate($params = array(), $seq = 0) {
* parameters for civicrm_contact_add api function call
* @param int $seq
* sequence number if creating multiple individuals
* @param bool $random
*
* @return int
* id of Individual created
*/
public function individualCreate($params = array(), $seq = 0) {
$params = array_merge($this->sampleContact('Individual', $seq), $params);
public function individualCreate($params = array(), $seq = 0, $random = FALSE) {
$params = array_merge($this->sampleContact('Individual', $seq, $random), $params);
return $this->_contactCreate($params);
}

Expand Down Expand Up @@ -1054,7 +1055,7 @@ public function householdCreate($params = array(), $seq = 0) {
* @return array
* properties of sample contact (ie. $params for API call)
*/
public function sampleContact($contact_type, $seq = 0) {
public function sampleContact($contact_type, $seq = 0, $random = FALSE) {
$samples = array(
'Individual' => array(
// The number of values in each list need to be coprime numbers to not have duplicates
Expand All @@ -1078,6 +1079,9 @@ public function sampleContact($contact_type, $seq = 0) {
$params = array('contact_type' => $contact_type);
foreach ($samples[$contact_type] as $key => $values) {
$params[$key] = $values[$seq % count($values)];
if ($random) {
$params[$key] .= substr(sha1(rand()), 0, 5);
}
}
if ($contact_type == 'Individual') {
$params['email'] = strtolower(
Expand Down Expand Up @@ -1870,13 +1874,14 @@ public function smartGroupCreate($smartGroupParams = array(), $groupParams = arr
*
* @param int $groupID
* @param int $totalCount
* @param bool $random
* @return int
* groupId of created group
*/
public function groupContactCreate($groupID, $totalCount = 10) {
public function groupContactCreate($groupID, $totalCount = 10, $random = FALSE) {
$params = array('group_id' => $groupID);
for ($i = 1; $i <= $totalCount; $i++) {
$contactID = $this->individualCreate();
$contactID = $this->individualCreate(array(), 0, $random);
if ($i == 1) {
$params += array('contact_id' => $contactID);
}
Expand Down
3 changes: 1 addition & 2 deletions tests/phpunit/api/v3/MailingABTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,7 @@ public function groupPctProvider() {
* @dataProvider groupPctProvider
*/
public function testDistribution($totalGroupContacts, $groupPct, $expectedCountA, $expectedCountB, $expectedCountC) {

$result = $this->groupContactCreate($this->_groupID, $totalGroupContacts);
$result = $this->groupContactCreate($this->_groupID, $totalGroupContacts, TRUE);
$this->assertEquals($totalGroupContacts, $result['added'], "in line " . __LINE__);

$params = $this->_params;
Expand Down
4 changes: 0 additions & 4 deletions tests/phpunit/api/v3/MailingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,6 @@ public function testMailerPreviewRecipients() {
$params['mailings']['include'] = array();
$params['mailings']['exclude'] = array();
$params['options']['force_rollback'] = 1;
$params['api.mailing_job.create'] = 1;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per the fix, there is no need to create Job in order to fetch recipient data.

$params['api.MailingRecipients.get'] = array(
'mailing_id' => '$value.id',
'api.contact.getvalue' => array(
Expand All @@ -302,12 +301,10 @@ public function testMailerPreviewRecipients() {

$maxIDs = array(
'mailing' => CRM_Core_DAO::singleValueQuery('SELECT MAX(id) FROM civicrm_mailing'),
'job' => CRM_Core_DAO::singleValueQuery('SELECT MAX(id) FROM civicrm_mailing_job'),
'group' => CRM_Core_DAO::singleValueQuery('SELECT MAX(id) FROM civicrm_mailing_group'),
);
$create = $this->callAPIAndDocument('Mailing', 'create', $params, __FUNCTION__, __FILE__);
$this->assertDBQuery($maxIDs['mailing'], 'SELECT MAX(id) FROM civicrm_mailing'); // 'Preview should not create any mailing records'
$this->assertDBQuery($maxIDs['job'], 'SELECT MAX(id) FROM civicrm_mailing_job'); // 'Preview should not create any mailing_job record'
$this->assertDBQuery($maxIDs['group'], 'SELECT MAX(id) FROM civicrm_mailing_group'); // 'Preview should not create any mailing_group records'

$preview = $create['values'][$create['id']]['api.MailingRecipients.get'];
Expand Down Expand Up @@ -346,7 +343,6 @@ public function testMailerPreviewRecipientsDeduplicate() {
$params['mailings']['include'] = array();
$params['options']['force_rollback'] = 1;
$params['dedupe_email'] = 1;
$params['api.mailing_job.create'] = 1;
$params['api.MailingRecipients.get'] = array(
'mailing_id' => '$value.id',
'api.contact.getvalue' => array(
Expand Down