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