Fix bug inn primary handling where TRUE rather than 1 used
[civicrm-core.git] / CRM / Core / BAO / Email.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
bc77d7c0 4 | Copyright CiviCRM LLC. All rights reserved. |
6a488035 5 | |
bc77d7c0
TO
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
6a488035 9 +--------------------------------------------------------------------+
d25dd0ee 10 */
6a488035
TO
11
12/**
13 *
14 * @package CRM
ca5cec67 15 * @copyright CiviCRM LLC https://civicrm.org/licensing
6a488035
TO
16 */
17
18/**
192d36c5 19 * This class contains functions for email handling.
6a488035
TO
20 */
21class CRM_Core_BAO_Email extends CRM_Core_DAO_Email {
22
cac01cdc 23 /**
192d36c5 24 * Create email address.
25 *
26 * Note that the create function calls 'add' but has more business logic.
6a488035 27 *
6a0b768e
TO
28 * @param array $params
29 * Input parameters.
77b97be7
EM
30 *
31 * @return object
6a488035 32 */
00be9182 33 public static function create($params) {
3bec4854 34 CRM_Core_BAO_Block::handlePrimary($params, get_class());
4b6bf55f 35
6a488035
TO
36 $hook = empty($params['id']) ? 'create' : 'edit';
37 CRM_Utils_Hook::pre($hook, 'Email', CRM_Utils_Array::value('id', $params), $params);
38
39 $email = new CRM_Core_DAO_Email();
40 $email->copyValues($params);
7629d5a6 41 if (!empty($email->email)) {
42 // lower case email field to optimize queries
43 $strtolower = function_exists('mb_strtolower') ? 'mb_strtolower' : 'strtolower';
44 $email->email = $strtolower($email->email);
45 }
6a488035 46
c2714028 47 /*
e70a7fc0 48 * since we're setting bulkmail for 1 of this contact's emails, first reset all their other emails to is_bulkmail false
2ffdaed1 49 * We shouldn't set the current email to false even though we
50 * are about to reset it to avoid contaminating the changelog if logging is enabled.
e70a7fc0
TO
51 * (only 1 email address can have is_bulkmail = true)
52 */
2ffdaed1 53 if ($email->is_bulkmail && !empty($params['contact_id']) && !self::isMultipleBulkMail()) {
6a488035
TO
54 $sql = "
55UPDATE civicrm_email
56SET is_bulkmail = 0
57WHERE contact_id = {$params['contact_id']}
58";
2ffdaed1 59 if ($hook === 'edit') {
2aa397bc
TO
60 $sql .= " AND id <> {$params['id']}";
61 }
6a488035
TO
62 CRM_Core_DAO::executeQuery($sql);
63 }
64
65 // handle if email is on hold
66 self::holdEmail($email);
67
68 $email->save();
69
cac01cdc 70 if ($email->is_primary) {
71 // update the UF user email if that has changed
72 CRM_Core_BAO_UFMatch::updateUFName($email->contact_id);
73 }
74
6a488035
TO
75 CRM_Utils_Hook::post($hook, 'Email', $email->id, $email);
76 return $email;
77 }
78
ec47f7b4 79 /**
80 * Takes an associative array and adds email.
81 *
82 * @param array $params
83 * (reference ) an assoc array of name/value pairs.
84 *
85 * @return object
86 * CRM_Core_BAO_Email object on success, null otherwise
87 */
88 public static function add(&$params) {
89 CRM_Core_Error::deprecatedFunctionWarning('apiv4 create');
90 return self::create($params);
91 }
92
6a488035
TO
93 /**
94 * Given the list of params in the params array, fetch the object
95 * and store the values in the values array
96 *
6a0b768e
TO
97 * @param array $entityBlock
98 * Input parameters to find object.
6a488035 99 *
cef76e5f 100 * @return array
6a488035 101 */
cef76e5f 102 public static function getValues($entityBlock) {
6a488035
TO
103 return CRM_Core_BAO_Block::getValues('email', $entityBlock);
104 }
105
106 /**
107 * Get all the emails for a specified contact_id, with the primary email being first
108 *
6a0b768e
TO
109 * @param int $id
110 * The contact id.
6a488035 111 *
dd244018
EM
112 * @param bool $updateBlankLocInfo
113 *
a6c01b45
CW
114 * @return array
115 * the array of email id's
6a488035 116 */
00be9182 117 public static function allEmails($id, $updateBlankLocInfo = FALSE) {
6a488035
TO
118 if (!$id) {
119 return NULL;
120 }
121
122 $query = "
123SELECT email,
124 civicrm_location_type.name as locationType,
125 civicrm_email.is_primary as is_primary,
126 civicrm_email.on_hold as on_hold,
127 civicrm_email.id as email_id,
128 civicrm_email.location_type_id as locationTypeId
129FROM civicrm_contact
130LEFT JOIN civicrm_email ON ( civicrm_email.contact_id = civicrm_contact.id )
131LEFT JOIN civicrm_location_type ON ( civicrm_email.location_type_id = civicrm_location_type.id )
132WHERE civicrm_contact.id = %1
133ORDER BY civicrm_email.is_primary DESC, email_id ASC ";
be2fb01f
CW
134 $params = [
135 1 => [
6a488035
TO
136 $id,
137 'Integer',
be2fb01f
CW
138 ],
139 ];
6a488035 140
be2fb01f 141 $emails = $values = [];
353ffa53
TO
142 $dao = CRM_Core_DAO::executeQuery($query, $params);
143 $count = 1;
6a488035 144 while ($dao->fetch()) {
be2fb01f 145 $values = [
6a488035
TO
146 'locationType' => $dao->locationType,
147 'is_primary' => $dao->is_primary,
148 'on_hold' => $dao->on_hold,
149 'id' => $dao->email_id,
150 'email' => $dao->email,
151 'locationTypeId' => $dao->locationTypeId,
be2fb01f 152 ];
6a488035
TO
153
154 if ($updateBlankLocInfo) {
155 $emails[$count++] = $values;
156 }
157 else {
158 $emails[$dao->email_id] = $values;
159 }
160 }
161 return $emails;
162 }
163
164 /**
165 * Get all the emails for a specified location_block id, with the primary email being first
166 *
6a0b768e
TO
167 * @param array $entityElements
168 * The array containing entity_id and.
16b10e64 169 * entity_table name
6a488035 170 *
a6c01b45
CW
171 * @return array
172 * the array of email id's
6a488035 173 */
00be9182 174 public static function allEntityEmails(&$entityElements) {
6a488035
TO
175 if (empty($entityElements)) {
176 return NULL;
177 }
178
179 $entityId = $entityElements['entity_id'];
180 $entityTable = $entityElements['entity_table'];
181
6a488035
TO
182 $sql = " SELECT email, ltype.name as locationType, e.is_primary as is_primary, e.on_hold as on_hold,e.id as email_id, e.location_type_id as locationTypeId
183FROM civicrm_loc_block loc, civicrm_email e, civicrm_location_type ltype, {$entityTable} ev
184WHERE ev.id = %1
185AND loc.id = ev.loc_block_id
186AND e.id IN (loc.email_id, loc.email_2_id)
187AND ltype.id = e.location_type_id
188ORDER BY e.is_primary DESC, email_id ASC ";
189
be2fb01f
CW
190 $params = [
191 1 => [
6a488035
TO
192 $entityId,
193 'Integer',
be2fb01f
CW
194 ],
195 ];
6a488035 196
be2fb01f 197 $emails = [];
6a488035
TO
198 $dao = CRM_Core_DAO::executeQuery($sql, $params);
199 while ($dao->fetch()) {
be2fb01f 200 $emails[$dao->email_id] = [
6a488035
TO
201 'locationType' => $dao->locationType,
202 'is_primary' => $dao->is_primary,
203 'on_hold' => $dao->on_hold,
204 'id' => $dao->email_id,
205 'email' => $dao->email,
206 'locationTypeId' => $dao->locationTypeId,
be2fb01f 207 ];
6a488035
TO
208 }
209
210 return $emails;
211 }
212
213 /**
100fef9d 214 * Set / reset hold status for an email
6a488035 215 *
6a0b768e
TO
216 * @param object $email
217 * Email object.
6a488035 218 */
00be9182 219 public static function holdEmail(&$email) {
7a5db44f 220 if ($email->id && $email->on_hold === NULL) {
221 // email is being updated but no change to on_hold.
222 return;
916f11f8 223 }
7a5db44f 224 if ($email->on_hold === 'null' || $email->on_hold === NULL) {
225 // legacy handling, deprecated.
226 $email->on_hold = 0;
227 }
228 $email->on_hold = (int) $email->on_hold;
229
6a488035
TO
230 //check for update mode
231 if ($email->id) {
be2fb01f 232 $params = [1 => [$email->id, 'Integer']];
7a5db44f 233 if ($email->on_hold) {
6a488035
TO
234 $sql = "
235SELECT id
236FROM civicrm_email
237WHERE id = %1
238AND hold_date IS NULL
239";
240 if (CRM_Core_DAO::singleValueQuery($sql, $params)) {
241 $email->hold_date = date('YmdHis');
242 $email->reset_date = 'null';
243 }
244 }
7a5db44f 245 elseif ($email->on_hold === 0) {
246 // we do this lookup to see if reset_date should be changed.
6a488035
TO
247 $sql = "
248SELECT id
249FROM civicrm_email
250WHERE id = %1
251AND hold_date IS NOT NULL
252AND reset_date IS NULL
253";
254 if (CRM_Core_DAO::singleValueQuery($sql, $params)) {
255 //set reset date only if it is not set and if hold date is set
353ffa53
TO
256 $email->on_hold = FALSE;
257 $email->hold_date = 'null';
6a488035
TO
258 $email->reset_date = date('YmdHis');
259 }
260 }
261 }
262 else {
7a5db44f 263 if ($email->on_hold) {
6a488035
TO
264 $email->hold_date = date('YmdHis');
265 }
266 }
267 }
268
beac1417
MW
269 /**
270 * Generate an array of Domain email addresses.
271 * @return array $domainEmails;
272 */
273 public static function domainEmails() {
be2fb01f 274 $domainEmails = [];
beac1417
MW
275 $domainFrom = (array) CRM_Core_OptionGroup::values('from_email_address');
276 foreach (array_keys($domainFrom) as $k) {
277 $domainEmail = $domainFrom[$k];
278 $domainEmails[$domainEmail] = htmlspecialchars($domainEmail);
279 }
280 return $domainEmails;
281 }
282
6a488035
TO
283 /**
284 * Build From Email as the combination of all the email ids of the logged in user and
285 * the domain email id
286 *
a6c01b45
CW
287 * @return array
288 * an array of email ids
6a488035 289 */
00be9182 290 public static function getFromEmail() {
c52a8fcc 291 // add all configured FROM email addresses
beac1417
MW
292 $fromEmailValues = self::domainEmails();
293
294 if (!Civi::settings()->get('allow_mail_from_logged_in_contact')) {
295 return $fromEmailValues;
c52a8fcc 296 }
6a488035 297
669f45ef 298 $contactFromEmails = [];
6a488035 299 // add logged in user's active email ids
2dbdb9b9 300 $contactID = CRM_Core_Session::getLoggedInContactID();
6a488035
TO
301 if ($contactID) {
302 $contactEmails = self::allEmails($contactID);
beac1417 303 $fromDisplayName = CRM_Core_Session::singleton()->getLoggedInContactDisplayName();
6a488035 304
beac1417 305 foreach ($contactEmails as $emailId => $emailVal) {
6a488035
TO
306 $email = trim($emailVal['email']);
307 if (!$email || $emailVal['on_hold']) {
308 continue;
309 }
310 $fromEmail = "$fromDisplayName <$email>";
311 $fromEmailHtml = htmlspecialchars($fromEmail) . ' ' . $emailVal['locationType'];
312
a7488080 313 if (!empty($emailVal['is_primary'])) {
6a488035
TO
314 $fromEmailHtml .= ' ' . ts('(preferred)');
315 }
0cb9621a 316 $contactFromEmails[$emailId] = $fromEmailHtml;
6a488035
TO
317 }
318 }
669f45ef 319 return CRM_Utils_Array::crmArrayMerge($contactFromEmails, $fromEmailValues);
6a488035
TO
320 }
321
b5c2afd0
EM
322 /**
323 * @return object
324 */
00be9182 325 public static function isMultipleBulkMail() {
84fb7424 326 return Civi::settings()->get('civimail_multiple_bulk_emails');
6a488035 327 }
12445e1c
CW
328
329 /**
fe482240 330 * Call common delete function.
ad37ac8e 331 *
332 * @param int $id
333 *
334 * @return bool
12445e1c 335 */
00be9182 336 public static function del($id) {
a65e2e55 337 return CRM_Contact_BAO_Contact::deleteObjectWithPrimary('Email', $id);
12445e1c 338 }
96025800 339
5b4b9509 340 /**
341 * Get filters for entity reference fields.
342 *
343 * @return array
344 */
345 public static function getEntityRefFilters() {
346 $contactFields = CRM_Contact_BAO_Contact::getEntityRefFilters();
347 foreach ($contactFields as $index => &$contactField) {
348 if (!empty($contactField['entity'])) {
349 // For now email_getlist can't parse state, country etc.
350 unset($contactFields[$index]);
351 }
352 elseif ($contactField['key'] !== 'contact_id') {
353 $contactField['entity'] = 'Contact';
354 $contactField['key'] = 'contact_id.' . $contactField['key'];
355 }
356 }
357 return $contactFields;
358 }
359
6a488035 360}