Merge pull request #24115 from kcristiano/5.52-token
[civicrm-core.git] / CRM / Core / BAO / Domain.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
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 |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 *
14 * @package CRM
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
16 */
17
18 /**
19 *
20 */
21 class CRM_Core_BAO_Domain extends CRM_Core_DAO_Domain {
22
23 /**
24 * Cache for a domain's location array
25 * @var array
26 */
27 private $_location = NULL;
28
29 /**
30 * Flushes the cache set by getDomain.
31 *
32 * @see CRM_Core_BAO_Domain::getDomain()
33 * @param CRM_Core_DAO_Domain $domain
34 */
35 public static function onPostSave($domain) {
36 // We want to clear out any cached tokens.
37 // Editing a domain is so rare we can risk being heavy handed.
38 Civi::cache('metadata')->clear();
39 Civi::$statics[__CLASS__]['current'] = NULL;
40 }
41
42 /**
43 * Retrieve DB object and copy to defaults array.
44 *
45 * @param array $params
46 * Array of criteria values.
47 * @param array $defaults
48 * Array to be populated with found values.
49 *
50 * @return self|null
51 * The DAO object, if found.
52 *
53 * @deprecated
54 */
55 public static function retrieve($params, &$defaults) {
56 return self::commonRetrieve(self::class, $params, $defaults);
57 }
58
59 /**
60 * Get the current domain.
61 *
62 * @return \CRM_Core_BAO_Domain
63 * @throws \CRM_Core_Exception
64 */
65 public static function getDomain() {
66 $domain = Civi::$statics[__CLASS__]['current'] ?? NULL;
67 if (!$domain) {
68 $domain = new CRM_Core_BAO_Domain();
69 $domain->id = CRM_Core_Config::domainID();
70 if (!$domain->find(TRUE)) {
71 throw new CRM_Core_Exception('No domain in DB');
72 }
73 Civi::$statics[__CLASS__]['current'] = $domain;
74 }
75 return $domain;
76 }
77
78 /**
79 * @param bool $skipUsingCache
80 *
81 * @return string
82 *
83 * @throws \CRM_Core_Exception
84 */
85 public static function version($skipUsingCache = FALSE) {
86 if ($skipUsingCache) {
87 Civi::$statics[__CLASS__]['current'] = NULL;
88 }
89
90 return self::getDomain()->version;
91 }
92
93 /**
94 * Is a database update required to apply latest schema changes.
95 *
96 * @return bool
97 *
98 * @throws \CRM_Core_Exception
99 */
100 public static function isDBUpdateRequired() {
101 $dbVersion = self::version();
102 $codeVersion = CRM_Utils_System::version();
103 return version_compare($dbVersion, $codeVersion) < 0;
104 }
105
106 /**
107 * Checks that the current DB schema is at least $min version
108 *
109 * @param string|int $min
110 * @return bool
111 */
112 public static function isDBVersionAtLeast($min) {
113 return version_compare(self::version(), $min, '>=');
114 }
115
116 /**
117 * @return string
118 */
119 protected static function getMissingDomainFromEmailMessage(): string {
120 $url = CRM_Utils_System::url('civicrm/admin/options/from_email_address',
121 'reset=1'
122 );
123 $status = ts("There is no valid default from email address configured for the domain. You can configure here <a href='%1'>Configure From Email Address.</a>", [1 => $url]);
124 return $status;
125 }
126
127 /**
128 * Get the location values of a domain.
129 *
130 * @return CRM_Core_BAO_Location[]|NULL
131 */
132 public function getLocationValues() {
133 if ($this->_location == NULL) {
134 $params = [
135 'contact_id' => $this->contact_id,
136 ];
137 $this->_location = CRM_Core_BAO_Location::getValues($params, TRUE);
138
139 if (empty($this->_location)) {
140 $this->_location = NULL;
141 }
142 }
143 return $this->_location;
144 }
145
146 /**
147 * Update a domain.
148 *
149 * @param array $params
150 * @param int $id
151 *
152 * @return CRM_Core_DAO_Domain
153 * @throws \CRM_Core_Exception
154 */
155 public static function edit($params, $id): CRM_Core_DAO_Domain {
156 $params['id'] = $id;
157 return self::writeRecord($params);
158 }
159
160 /**
161 * Create or update domain.
162 *
163 * @param array $params
164 * @return CRM_Core_DAO_Domain
165 */
166 public static function create($params) {
167 return self::writeRecord($params);
168 }
169
170 /**
171 * @return bool
172 */
173 public static function multipleDomains() {
174 $session = CRM_Core_Session::singleton();
175
176 $numberDomains = $session->get('numberDomains');
177 if (!$numberDomains) {
178 $query = 'SELECT count(*) from civicrm_domain';
179 $numberDomains = CRM_Core_DAO::singleValueQuery($query);
180 $session->set('numberDomains', $numberDomains);
181 }
182 return $numberDomains > 1;
183 }
184
185 /**
186 * @param bool $skipFatal
187 * @param bool $returnString
188 * If you are using this second parameter you probably are better
189 * calling `getFromEmail()` which will return an actual string.
190 *
191 * @return array
192 * name & email for domain
193 *
194 * @throws \CRM_Core_Exception
195 */
196 public static function getNameAndEmail($skipFatal = FALSE, $returnString = FALSE) {
197 $fromEmailAddress = CRM_Core_OptionGroup::values('from_email_address', NULL, NULL, NULL, ' AND is_default = 1');
198 if (!empty($fromEmailAddress)) {
199 if ($returnString) {
200 // Return a string like: "Demonstrators Anonymous" <info@example.org>
201 return $fromEmailAddress;
202 }
203 foreach ($fromEmailAddress as $key => $value) {
204 $email = CRM_Utils_Mail::pluckEmailFromHeader($value);
205 $fromArray = explode('"', $value);
206 $fromName = $fromArray[1] ?? NULL;
207 break;
208 }
209 return [$fromName, $email];
210 }
211
212 if ($skipFatal) {
213 return [NULL, NULL];
214 }
215
216 $status = self::getMissingDomainFromEmailMessage();
217
218 throw new CRM_Core_Exception($status);
219 }
220
221 /**
222 * Get the domain email in a format suitable for using as the from address.
223 *
224 * @return string
225 * @throws \CRM_Core_Exception
226 */
227 public static function getFromEmail(): string {
228 $email = CRM_Core_OptionGroup::values('from_email_address', NULL, NULL, NULL, ' AND is_default = 1');
229 $email = current($email);
230 if (!$email) {
231 throw new CRM_Core_Exception(self::getMissingDomainFromEmailMessage());
232 }
233 return $email;
234 }
235
236 /**
237 * @param int $contactID
238 *
239 * @return bool|null|object|string
240 *
241 * @throws \CRM_Core_Exception
242 */
243 public static function addContactToDomainGroup($contactID) {
244 $groupID = self::getGroupId();
245
246 if ($groupID) {
247 $contactIDs = [$contactID];
248 CRM_Contact_BAO_GroupContact::addContactsToGroup($contactIDs, $groupID);
249
250 return $groupID;
251 }
252 return FALSE;
253 }
254
255 /**
256 * @return bool|null|object|string
257 *
258 * @throws \CRM_Core_Exception
259 */
260 public static function getGroupId() {
261 static $groupID = NULL;
262
263 if ($groupID) {
264 return $groupID;
265 }
266
267 $domainGroupID = Civi::settings()->get('domain_group_id');
268 $multisite = Civi::settings()->get('is_enabled');
269
270 if ($domainGroupID) {
271 $groupID = $domainGroupID;
272 }
273 elseif ($multisite) {
274 // create a group with that of domain name
275 $title = self::getDomain()->name;
276 $groupID = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group',
277 $title, 'id', 'title', TRUE
278 );
279 }
280 return $groupID ? $groupID : FALSE;
281 }
282
283 /**
284 * @param int $groupId
285 *
286 * @return bool
287 *
288 * @throws \CRM_Core_Exception
289 */
290 public static function isDomainGroup($groupId) {
291 $domainGroupID = self::getGroupId();
292 return $domainGroupID == (bool) $groupId;
293 }
294
295 /**
296 * @return array
297 *
298 * @throws \CRM_Core_Exception
299 */
300 public static function getChildGroupIds() {
301 $domainGroupID = self::getGroupId();
302 $childGrps = [];
303
304 if ($domainGroupID) {
305 $childGrps = CRM_Contact_BAO_GroupNesting::getChildGroupIds($domainGroupID);
306 $childGrps[] = $domainGroupID;
307 }
308 return $childGrps;
309 }
310
311 /**
312 * Retrieve a list of contact-ids that belongs to current domain/site.
313 *
314 * @return array
315 *
316 * @throws \CRM_Core_Exception
317 */
318 public static function getContactList() {
319 $siteGroups = CRM_Core_BAO_Domain::getChildGroupIds();
320 $siteContacts = [];
321
322 if (!empty($siteGroups)) {
323 $query = "
324 SELECT cc.id
325 FROM civicrm_contact cc
326 INNER JOIN civicrm_group_contact gc ON
327 (gc.contact_id = cc.id AND gc.status = 'Added' AND gc.group_id IN (" . implode(',', $siteGroups) . "))";
328
329 $dao = CRM_Core_DAO::executeQuery($query);
330 while ($dao->fetch()) {
331 $siteContacts[] = $dao->id;
332 }
333 }
334 return $siteContacts;
335 }
336
337 /**
338 * CRM-20308 & CRM-19657
339 * Return domain information / user information for the usage in receipts
340 * Try default from address then fall back to using logged in user details
341 *
342 * @throws \CiviCRM_API3_Exception
343 */
344 public static function getDefaultReceiptFrom() {
345 $domain = civicrm_api3('domain', 'getsingle', ['id' => CRM_Core_Config::domainID()]);
346 if (!empty($domain['from_email'])) {
347 return [$domain['from_name'], $domain['from_email']];
348 }
349 if (!empty($domain['domain_email'])) {
350 return [$domain['name'], $domain['domain_email']];
351 }
352 $userName = '';
353 $userEmail = '';
354
355 if (!Civi::settings()->get('allow_mail_from_logged_in_contact')) {
356 return [$userName, $userEmail];
357 }
358
359 $userID = CRM_Core_Session::getLoggedInContactID();
360 if (!empty($userID)) {
361 [$userName, $userEmail] = CRM_Contact_BAO_Contact_Location::getEmailDetails($userID);
362 }
363 // If still empty fall back to the logged in user details.
364 // return empty values no matter what.
365 return [$userName, $userEmail];
366 }
367
368 /**
369 * Get address to be used for system from addresses when a reply is not expected.
370 */
371 public static function getNoReplyEmailAddress() {
372 $emailDomain = CRM_Core_BAO_MailSettings::defaultDomain();
373 return "do-not-reply@$emailDomain";
374 }
375
376 }