Commit | Line | Data |
---|---|---|
1e927c45 TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
bc77d7c0 | 4 | | Copyright CiviCRM LLC. All rights reserved. | |
1e927c45 | 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 | | |
1e927c45 | 9 | +--------------------------------------------------------------------+ |
d25dd0ee | 10 | */ |
1e927c45 TO |
11 | |
12 | /** | |
13 | * | |
14 | * @package CRM | |
ca5cec67 | 15 | * @copyright CiviCRM LLC https://civicrm.org/licensing |
1e927c45 | 16 | */ |
3a0d0bbd | 17 | class CRM_Utils_Check_Component_Env extends CRM_Utils_Check_Component { |
1e927c45 | 18 | |
31e80d5a CW |
19 | /** |
20 | * @return array | |
21 | */ | |
22 | public function checkPhpVersion() { | |
be2fb01f | 23 | $messages = []; |
cc1f4988 | 24 | $phpVersion = phpversion(); |
31e80d5a | 25 | |
cc1f4988 | 26 | if (version_compare($phpVersion, CRM_Upgrade_Incremental_General::RECOMMENDED_PHP_VER) >= 0) { |
31e80d5a | 27 | $messages[] = new CRM_Utils_Check_Message( |
165aab59 | 28 | __FUNCTION__, |
cc1f4988 | 29 | ts('This system uses PHP version %1 which meets or exceeds the recommendation of %2.', |
be2fb01f | 30 | [ |
cc1f4988 | 31 | 1 => $phpVersion, |
f955c30c | 32 | 2 => preg_replace(';^(\d+\.\d+(?:\.[1-9]\d*)?).*$;', '\1', CRM_Upgrade_Incremental_General::RECOMMENDED_PHP_VER), |
be2fb01f | 33 | ]), |
4094935a AP |
34 | ts('PHP Up-to-Date'), |
35 | \Psr\Log\LogLevel::INFO, | |
36 | 'fa-server' | |
d0c1e96f TO |
37 | ); |
38 | } | |
cc1f4988 | 39 | elseif (version_compare($phpVersion, CRM_Upgrade_Incremental_General::MIN_RECOMMENDED_PHP_VER) >= 0) { |
d0c1e96f TO |
40 | $messages[] = new CRM_Utils_Check_Message( |
41 | __FUNCTION__, | |
cc1f4988 | 42 | ts('This system uses PHP version %1. This meets the minimum recommendations and you do not need to upgrade immediately, but the preferred version is %2.', |
be2fb01f | 43 | [ |
cc1f4988 CW |
44 | 1 => $phpVersion, |
45 | 2 => CRM_Upgrade_Incremental_General::RECOMMENDED_PHP_VER, | |
be2fb01f | 46 | ]), |
4094935a AP |
47 | ts('PHP Out-of-Date'), |
48 | \Psr\Log\LogLevel::NOTICE, | |
49 | 'fa-server' | |
31e80d5a CW |
50 | ); |
51 | } | |
cc1f4988 | 52 | elseif (version_compare($phpVersion, CRM_Upgrade_Incremental_General::MIN_INSTALL_PHP_VER) >= 0) { |
31e80d5a | 53 | $messages[] = new CRM_Utils_Check_Message( |
165aab59 | 54 | __FUNCTION__, |
96fdb289 | 55 | ts('This system uses PHP version %1. This meets the minimum requirements for CiviCRM to function but is not recommended. At least PHP version %2 is recommended; the preferred version is %3.', |
be2fb01f | 56 | [ |
cc1f4988 CW |
57 | 1 => $phpVersion, |
58 | 2 => CRM_Upgrade_Incremental_General::MIN_RECOMMENDED_PHP_VER, | |
f955c30c | 59 | 3 => preg_replace(';^(\d+\.\d+(?:\.[1-9]\d*)?).*$;', '\1', CRM_Upgrade_Incremental_General::RECOMMENDED_PHP_VER), |
be2fb01f | 60 | ]), |
4094935a AP |
61 | ts('PHP Out-of-Date'), |
62 | \Psr\Log\LogLevel::WARNING, | |
63 | 'fa-server' | |
31e80d5a CW |
64 | ); |
65 | } | |
cc1f4988 CW |
66 | else { |
67 | $messages[] = new CRM_Utils_Check_Message( | |
68 | __FUNCTION__, | |
f955c30c | 69 | ts('This system uses PHP version %1. To ensure the continued operation of CiviCRM, upgrade your server now. At least PHP version %2 is recommended; the preferred version is %3.', |
be2fb01f | 70 | [ |
cc1f4988 CW |
71 | 1 => $phpVersion, |
72 | 2 => CRM_Upgrade_Incremental_General::MIN_RECOMMENDED_PHP_VER, | |
f955c30c | 73 | 3 => preg_replace(';^(\d+\.\d+(?:\.[1-9]\d*)?).*$;', '\1', CRM_Upgrade_Incremental_General::RECOMMENDED_PHP_VER), |
be2fb01f | 74 | ]), |
4094935a AP |
75 | ts('PHP Out-of-Date'), |
76 | \Psr\Log\LogLevel::ERROR, | |
77 | 'fa-server' | |
cc1f4988 CW |
78 | ); |
79 | } | |
31e80d5a CW |
80 | |
81 | return $messages; | |
82 | } | |
83 | ||
991298ee TO |
84 | /** |
85 | * @return array | |
86 | */ | |
87 | public function checkPhpMysqli() { | |
be2fb01f | 88 | $messages = []; |
991298ee TO |
89 | |
90 | if (!extension_loaded('mysqli')) { | |
91 | $messages[] = new CRM_Utils_Check_Message( | |
92 | __FUNCTION__, | |
93 | ts('Future versions of CiviCRM may require the PHP extension "%2". To ensure that your system will be compatible, please install it in advance. For more explanation, see <a href="%1">the announcement</a>.', | |
be2fb01f | 94 | [ |
991298ee TO |
95 | 1 => 'https://civicrm.org/blog/totten/psa-please-verify-php-extension-mysqli', |
96 | 2 => 'mysqli', | |
be2fb01f | 97 | ]), |
4094935a AP |
98 | ts('Forward Compatibility: Enable "mysqli"'), |
99 | \Psr\Log\LogLevel::WARNING, | |
100 | 'fa-server' | |
991298ee TO |
101 | ); |
102 | } | |
103 | ||
104 | return $messages; | |
105 | } | |
106 | ||
d5d56ec1 | 107 | /** |
7342d7c4 TO |
108 | * Check that the MySQL time settings match the PHP time settings. |
109 | * | |
110 | * @return array<CRM_Utils_Check_Message> an empty array, or a list of warnings | |
111 | */ | |
1e927c45 | 112 | public function checkMysqlTime() { |
be2fb01f | 113 | $messages = []; |
1e927c45 TO |
114 | |
115 | $phpNow = date('Y-m-d H:i'); | |
116 | $sqlNow = CRM_Core_DAO::singleValueQuery("SELECT date_format(now(), '%Y-%m-%d %H:%i')"); | |
8010540a | 117 | if (!CRM_Utils_Time::isEqual($phpNow, $sqlNow, 2.5 * 60)) { |
1e927c45 | 118 | $messages[] = new CRM_Utils_Check_Message( |
165aab59 | 119 | __FUNCTION__, |
be2fb01f | 120 | ts('Timestamps reported by MySQL (eg "%2") and PHP (eg "%3" ) are mismatched.<br /><a href="%1">Read more about this warning</a>', [ |
8e0c92e1 | 121 | 1 => CRM_Utils_System::docURL2('sysadmin/requirements/#mysql-time', TRUE), |
1e927c45 TO |
122 | 2 => $sqlNow, |
123 | 3 => $phpNow, | |
be2fb01f | 124 | ]), |
1b366958 | 125 | ts('Timestamp Mismatch'), |
165aab59 CW |
126 | \Psr\Log\LogLevel::ERROR, |
127 | 'fa-server' | |
1e927c45 TO |
128 | ); |
129 | } | |
130 | ||
131 | return $messages; | |
132 | } | |
7342d7c4 | 133 | |
5bc392e6 EM |
134 | /** |
135 | * @return array | |
136 | */ | |
7342d7c4 | 137 | public function checkDebug() { |
7342d7c4 TO |
138 | $config = CRM_Core_Config::singleton(); |
139 | if ($config->debug) { | |
4b540f18 | 140 | $message = new CRM_Utils_Check_Message( |
165aab59 | 141 | __FUNCTION__, |
7342d7c4 | 142 | ts('Warning: Debug is enabled in <a href="%1">system settings</a>. This should not be enabled on production servers.', |
be2fb01f | 143 | [1 => CRM_Utils_System::url('civicrm/admin/setting/debug', 'reset=1')]), |
1b366958 | 144 | ts('Debug Mode Enabled'), |
d1066fc7 | 145 | CRM_Core_Config::environment() == 'Production' ? \Psr\Log\LogLevel::WARNING : \Psr\Log\LogLevel::INFO, |
165aab59 | 146 | 'fa-bug' |
7342d7c4 | 147 | ); |
4b540f18 CW |
148 | $message->addAction( |
149 | ts('Disable Debug Mode'), | |
150 | ts('Disable debug mode now?'), | |
151 | 'api3', | |
be2fb01f | 152 | ['Setting', 'create', ['debug_enabled' => 0]] |
4b540f18 | 153 | ); |
be2fb01f | 154 | return [$message]; |
7342d7c4 TO |
155 | } |
156 | ||
be2fb01f | 157 | return []; |
7342d7c4 TO |
158 | } |
159 | ||
5bc392e6 EM |
160 | /** |
161 | * @return array | |
162 | */ | |
7342d7c4 | 163 | public function checkOutboundMail() { |
be2fb01f | 164 | $messages = []; |
7342d7c4 | 165 | |
d1066fc7 CW |
166 | // CiviMail doesn't work in non-production environments; skip. |
167 | if (CRM_Core_Config::environment() != 'Production') { | |
168 | return $messages; | |
169 | } | |
170 | ||
aaffa79f | 171 | $mailingInfo = Civi::settings()->get('mailing_backend'); |
7342d7c4 TO |
172 | if (($mailingInfo['outBound_option'] == CRM_Mailing_Config::OUTBOUND_OPTION_REDIRECT_TO_DB |
173 | || (defined('CIVICRM_MAIL_LOG') && CIVICRM_MAIL_LOG) | |
174 | || $mailingInfo['outBound_option'] == CRM_Mailing_Config::OUTBOUND_OPTION_DISABLED | |
175 | || $mailingInfo['outBound_option'] == CRM_Mailing_Config::OUTBOUND_OPTION_MOCK) | |
176 | ) { | |
177 | $messages[] = new CRM_Utils_Check_Message( | |
165aab59 | 178 | __FUNCTION__, |
7342d7c4 | 179 | ts('Warning: Outbound email is disabled in <a href="%1">system settings</a>. Proper settings should be enabled on production servers.', |
be2fb01f | 180 | [1 => CRM_Utils_System::url('civicrm/admin/setting/smtp', 'reset=1')]), |
1b366958 | 181 | ts('Outbound Email Disabled'), |
165aab59 CW |
182 | \Psr\Log\LogLevel::WARNING, |
183 | 'fa-envelope' | |
7342d7c4 TO |
184 | ); |
185 | } | |
186 | ||
187 | return $messages; | |
188 | } | |
96025800 | 189 | |
1b366958 AH |
190 | /** |
191 | * Check that domain email and org name are set | |
192 | * @return array | |
193 | */ | |
1b366958 | 194 | public function checkDomainNameEmail() { |
be2fb01f | 195 | $messages = []; |
1b366958 | 196 | |
d1066fc7 CW |
197 | // CiviMail doesn't work in non-production environments; skip. |
198 | if (CRM_Core_Config::environment() != 'Production') { | |
199 | return $messages; | |
200 | } | |
201 | ||
1b366958 | 202 | list($domainEmailName, $domainEmailAddress) = CRM_Core_BAO_Domain::getNameAndEmail(TRUE); |
8ce83e54 KC |
203 | $domain = CRM_Core_BAO_Domain::getDomain(); |
204 | $domainName = $domain->name; | |
205 | $fixEmailUrl = CRM_Utils_System::url("civicrm/admin/options/from_email_address", "&reset=1"); | |
206 | $fixDomainName = CRM_Utils_System::url("civicrm/admin/domain", "action=update&reset=1"); | |
1b366958 AH |
207 | |
208 | if (!$domainEmailAddress || $domainEmailAddress == 'info@EXAMPLE.ORG') { | |
209 | if (!$domainName || $domainName == 'Default Domain Name') { | |
8ce83e54 | 210 | $msg = ts("Please enter your organization's <a href=\"%1\">name, primary address </a> and <a href=\"%2\">default FROM Email Address </a> (for system-generated emails).", |
be2fb01f | 211 | [ |
8ce83e54 KC |
212 | 1 => $fixDomainName, |
213 | 2 => $fixEmailUrl, | |
be2fb01f | 214 | ] |
8ce83e54 | 215 | ); |
1b366958 AH |
216 | } |
217 | else { | |
218 | $msg = ts('Please enter a <a href="%1">default FROM Email Address</a> (for system-generated emails).', | |
be2fb01f | 219 | [1 => $fixEmailUrl]); |
1b366958 AH |
220 | } |
221 | } | |
222 | elseif (!$domainName || $domainName == 'Default Domain Name') { | |
223 | $msg = ts("Please enter your organization's <a href=\"%1\">name and primary address</a>.", | |
be2fb01f | 224 | [1 => $fixDomainName]); |
1b366958 | 225 | } |
aacaa119 AH |
226 | |
227 | if (!empty($msg)) { | |
228 | $messages[] = new CRM_Utils_Check_Message( | |
165aab59 | 229 | __FUNCTION__, |
aacaa119 | 230 | $msg, |
d0d5e238 | 231 | ts('Organization Setup'), |
165aab59 CW |
232 | \Psr\Log\LogLevel::WARNING, |
233 | 'fa-check-square-o' | |
aacaa119 AH |
234 | ); |
235 | } | |
1b366958 AH |
236 | |
237 | return $messages; | |
238 | } | |
239 | ||
240 | /** | |
241 | * Checks if a default bounce handling mailbox is set up | |
242 | * @return array | |
243 | */ | |
1b366958 | 244 | public function checkDefaultMailbox() { |
be2fb01f | 245 | $messages = []; |
d1066fc7 CW |
246 | |
247 | // CiviMail doesn't work in non-production environments; skip. | |
248 | if (CRM_Core_Config::environment() != 'Production') { | |
249 | return $messages; | |
250 | } | |
251 | ||
1b366958 AH |
252 | $config = CRM_Core_Config::singleton(); |
253 | ||
254 | if (in_array('CiviMail', $config->enableComponents) && | |
255 | CRM_Core_BAO_MailSettings::defaultDomain() == "EXAMPLE.ORG" | |
256 | ) { | |
257 | $message = new CRM_Utils_Check_Message( | |
165aab59 | 258 | __FUNCTION__, |
aa96ce62 | 259 | ts('Please configure a <a href="%1">default mailbox</a> for CiviMail.', |
be2fb01f | 260 | [1 => CRM_Utils_System::url('civicrm/admin/mailSettings', "reset=1")]), |
1b366958 | 261 | ts('Configure Default Mailbox'), |
165aab59 CW |
262 | \Psr\Log\LogLevel::WARNING, |
263 | 'fa-envelope' | |
1b366958 | 264 | ); |
be2fb01f | 265 | $docUrl = 'target="_blank" href="' . CRM_Utils_System::docURL(['page' => 'user/advanced-configuration/email-system-configuration/', 'URLonly' => TRUE]) . '""'; |
2a243675 CW |
266 | $message->addHelp( |
267 | ts('A default mailbox must be configured for email bounce processing.') . '<br />' . | |
be2fb01f | 268 | ts("Learn more in the <a %1>online documentation</a>.", [1 => $docUrl]) |
2a243675 | 269 | ); |
1b366958 AH |
270 | $messages[] = $message; |
271 | } | |
272 | ||
273 | return $messages; | |
274 | } | |
aa96ce62 AH |
275 | |
276 | /** | |
6a1cf294 | 277 | * Checks if cron has run in the past hour (3600 seconds) |
aa96ce62 | 278 | * @return array |
6a1cf294 | 279 | * @throws CRM_Core_Exception |
aa96ce62 | 280 | */ |
aa96ce62 | 281 | public function checkLastCron() { |
be2fb01f | 282 | $messages = []; |
aa96ce62 | 283 | |
d1066fc7 CW |
284 | // Cron doesn't work in non-production environments; skip. |
285 | if (CRM_Core_Config::environment() != 'Production') { | |
286 | return $messages; | |
287 | } | |
288 | ||
aa96ce62 AH |
289 | $statusPreference = new CRM_Core_DAO_StatusPreference(); |
290 | $statusPreference->domain_id = CRM_Core_Config::domainID(); | |
6a1cf294 | 291 | $statusPreference->name = __FUNCTION__; |
aa96ce62 | 292 | |
6a1cf294 CW |
293 | $level = \Psr\Log\LogLevel::INFO; |
294 | $now = gmdate('U'); | |
295 | ||
296 | // Get timestamp of last cron run | |
0296367d | 297 | if ($statusPreference->find(TRUE) && !empty($statusPreference->check_info)) { |
6a1cf294 | 298 | $msg = ts('Last cron run at %1.', [1 => CRM_Utils_Date::customFormat(date('c', $statusPreference->check_info))]); |
fba5f6ac | 299 | } |
6a1cf294 | 300 | // If cron record doesn't exist, this is a new install. Make a placeholder record (prefs='new'). |
fba5f6ac | 301 | else { |
6a1cf294 CW |
302 | $statusPreference = CRM_Core_BAO_StatusPreference::create([ |
303 | 'name' => __FUNCTION__, | |
304 | 'check_info' => $now, | |
305 | 'prefs' => 'new', | |
306 | ]); | |
fba5f6ac | 307 | } |
6a1cf294 | 308 | $lastCron = $statusPreference->check_info; |
aa96ce62 | 309 | |
6a1cf294 CW |
310 | if ($statusPreference->prefs !== 'new' && $lastCron > $now - 3600) { |
311 | $title = ts('Cron Running OK'); | |
aa96ce62 | 312 | } |
fba5f6ac | 313 | else { |
6a1cf294 CW |
314 | // If placeholder record found, give one day "grace period" for admin to set-up cron |
315 | if ($statusPreference->prefs === 'new') { | |
316 | $title = ts('Set-up Cron'); | |
317 | $msg = ts('No cron runs have been recorded.'); | |
318 | // After 1 day (86400 seconds) increase the error level | |
319 | $level = ($lastCron > $now - 86400) ? \Psr\Log\LogLevel::NOTICE : \Psr\Log\LogLevel::WARNING; | |
320 | } | |
321 | else { | |
322 | $title = ts('Cron Not Running'); | |
323 | // After 1 day (86400 seconds) increase the error level | |
324 | $level = ($lastCron > $now - 86400) ? \Psr\Log\LogLevel::WARNING : \Psr\Log\LogLevel::ERROR; | |
325 | } | |
6f0dbc29 TO |
326 | $cronLink = 'target="_blank" href="' . htmlentities(CRM_Utils_System::docURL2('sysadmin/setup/jobs/', TRUE)) . '""'; |
327 | $msg .= '<p>' . ts('To enable scheduling support, please <a %1>set up the cron job</a>.', [ | |
328 | 1 => $cronLink, | |
329 | ]) . '</p>'; | |
aa96ce62 AH |
330 | } |
331 | ||
6a1cf294 CW |
332 | $messages[] = new CRM_Utils_Check_Message( |
333 | __FUNCTION__, | |
334 | $msg, | |
335 | $title, | |
336 | $level, | |
337 | 'fa-clock-o' | |
338 | ); | |
aa96ce62 AH |
339 | return $messages; |
340 | } | |
fba5f6ac | 341 | |
50574fda TO |
342 | /** |
343 | * Recommend that sites use path-variables for their directories and URLs. | |
344 | * @return array | |
345 | */ | |
346 | public function checkUrlVariables() { | |
be2fb01f | 347 | $messages = []; |
50574fda | 348 | $hasOldStyle = FALSE; |
be2fb01f | 349 | $settingNames = [ |
50574fda TO |
350 | 'userFrameworkResourceURL', |
351 | 'imageUploadURL', | |
352 | 'customCSSURL', | |
353 | 'extensionsURL', | |
be2fb01f | 354 | ]; |
50574fda TO |
355 | |
356 | foreach ($settingNames as $settingName) { | |
357 | $settingValue = Civi::settings()->get($settingName); | |
358 | if (!empty($settingValue) && $settingValue{0} != '[') { | |
359 | $hasOldStyle = TRUE; | |
360 | break; | |
361 | } | |
362 | } | |
363 | ||
364 | if ($hasOldStyle) { | |
365 | $message = new CRM_Utils_Check_Message( | |
366 | __FUNCTION__, | |
367 | ts('<a href="%1">Resource URLs</a> may use absolute paths, relative paths, or variables. Absolute paths are more difficult to maintain. To maximize portability, consider using a variable in each URL (eg "<tt>[cms.root]</tt>" or "<tt>[civicrm.files]</tt>").', | |
be2fb01f | 368 | [1 => CRM_Utils_System::url('civicrm/admin/setting/url', "reset=1")]), |
50574fda TO |
369 | ts('Resource URLs: Make them portable'), |
370 | \Psr\Log\LogLevel::NOTICE, | |
371 | 'fa-server' | |
372 | ); | |
373 | $messages[] = $message; | |
374 | } | |
375 | ||
376 | return $messages; | |
377 | } | |
378 | ||
379 | /** | |
380 | * Recommend that sites use path-variables for their directories and URLs. | |
381 | * @return array | |
382 | */ | |
383 | public function checkDirVariables() { | |
be2fb01f | 384 | $messages = []; |
50574fda | 385 | $hasOldStyle = FALSE; |
be2fb01f | 386 | $settingNames = [ |
50574fda TO |
387 | 'uploadDir', |
388 | 'imageUploadDir', | |
389 | 'customFileUploadDir', | |
390 | 'customTemplateDir', | |
391 | 'customPHPPathDir', | |
392 | 'extensionsDir', | |
be2fb01f | 393 | ]; |
50574fda TO |
394 | |
395 | foreach ($settingNames as $settingName) { | |
396 | $settingValue = Civi::settings()->get($settingName); | |
397 | if (!empty($settingValue) && $settingValue{0} != '[') { | |
398 | $hasOldStyle = TRUE; | |
399 | break; | |
400 | } | |
401 | } | |
402 | ||
403 | if ($hasOldStyle) { | |
404 | $message = new CRM_Utils_Check_Message( | |
405 | __FUNCTION__, | |
406 | ts('<a href="%1">Directories</a> may use absolute paths, relative paths, or variables. Absolute paths are more difficult to maintain. To maximize portability, consider using a variable in each directory (eg "<tt>[cms.root]</tt>" or "<tt>[civicrm.files]</tt>").', | |
be2fb01f | 407 | [1 => CRM_Utils_System::url('civicrm/admin/setting/path', "reset=1")]), |
50574fda TO |
408 | ts('Directory Paths: Make them portable'), |
409 | \Psr\Log\LogLevel::NOTICE, | |
410 | 'fa-server' | |
411 | ); | |
412 | $messages[] = $message; | |
413 | } | |
414 | ||
415 | return $messages; | |
416 | } | |
417 | ||
3f0e59f6 AH |
418 | /** |
419 | * Check that important directories are writable. | |
420 | * | |
421 | * @return array | |
422 | * Any CRM_Utils_Check_Message instances that need to be generated. | |
423 | */ | |
424 | public function checkDirsWritable() { | |
be2fb01f | 425 | $notWritable = []; |
3f0e59f6 AH |
426 | |
427 | $config = CRM_Core_Config::singleton(); | |
be2fb01f | 428 | $directories = [ |
3f0e59f6 AH |
429 | 'uploadDir' => ts('Temporary Files Directory'), |
430 | 'imageUploadDir' => ts('Images Directory'), | |
431 | 'customFileUploadDir' => ts('Custom Files Directory'), | |
be2fb01f | 432 | ]; |
3f0e59f6 AH |
433 | |
434 | foreach ($directories as $directory => $label) { | |
435 | $file = CRM_Utils_File::createFakeFile($config->$directory); | |
436 | ||
437 | if ($file === FALSE) { | |
438 | $notWritable[] = "$label ({$config->$directory})"; | |
439 | } | |
440 | else { | |
441 | $dirWithSlash = CRM_Utils_File::addTrailingSlash($config->$directory); | |
442 | unlink($dirWithSlash . $file); | |
443 | } | |
444 | } | |
445 | ||
be2fb01f | 446 | $messages = []; |
3f0e59f6 AH |
447 | |
448 | if (!empty($notWritable)) { | |
449 | $messages[] = new CRM_Utils_Check_Message( | |
450 | __FUNCTION__, | |
be2fb01f | 451 | ts('The %1 is not writable. Please check your file permissions.', [ |
3f0e59f6 AH |
452 | 1 => implode(', ', $notWritable), |
453 | 'count' => count($notWritable), | |
454 | 'plural' => 'The following directories are not writable: %1. Please check your file permissions.', | |
be2fb01f CW |
455 | ]), |
456 | ts('Directory not writable', [ | |
3f0e59f6 AH |
457 | 'count' => count($notWritable), |
458 | 'plural' => 'Directories not writable', | |
be2fb01f | 459 | ]), |
3f0e59f6 AH |
460 | \Psr\Log\LogLevel::ERROR, |
461 | 'fa-ban' | |
462 | ); | |
463 | } | |
464 | ||
465 | return $messages; | |
466 | } | |
50574fda | 467 | |
fba5f6ac AH |
468 | /** |
469 | * Checks if new versions are available | |
470 | * @return array | |
471 | */ | |
fba5f6ac | 472 | public function checkVersion() { |
be2fb01f | 473 | $messages = []; |
e2fb6a98 CW |
474 | try { |
475 | $vc = new CRM_Utils_VersionCheck(); | |
476 | $vc->initialize(); | |
477 | } | |
478 | catch (Exception $e) { | |
479 | $messages[] = new CRM_Utils_Check_Message( | |
480 | 'checkVersionError', | |
481 | ts('Directory %1 is not writable. Please change your file permissions.', | |
be2fb01f | 482 | [1 => dirname($vc->cacheFile)]), |
e2fb6a98 CW |
483 | ts('Directory not writable'), |
484 | \Psr\Log\LogLevel::ERROR, | |
485 | 'fa-times-circle-o' | |
486 | ); | |
487 | return $messages; | |
488 | } | |
fba5f6ac | 489 | |
b864507b CW |
490 | // Show a notice if the version_check job is disabled |
491 | if (empty($vc->cronJob['is_active'])) { | |
be2fb01f | 492 | $args = empty($vc->cronJob['id']) ? ['reset' => 1] : ['reset' => 1, 'action' => 'update', 'id' => $vc->cronJob['id']]; |
540c3e63 CW |
493 | $messages[] = new CRM_Utils_Check_Message( |
494 | 'checkVersionDisabled', | |
be2fb01f | 495 | ts('The check for new versions of CiviCRM has been disabled. <a %1>Re-enable the scheduled job</a> to receive important security update notifications.', [1 => 'href="' . CRM_Utils_System::url('civicrm/admin/job', $args) . '"']), |
540c3e63 CW |
496 | ts('Update Check Disabled'), |
497 | \Psr\Log\LogLevel::NOTICE, | |
498 | 'fa-times-circle-o' | |
499 | ); | |
500 | } | |
501 | ||
83f064f2 | 502 | if ($vc->isInfoAvailable) { |
be2fb01f | 503 | $severities = [ |
88790378 TO |
504 | 'info' => CRM_Utils_Check::severityMap(\Psr\Log\LogLevel::INFO), |
505 | 'notice' => CRM_Utils_Check::severityMap(\Psr\Log\LogLevel::NOTICE) , | |
506 | 'warning' => CRM_Utils_Check::severityMap(\Psr\Log\LogLevel::WARNING) , | |
507 | 'critical' => CRM_Utils_Check::severityMap(\Psr\Log\LogLevel::CRITICAL), | |
be2fb01f | 508 | ]; |
0770d5cb | 509 | foreach ($vc->getVersionMessages() ?? [] as $msg) { |
88790378 TO |
510 | $messages[] = new CRM_Utils_Check_Message(__FUNCTION__ . '_' . $msg['name'], |
511 | $msg['message'], $msg['title'], $severities[$msg['severity']], 'fa-cloud-upload'); | |
d450a5f0 | 512 | } |
06576a03 | 513 | } |
fba5f6ac | 514 | |
06576a03 | 515 | return $messages; |
fba5f6ac | 516 | } |
580ad3ef AH |
517 | |
518 | /** | |
519 | * Checks if extensions are set up properly | |
520 | * @return array | |
521 | */ | |
580ad3ef | 522 | public function checkExtensions() { |
be2fb01f | 523 | $messages = []; |
580ad3ef AH |
524 | $extensionSystem = CRM_Extension_System::singleton(); |
525 | $mapper = $extensionSystem->getMapper(); | |
526 | $manager = $extensionSystem->getManager(); | |
580ad3ef AH |
527 | |
528 | if ($extensionSystem->getDefaultContainer()) { | |
529 | $basedir = $extensionSystem->getDefaultContainer()->baseDir; | |
530 | } | |
531 | ||
532 | if (empty($basedir)) { | |
533 | // no extension directory | |
534 | $messages[] = new CRM_Utils_Check_Message( | |
165aab59 | 535 | __FUNCTION__, |
580ad3ef | 536 | ts('Your extensions directory is not set. Click <a href="%1">here</a> to set the extensions directory.', |
be2fb01f | 537 | [1 => CRM_Utils_System::url('civicrm/admin/setting/path', 'reset=1')]), |
e2fb6a98 | 538 | ts('Directory not writable'), |
165aab59 CW |
539 | \Psr\Log\LogLevel::NOTICE, |
540 | 'fa-plug' | |
580ad3ef AH |
541 | ); |
542 | return $messages; | |
543 | } | |
544 | ||
545 | if (!is_dir($basedir)) { | |
546 | $messages[] = new CRM_Utils_Check_Message( | |
165aab59 | 547 | __FUNCTION__, |
9329d168 | 548 | ts('Your extensions directory path points to %1, which is not a directory. Please check your file system.', |
be2fb01f | 549 | [1 => $basedir]), |
580ad3ef | 550 | ts('Extensions directory incorrect'), |
165aab59 CW |
551 | \Psr\Log\LogLevel::ERROR, |
552 | 'fa-plug' | |
580ad3ef AH |
553 | ); |
554 | return $messages; | |
555 | } | |
556 | elseif (!is_writable($basedir)) { | |
557 | $messages[] = new CRM_Utils_Check_Message( | |
698721fc | 558 | __FUNCTION__ . 'Writable', |
599164fe | 559 | ts('Your extensions directory (%1) is read-only. If you would like to perform downloads or upgrades, then change the file permissions.', |
be2fb01f | 560 | [1 => $basedir]), |
37b705a0 | 561 | ts('Read-Only Extensions'), |
6e7ad3dc | 562 | \Psr\Log\LogLevel::NOTICE, |
165aab59 | 563 | 'fa-plug' |
580ad3ef | 564 | ); |
580ad3ef AH |
565 | } |
566 | ||
567 | if (empty($extensionSystem->getDefaultContainer()->baseUrl)) { | |
568 | $messages[] = new CRM_Utils_Check_Message( | |
698721fc | 569 | __FUNCTION__ . 'URL', |
580ad3ef | 570 | ts('The extensions URL is not properly set. Please go to the <a href="%1">URL setting page</a> and correct it.', |
be2fb01f | 571 | [1 => CRM_Utils_System::url('civicrm/admin/setting/url', 'reset=1')]), |
165aab59 CW |
572 | ts('Extensions url missing'), |
573 | \Psr\Log\LogLevel::ERROR, | |
574 | 'fa-plug' | |
580ad3ef | 575 | ); |
580ad3ef AH |
576 | } |
577 | ||
b769826b CW |
578 | if (!$extensionSystem->getBrowser()->isEnabled()) { |
579 | $messages[] = new CRM_Utils_Check_Message( | |
165aab59 | 580 | __FUNCTION__, |
b769826b CW |
581 | ts('Not checking remote URL for extensions since ext_repo_url is set to false.'), |
582 | ts('Extensions check disabled'), | |
165aab59 CW |
583 | \Psr\Log\LogLevel::NOTICE, |
584 | 'fa-plug' | |
b769826b CW |
585 | ); |
586 | return $messages; | |
587 | } | |
588 | ||
589 | try { | |
590 | $remotes = $extensionSystem->getBrowser()->getExtensions(); | |
591 | } | |
592 | catch (CRM_Extension_Exception $e) { | |
593 | $messages[] = new CRM_Utils_Check_Message( | |
165aab59 | 594 | __FUNCTION__, |
b769826b CW |
595 | $e->getMessage(), |
596 | ts('Extension download error'), | |
165aab59 CW |
597 | \Psr\Log\LogLevel::ERROR, |
598 | 'fa-plug' | |
b769826b CW |
599 | ); |
600 | return $messages; | |
601 | } | |
602 | ||
603 | if (!$remotes) { | |
604 | // CRM-13141 There may not be any compatible extensions available for the requested CiviCRM version + CMS. If so, $extdir is empty so just return a notice. | |
605 | $messages[] = new CRM_Utils_Check_Message( | |
165aab59 | 606 | __FUNCTION__, |
be2fb01f | 607 | ts('There are currently no extensions on the CiviCRM public extension directory which are compatible with version %1. If you want to install an extension which is not marked as compatible, you may be able to <a %2>download and install extensions manually</a> (depending on access to your web server).', [ |
b769826b CW |
608 | 1 => CRM_Utils_System::majorVersion(), |
609 | 2 => 'href="http://wiki.civicrm.org/confluence/display/CRMDOC/Extensions"', | |
be2fb01f | 610 | ]), |
b769826b | 611 | ts('No Extensions Available for this Version'), |
165aab59 CW |
612 | \Psr\Log\LogLevel::NOTICE, |
613 | 'fa-plug' | |
b769826b CW |
614 | ); |
615 | return $messages; | |
616 | } | |
617 | ||
580ad3ef AH |
618 | $keys = array_keys($manager->getStatuses()); |
619 | sort($keys); | |
be2fb01f | 620 | $updates = $errors = $okextensions = []; |
48f03858 | 621 | |
580ad3ef AH |
622 | foreach ($keys as $key) { |
623 | try { | |
624 | $obj = $mapper->keyToInfo($key); | |
625 | } | |
626 | catch (CRM_Extension_Exception $ex) { | |
be2fb01f | 627 | $errors[] = ts('Failed to read extension (%1). Please refresh the extension list.', [1 => $key]); |
580ad3ef AH |
628 | continue; |
629 | } | |
630 | $row = CRM_Admin_Page_Extensions::createExtendedInfo($obj); | |
631 | switch ($row['status']) { | |
632 | case CRM_Extension_Manager::STATUS_INSTALLED_MISSING: | |
6b409353 | 633 | $errors[] = ts('%1 extension (%2) is installed but missing files.', [1 => $row['label'] ?? NULL, 2 => $key]); |
580ad3ef AH |
634 | break; |
635 | ||
636 | case CRM_Extension_Manager::STATUS_INSTALLED: | |
48f03858 | 637 | if (!empty($remotes[$key]) && version_compare($row['version'], $remotes[$key]->version, '<')) { |
be2fb01f | 638 | $updates[] = ts('%1 (%2) version %3 is installed. <a %4>Upgrade to version %5</a>.', [ |
6b409353 | 639 | 1 => $row['label'] ?? NULL, |
6714d8d2 SL |
640 | 2 => $key, |
641 | 3 => $row['version'], | |
642 | 4 => 'href="' . CRM_Utils_System::url('civicrm/admin/extensions', "action=update&id=$key&key=$key") . '"', | |
643 | 5 => $remotes[$key]->version, | |
644 | ]); | |
48f03858 CW |
645 | } |
646 | else { | |
647 | if (empty($row['label'])) { | |
648 | $okextensions[] = $key; | |
580ad3ef AH |
649 | } |
650 | else { | |
be2fb01f | 651 | $okextensions[] = ts('%1 (%2) version %3', [ |
48f03858 CW |
652 | 1 => $row['label'], |
653 | 2 => $key, | |
654 | 3 => $row['version'], | |
be2fb01f | 655 | ]); |
580ad3ef AH |
656 | } |
657 | } | |
580ad3ef | 658 | break; |
580ad3ef AH |
659 | } |
660 | } | |
6e61248d CW |
661 | |
662 | if (!$okextensions && !$updates && !$errors) { | |
e2a3547b | 663 | $messages[] = new CRM_Utils_Check_Message( |
c08d5b15 | 664 | 'extensionsOk', |
be2fb01f | 665 | ts('No extensions installed. <a %1>Browse available extensions</a>.', [ |
81756b44 | 666 | 1 => 'href="' . CRM_Utils_System::url('civicrm/admin/extensions', 'reset=1') . '"', |
be2fb01f | 667 | ]), |
6e61248d CW |
668 | ts('Extensions'), |
669 | \Psr\Log\LogLevel::INFO, | |
670 | 'fa-plug' | |
e2a3547b | 671 | ); |
580ad3ef | 672 | } |
6e61248d CW |
673 | |
674 | if ($errors) { | |
675 | $messages[] = new CRM_Utils_Check_Message( | |
698721fc | 676 | __FUNCTION__ . 'Error', |
6e61248d CW |
677 | '<ul><li>' . implode('</li><li>', $errors) . '</li></ul>', |
678 | ts('Extension Error'), | |
679 | \Psr\Log\LogLevel::ERROR, | |
680 | 'fa-plug' | |
681 | ); | |
48f03858 | 682 | } |
6e61248d CW |
683 | |
684 | if ($updates) { | |
685 | $messages[] = new CRM_Utils_Check_Message( | |
686 | 'extensionUpdates', | |
687 | '<ul><li>' . implode('</li><li>', $updates) . '</li></ul>', | |
be2fb01f | 688 | ts('Extension Update Available', ['plural' => '%count Extension Updates Available', 'count' => count($updates)]), |
6e61248d CW |
689 | \Psr\Log\LogLevel::WARNING, |
690 | 'fa-plug' | |
691 | ); | |
580ad3ef | 692 | } |
097c681e | 693 | |
6e61248d | 694 | if ($okextensions) { |
c08d5b15 | 695 | if ($updates || $errors) { |
be2fb01f | 696 | $message = ts('1 extension is up-to-date:', ['plural' => '%count extensions are up-to-date:', 'count' => count($okextensions)]); |
c08d5b15 CW |
697 | } |
698 | else { | |
699 | $message = ts('All extensions are up-to-date:'); | |
700 | } | |
6e61248d CW |
701 | $messages[] = new CRM_Utils_Check_Message( |
702 | 'extensionsOk', | |
c08d5b15 | 703 | $message . '<ul><li>' . implode('</li><li>', $okextensions) . '</li></ul>', |
6e61248d CW |
704 | ts('Extensions'), |
705 | \Psr\Log\LogLevel::INFO, | |
706 | 'fa-plug' | |
707 | ); | |
708 | } | |
580ad3ef AH |
709 | |
710 | return $messages; | |
711 | } | |
712 | ||
580ad3ef | 713 | /** |
4b540f18 CW |
714 | * Checks if there are pending extension upgrades. |
715 | * | |
580ad3ef AH |
716 | * @return array |
717 | */ | |
718 | public function checkExtensionUpgrades() { | |
580ad3ef | 719 | if (CRM_Extension_Upgrades::hasPending()) { |
4b540f18 | 720 | $message = new CRM_Utils_Check_Message( |
165aab59 | 721 | __FUNCTION__, |
4b540f18 CW |
722 | ts('Extension upgrades should be run as soon as possible.'), |
723 | ts('Extension Upgrades Pending'), | |
165aab59 CW |
724 | \Psr\Log\LogLevel::ERROR, |
725 | 'fa-plug' | |
580ad3ef | 726 | ); |
4b540f18 CW |
727 | $message->addAction( |
728 | ts('Run Upgrades'), | |
729 | ts('Run extension upgrades now?'), | |
730 | 'href', | |
be2fb01f | 731 | ['path' => 'civicrm/admin/extensions/upgrade', 'query' => ['reset' => 1, 'destination' => CRM_Utils_System::url('civicrm/a/#/status')]] |
4b540f18 | 732 | ); |
be2fb01f | 733 | return [$message]; |
580ad3ef | 734 | } |
be2fb01f | 735 | return []; |
580ad3ef AH |
736 | } |
737 | ||
738 | /** | |
739 | * Checks if CiviCRM database version is up-to-date | |
740 | * @return array | |
741 | */ | |
580ad3ef | 742 | public function checkDbVersion() { |
be2fb01f | 743 | $messages = []; |
580ad3ef AH |
744 | $dbVersion = CRM_Core_BAO_Domain::version(); |
745 | $upgradeUrl = CRM_Utils_System::url("civicrm/upgrade", "reset=1"); | |
746 | ||
747 | if (!$dbVersion) { | |
748 | // if db.ver missing | |
749 | $messages[] = new CRM_Utils_Check_Message( | |
165aab59 | 750 | __FUNCTION__, |
580ad3ef AH |
751 | ts('Version information found to be missing in database. You will need to determine the correct version corresponding to your current database state.'), |
752 | ts('Database Version Missing'), | |
165aab59 CW |
753 | \Psr\Log\LogLevel::ERROR, |
754 | 'fa-database' | |
580ad3ef AH |
755 | ); |
756 | } | |
757 | elseif (!CRM_Utils_System::isVersionFormatValid($dbVersion)) { | |
758 | $messages[] = new CRM_Utils_Check_Message( | |
165aab59 | 759 | __FUNCTION__, |
580ad3ef AH |
760 | ts('Database is marked with invalid version format. You may want to investigate this before you proceed further.'), |
761 | ts('Database Version Invalid'), | |
165aab59 CW |
762 | \Psr\Log\LogLevel::ERROR, |
763 | 'fa-database' | |
580ad3ef AH |
764 | ); |
765 | } | |
766 | elseif (stripos($dbVersion, 'upgrade')) { | |
767 | // if db.ver indicates a partially upgraded db | |
768 | $messages[] = new CRM_Utils_Check_Message( | |
165aab59 | 769 | __FUNCTION__, |
be2fb01f | 770 | ts('Database check failed - the database looks to have been partially upgraded. You must reload the database with the backup and try the <a href=\'%1\'>upgrade process</a> again.', [1 => $upgradeUrl]), |
580ad3ef | 771 | ts('Database Partially Upgraded'), |
165aab59 CW |
772 | \Psr\Log\LogLevel::ALERT, |
773 | 'fa-database' | |
580ad3ef AH |
774 | ); |
775 | } | |
776 | else { | |
580ad3ef | 777 | // if db.ver < code.ver, time to upgrade |
1fbda76b | 778 | if (CRM_Core_BAO_Domain::isDBUpdateRequired()) { |
580ad3ef | 779 | $messages[] = new CRM_Utils_Check_Message( |
165aab59 | 780 | __FUNCTION__, |
be2fb01f | 781 | ts('New codebase version detected. You must visit <a href=\'%1\'>upgrade screen</a> to upgrade the database.', [1 => $upgradeUrl]), |
580ad3ef | 782 | ts('Database Upgrade Required'), |
165aab59 CW |
783 | \Psr\Log\LogLevel::ALERT, |
784 | 'fa-database' | |
580ad3ef AH |
785 | ); |
786 | } | |
787 | ||
788 | // if db.ver > code.ver, sth really wrong | |
cc52250f | 789 | $codeVersion = CRM_Utils_System::version(); |
790 | if (version_compare($dbVersion, $codeVersion) > 0) { | |
580ad3ef | 791 | $messages[] = new CRM_Utils_Check_Message( |
165aab59 | 792 | __FUNCTION__, |
580ad3ef AH |
793 | ts('Your database is marked with an unexpected version number: %1. The v%2 codebase may not be compatible with your database state. |
794 | You will need to determine the correct version corresponding to your current database state. You may want to revert to the codebase | |
795 | you were using until you resolve this problem.<br/>OR if this is a manual install from git, you might want to fix civicrm-version.php file.', | |
be2fb01f | 796 | [1 => $dbVersion, 2 => $codeVersion] |
580ad3ef AH |
797 | ), |
798 | ts('Database In Unexpected Version'), | |
165aab59 CW |
799 | \Psr\Log\LogLevel::ERROR, |
800 | 'fa-database' | |
580ad3ef AH |
801 | ); |
802 | } | |
803 | } | |
804 | ||
805 | return $messages; | |
806 | } | |
807 | ||
808 | /** | |
809 | * ensure that all CiviCRM tables are InnoDB | |
810 | * @return array | |
811 | */ | |
580ad3ef | 812 | public function checkDbEngine() { |
be2fb01f | 813 | $messages = []; |
580ad3ef AH |
814 | |
815 | if (CRM_Core_DAO::isDBMyISAM(150)) { | |
816 | $messages[] = new CRM_Utils_Check_Message( | |
165aab59 | 817 | __FUNCTION__, |
580ad3ef AH |
818 | ts('Your database is configured to use the MyISAM database engine. CiviCRM requires InnoDB. You will need to convert any MyISAM tables in your database to InnoDB. Using MyISAM tables will result in data integrity issues.'), |
819 | ts('MyISAM Database Engine'), | |
165aab59 CW |
820 | \Psr\Log\LogLevel::ERROR, |
821 | 'fa-database' | |
580ad3ef AH |
822 | ); |
823 | } | |
824 | return $messages; | |
825 | } | |
826 | ||
765e99a6 JP |
827 | /** |
828 | * ensure reply id is set to any default value | |
829 | * @return array | |
830 | */ | |
831 | public function checkReplyIdForMailing() { | |
be2fb01f | 832 | $messages = []; |
765e99a6 | 833 | |
d1066fc7 CW |
834 | // CiviMail doesn't work in non-production environments; skip. |
835 | if (CRM_Core_Config::environment() != 'Production') { | |
836 | return $messages; | |
837 | } | |
838 | ||
765e99a6 JP |
839 | if (!CRM_Mailing_PseudoConstant::defaultComponent('Reply', '')) { |
840 | $messages[] = new CRM_Utils_Check_Message( | |
841 | __FUNCTION__, | |
be2fb01f | 842 | ts('Reply Auto Responder is not set to any default value in <a %1>Headers, Footers, and Automated Messages</a>. This will disable the submit operation on any mailing created from CiviMail.', [1 => 'href="' . CRM_Utils_System::url('civicrm/admin/component', 'reset=1') . '"']), |
765e99a6 JP |
843 | ts('No Default value for Auto Responder.'), |
844 | \Psr\Log\LogLevel::WARNING, | |
845 | 'fa-reply' | |
846 | ); | |
847 | } | |
848 | return $messages; | |
849 | } | |
850 | ||
28288426 CW |
851 | /** |
852 | * Check for required mbstring extension | |
853 | * @return array | |
854 | */ | |
855 | public function checkMbstring() { | |
be2fb01f | 856 | $messages = []; |
28288426 CW |
857 | |
858 | if (!function_exists('mb_substr')) { | |
859 | $messages[] = new CRM_Utils_Check_Message( | |
860 | __FUNCTION__, | |
ade9995e | 861 | ts('The PHP Multibyte String extension is needed for CiviCRM to correctly handle user input among other functionality. Ask your system administrator to install it.'), |
28288426 | 862 | ts('Missing mbstring Extension'), |
ade9995e | 863 | \Psr\Log\LogLevel::WARNING, |
28288426 CW |
864 | 'fa-server' |
865 | ); | |
866 | } | |
867 | return $messages; | |
868 | } | |
869 | ||
f008885c E |
870 | /** |
871 | * Check if environment is Production. | |
872 | * @return array | |
873 | */ | |
874 | public function checkEnvironment() { | |
be2fb01f | 875 | $messages = []; |
f008885c E |
876 | |
877 | $environment = CRM_Core_Config::environment(); | |
878 | if ($environment != 'Production') { | |
879 | $messages[] = new CRM_Utils_Check_Message( | |
880 | __FUNCTION__, | |
be2fb01f | 881 | ts('The environment of this CiviCRM instance is set to \'%1\'. Certain functionality like scheduled jobs has been disabled.', [1 => $environment]), |
f008885c | 882 | ts('Non-Production Environment'), |
d1066fc7 | 883 | \Psr\Log\LogLevel::NOTICE, |
f008885c E |
884 | 'fa-bug' |
885 | ); | |
886 | } | |
887 | return $messages; | |
888 | } | |
889 | ||
75615982 | 890 | /** |
891 | * Check for utf8mb4 support by MySQL. | |
892 | * | |
893 | * @return array<CRM_Utils_Check_Message> an empty array, or a list of warnings | |
894 | */ | |
895 | public function checkMysqlUtf8mb4() { | |
be2fb01f | 896 | $messages = []; |
75615982 | 897 | |
898 | if (CRM_Core_DAO::getConnection()->phptype != 'mysqli') { | |
899 | return $messages; | |
900 | } | |
901 | ||
6bd3e3c4 | 902 | // Use mysqli_query() to avoid logging an error message. |
590e3cec SL |
903 | $mb4testTableName = CRM_Utils_SQL_TempTable::build()->setCategory('utf8mb4test')->getName(); |
904 | if (mysqli_query(CRM_Core_DAO::getConnection()->connection, 'CREATE TEMPORARY TABLE ' . $mb4testTableName . ' (id VARCHAR(255), PRIMARY KEY(id(255))) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC ENGINE=INNODB')) { | |
905 | CRM_Core_DAO::executeQuery('DROP TEMPORARY TABLE ' . $mb4testTableName); | |
75615982 | 906 | } |
6bd3e3c4 | 907 | else { |
75615982 | 908 | $messages[] = new CRM_Utils_Check_Message( |
909 | __FUNCTION__, | |
5aebe76c SL |
910 | ts("Future versions of CiviCRM may require MySQL to support utf8mb4 encoding. It is recommended, though not yet required. Please discuss with your server administrator about configuring your MySQL server for utf8mb4. CiviCRM's recommended configurations are in the <a href='%1' title='System Administrator Guide'>System Administrator Guide</a>", [1 => CRM_Utils_System::docURL2("sysadmin/requirements/#mysql-configuration", TRUE)]), |
911 | ts('MySQL Emoji Support (utf8mb4)'), | |
75615982 | 912 | \Psr\Log\LogLevel::WARNING, |
913 | 'fa-database' | |
914 | ); | |
915 | } | |
916 | // Ensure that the MySQL driver supports utf8mb4 encoding. | |
e479ac61 | 917 | $version = mysqli_get_client_info(); |
75615982 | 918 | if (strpos($version, 'mysqlnd') !== FALSE) { |
919 | // The mysqlnd driver supports utf8mb4 starting at version 5.0.9. | |
920 | $version = preg_replace('/^\D+([\d.]+).*/', '$1', $version); | |
921 | if (version_compare($version, '5.0.9', '<')) { | |
922 | $messages[] = new CRM_Utils_Check_Message( | |
b2a06ef7 | 923 | __FUNCTION__ . 'mysqlnd', |
75615982 | 924 | ts('It is recommended, though not yet required, to upgrade your PHP MySQL driver (mysqlnd) to >= 5.0.9 for utf8mb4 support.'), |
925 | ts('PHP MySQL Driver (mysqlnd)'), | |
926 | \Psr\Log\LogLevel::WARNING, | |
927 | 'fa-server' | |
928 | ); | |
929 | } | |
930 | } | |
931 | else { | |
932 | // The libmysqlclient driver supports utf8mb4 starting at version 5.5.3. | |
933 | if (version_compare($version, '5.5.3', '<')) { | |
934 | $messages[] = new CRM_Utils_Check_Message( | |
b2a06ef7 | 935 | __FUNCTION__ . 'libmysqlclient', |
7806826f | 936 | ts('It is recommended, though not yet required, to upgrade your PHP MySQL driver (libmysqlclient) to >= 5.5.3 for utf8mb4 support.'), |
75615982 | 937 | ts('PHP MySQL Driver (libmysqlclient)'), |
938 | \Psr\Log\LogLevel::WARNING, | |
939 | 'fa-server' | |
940 | ); | |
941 | } | |
942 | } | |
943 | ||
944 | return $messages; | |
945 | } | |
946 | ||
17ca7aac SL |
947 | public function checkMysqlVersion() { |
948 | $messages = []; | |
949 | $version = CRM_Utils_SQL::getDatabaseVersion(); | |
965596b4 | 950 | $minRecommendedVersion = CRM_Upgrade_Incremental_General::MIN_RECOMMENDED_MYSQL_VER; |
57ec4649 | 951 | $mariaDbRecommendedVersion = '10.1'; |
b1634834 SL |
952 | $upcomingCiviChangeVersion = '5.34'; |
953 | if (version_compare(CRM_Utils_SQL::getDatabaseVersion(), $minRecommendedVersion, '<')) { | |
17ca7aac SL |
954 | $messages[] = new CRM_Utils_Check_Message( |
955 | __FUNCTION__, | |
b1634834 | 956 | ts('To prepare for CiviCRM v%4, please upgrade MySQL. The recommended version will be MySQL v%2 or MariaDB v%3.', [ |
f7738e49 | 957 | 1 => $version, |
57ec4649 TO |
958 | 2 => $minRecommendedVersion . '+', |
959 | 3 => $mariaDbRecommendedVersion . '+', | |
b1634834 | 960 | 4 => $upcomingCiviChangeVersion . '+', |
f7738e49 | 961 | ]), |
57ec4649 | 962 | ts('MySQL Out-of-Date'), |
f7738e49 SL |
963 | \Psr\Log\LogLevel::NOTICE, |
964 | 'fa-server' | |
965 | ); | |
966 | } | |
965596b4 | 967 | return $messages; |
17ca7aac SL |
968 | } |
969 | ||
d76cb10e SL |
970 | public function checkPHPIntlExists() { |
971 | $messages = []; | |
972 | if (!extension_loaded('intl')) { | |
973 | $messages[] = new CRM_Utils_Check_Message( | |
974 | __FUNCTION__, | |
edeb3ee8 | 975 | ts('This system currently does not have the PHP-Intl extension enabled. Please contact your system administrator about getting the extension enabled.'), |
d76cb10e SL |
976 | ts('Missing PHP Extension: INTL'), |
977 | \Psr\Log\LogLevel::WARNING, | |
978 | 'fa-server' | |
979 | ); | |
980 | } | |
981 | return $messages; | |
982 | } | |
983 | ||
5bc392e6 | 984 | } |