Merge pull request #17981 from eileenmcnaughton/merge_form
[civicrm-core.git] / Civi / Install / Requirements.php
CommitLineData
d7dea16c
EM
1<?php
2
3namespace Civi\Install;
4
5/**
6 * Class Requirements
7 * @package Civi\Install
8 */
9class Requirements {
10
11 /**
12 * Requirement severity -- Requirement successfully met.
13 */
14 const REQUIREMENT_OK = 0;
15
16 /**
17 * Requirement severity -- Warning condition; proceed but flag warning.
18 */
19 const REQUIREMENT_WARNING = 1;
20
21 /**
22 * Requirement severity -- Error condition; abort installation.
23 */
24 const REQUIREMENT_ERROR = 2;
25
34f3bbd9
SL
26 /**
27 * @var array
28 */
c64f69d9 29 protected $system_checks = [
d7dea16c 30 'checkMemory',
d7dea16c
EM
31 'checkMysqlConnectExists',
32 'checkJsonEncodeExists',
9ad2ba41 33 'checkMultibyteExists',
c64f69d9 34 ];
d7dea16c 35
8a0e49bc
MT
36 protected $system_checks_web = [
37 'checkServerVariables',
38 ];
39
c64f69d9 40 protected $database_checks = [
d7dea16c
EM
41 'checkMysqlConnection',
42 'checkMysqlVersion',
43 'checkMysqlInnodb',
44 'checkMysqlTempTables',
45 'checkMySQLAutoIncrementIncrementOne',
46 'checkMysqlTrigger',
47 'checkMysqlThreadStack',
48 'checkMysqlLockTables',
75615982 49 'checkMysqlUtf8mb4',
c64f69d9 50 ];
d7dea16c
EM
51
52 /**
53 * Run all requirements tests.
54 *
55 * @param array $config
56 * An array with two keys:
57 * - file_paths
58 * - db_config
59 *
a6c01b45
CW
60 * @return array
61 * An array of check summaries. Each array contains the keys 'title', 'severity', and 'details'.
d7dea16c
EM
62 */
63 public function checkAll(array $config) {
6ef58b18
SL
64 if (!class_exists('\CRM_Utils_SQL_TempTable')) {
65 require_once dirname(__FILE__) . '/../../CRM/Utils/SQL/TempTable.php';
66 }
d7dea16c
EM
67 return array_merge($this->checkSystem($config['file_paths']), $this->checkDatabase($config['db_config']));
68 }
69
70 /**
71 * Check system requirements are met, such as sufficient memory,
72 * necessary file paths are writable and required php extensions
73 * are available.
74 *
75 * @param array $file_paths
76 * An array of file paths that will be checked to confirm they
77 * are writable.
78 *
79 * @return array
80 */
81 public function checkSystem(array $file_paths) {
c64f69d9 82 $errors = [];
d7dea16c
EM
83
84 $errors[] = $this->checkFilepathIsWritable($file_paths);
85 foreach ($this->system_checks as $check) {
86 $errors[] = $this->$check();
87 }
88
8a0e49bc
MT
89 if (PHP_SAPI !== 'cli') {
90 foreach ($this->system_checks_web as $check) {
91 $errors[] = $this->$check();
92 }
93 }
94
d7dea16c
EM
95 return $errors;
96 }
97
98 /**
99 * Check database connection, database version and other
100 * database requirements are met.
101 *
102 * @param array $db_config
103 * An array with keys:
104 * - host (with optional port specified eg. localhost:12345)
16b10e64 105 * - database (name of database to select)
d7dea16c
EM
106 * - username
107 * - password
108 *
109 * @return array
110 */
111 public function checkDatabase(array $db_config) {
c64f69d9 112 $errors = [];
d7dea16c
EM
113
114 foreach ($this->database_checks as $check) {
115 $errors[] = $this->$check($db_config);
116 }
117
118 return $errors;
119 }
120
9043c4bf
SL
121 /**
122 * Generates a mysql connection
123 *
34f3bbd9 124 * @param $db_config array
9043c4bf
SL
125 * @return object mysqli connection
126 */
127 protected function connect($db_config) {
3916ca43
SL
128 $host = NULL;
129 if (!empty($db_config['host'])) {
130 $host = $db_config['host'];
131 }
132 elseif (!empty($db_config['server'])) {
133 $host = $db_config['server'];
134 }
135 $conn = @mysqli_connect($host, $db_config['username'], $db_config['password'], $db_config['database'], !empty($db_config['port']) ? $db_config['port'] : NULL);
136 return $conn;
9043c4bf
SL
137 }
138
d7dea16c 139 /**
fe482240 140 * Check configured php Memory.
d7dea16c
EM
141 * @return array
142 */
143 public function checkMemory() {
144 $min = 1024 * 1024 * 32;
145 $recommended = 1024 * 1024 * 64;
146
147 $mem = $this->getPHPMemory();
148 $mem_string = ini_get('memory_limit');
149
c64f69d9 150 $results = [
d7dea16c
EM
151 'title' => 'CiviCRM memory check',
152 'severity' => $this::REQUIREMENT_OK,
153 'details' => "You have $mem_string allocated (minimum 32Mb, recommended 64Mb)",
c64f69d9 154 ];
d7dea16c
EM
155
156 if ($mem < $min && $mem > 0) {
157 $results['severity'] = $this::REQUIREMENT_ERROR;
158 }
4c9b6178 159 elseif ($mem < $recommended && $mem != 0) {
d7dea16c
EM
160 $results['severity'] = $this::REQUIREMENT_WARNING;
161 }
4c9b6178 162 elseif ($mem == 0) {
d7dea16c
EM
163 $results['details'] = "Cannot determine PHP memory allocation. Install only if you're sure you've allocated at least 32 MB.";
164 $results['severity'] = $this::REQUIREMENT_WARNING;
165 }
166
167 return $results;
168 }
169
170 /**
fe482240 171 * Get Configured PHP memory.
d7dea16c
EM
172 * @return float
173 */
174 protected function getPHPMemory() {
175 $memString = ini_get("memory_limit");
176
177 switch (strtolower(substr($memString, -1))) {
178 case "k":
179 return round(substr($memString, 0, -1) * 1024);
ea100cb5 180
d7dea16c
EM
181 case "m":
182 return round(substr($memString, 0, -1) * 1024 * 1024);
ea100cb5 183
d7dea16c
EM
184 case "g":
185 return round(substr($memString, 0, -1) * 1024 * 1024 * 1024);
ea100cb5 186
d7dea16c
EM
187 default:
188 return round($memString);
189 }
190 }
191
192 /**
193 * @return array
194 */
00be9182 195 public function checkServerVariables() {
c64f69d9 196 $results = [
d7dea16c
EM
197 'title' => 'CiviCRM PHP server variables',
198 'severity' => $this::REQUIREMENT_OK,
199 'details' => 'The required $_SERVER variables are set',
c64f69d9 200 ];
d7dea16c 201
c64f69d9
CW
202 $required_variables = ['SCRIPT_NAME', 'HTTP_HOST', 'SCRIPT_FILENAME'];
203 $missing = [];
d7dea16c
EM
204
205 foreach ($required_variables as $required_variable) {
206 if (empty($_SERVER[$required_variable])) {
207 $missing[] = '$_SERVER[' . $required_variable . ']';
208 }
209 }
210
211 if ($missing) {
212 $results['severity'] = $this::REQUIREMENT_ERROR;
213 $results['details'] = 'The following PHP variables are not set: ' . implode(', ', $missing);
214 }
215
216 return $results;
217 }
218
219 /**
220 * @return array
221 */
222 public function checkJsonEncodeExists() {
c64f69d9 223 $results = [
d7dea16c
EM
224 'title' => 'CiviCRM JSON encoding support',
225 'severity' => $this::REQUIREMENT_OK,
226 'details' => 'Function json_encode() found',
c64f69d9 227 ];
d7dea16c
EM
228 if (!function_exists('json_encode')) {
229 $results['severity'] = $this::REQUIREMENT_ERROR;
230 $results['details'] = 'Function json_encode() does not exist';
231 }
232
233 return $results;
234 }
235
9ad2ba41
SL
236 /**
237 * CHeck that PHP Multibyte functions are enabled.
238 * @return array
239 */
240 public function checkMultibyteExists() {
c64f69d9 241 $results = [
9ad2ba41
SL
242 'title' => 'CiviCRM MultiByte encoding support',
243 'severity' => $this::REQUIREMENT_OK,
244 'details' => 'PHP Multibyte etension found',
c64f69d9 245 ];
9ad2ba41
SL
246 if (!function_exists('mb_substr')) {
247 $results['severity'] = $this::REQUIREMENT_ERROR;
248 $results['details'] = 'PHP Multibyte extension has not been installed and enabled';
249 }
250
251 return $results;
252 }
253
d7dea16c
EM
254 /**
255 * @return array
256 */
257 public function checkMysqlConnectExists() {
c64f69d9 258 $results = [
d7dea16c
EM
259 'title' => 'CiviCRM MySQL check',
260 'severity' => $this::REQUIREMENT_OK,
fcf908c6 261 'details' => 'Function mysqli_connect() found',
c64f69d9 262 ];
fcf908c6 263 if (!function_exists('mysqli_connect')) {
d7dea16c 264 $results['severity'] = $this::REQUIREMENT_ERROR;
fcf908c6 265 $results['details'] = 'Function mysqli_connect() does not exist';
d7dea16c
EM
266 }
267
268 return $results;
269 }
270
271 /**
272 * @param array $db_config
273 *
274 * @return array
275 */
276 public function checkMysqlConnection(array $db_config) {
c64f69d9 277 $results = [
d7dea16c
EM
278 'title' => 'CiviCRM MySQL connection',
279 'severity' => $this::REQUIREMENT_OK,
280 'details' => "Connected",
c64f69d9 281 ];
d7dea16c 282
9043c4bf 283 $conn = $this->connect($db_config);
d7dea16c
EM
284
285 if (!$conn) {
fcf908c6 286 $results['details'] = mysqli_connect_error();
d7dea16c
EM
287 $results['severity'] = $this::REQUIREMENT_ERROR;
288 return $results;
289 }
290
fcf908c6 291 if (!@mysqli_select_db($conn, $db_config['database'])) {
292 $results['details'] = mysqli_error($conn);
d7dea16c
EM
293 $results['severity'] = $this::REQUIREMENT_ERROR;
294 return $results;
295 }
296
297 return $results;
298 }
299
300 /**
301 * @param array $db_config
302 *
303 * @return array
304 */
305 public function checkMysqlVersion(array $db_config) {
edaacca6
SL
306 if (!class_exists('\CRM_Upgrade_Incremental_General')) {
307 require_once dirname(__FILE__) . '/../../CRM/Upgrade/Incremental/General.php';
308 }
010e8b6c 309 $min = \CRM_Upgrade_Incremental_General::MIN_INSTALL_MYSQL_VER;
c64f69d9 310 $results = [
d7dea16c
EM
311 'title' => 'CiviCRM MySQL Version',
312 'severity' => $this::REQUIREMENT_OK,
c64f69d9 313 ];
d7dea16c 314
9043c4bf 315 $conn = $this->connect($db_config);
fcf908c6 316 if (!$conn || !($info = mysqli_get_server_info($conn))) {
d7dea16c
EM
317 $results['severity'] = $this::REQUIREMENT_WARNING;
318 $results['details'] = "Cannot determine the version of MySQL installed. Please ensure at least version {$min} is installed.";
319 return $results;
320 }
321
66c0d0bd
SL
322 $versionDetails = mysqli_query($conn, 'SELECT version() as version')->fetch_assoc();
323 if (version_compare($versionDetails['version'], $min) == -1) {
d7dea16c
EM
324 $results['severity'] = $this::REQUIREMENT_ERROR;
325 $results['details'] = "MySQL version is {$info}; minimum required is {$min}";
326 return $results;
327 }
328
329 $results['details'] = "MySQL version is {$info}";
330 return $results;
331 }
332
333 /**
334 * @param array $db_config
335 *
336 * @return array
337 */
338 public function checkMysqlInnodb(array $db_config) {
c64f69d9 339 $results = [
d7dea16c
EM
340 'title' => 'CiviCRM InnoDB support',
341 'severity' => $this::REQUIREMENT_ERROR,
87a890cc 342 'details' => 'Could not determine if MySQL has InnoDB support. Assuming none.',
c64f69d9 343 ];
d7dea16c 344
9043c4bf 345 $conn = $this->connect($db_config);
d7dea16c
EM
346 if (!$conn) {
347 return $results;
348 }
349
350 $innodb_support = FALSE;
fcf908c6 351 $result = mysqli_query($conn, "SHOW ENGINES");
352 while ($values = mysqli_fetch_array($result)) {
d7dea16c
EM
353 if ($values['Engine'] == 'InnoDB') {
354 if (strtolower($values['Support']) == 'yes' || strtolower($values['Support']) == 'default') {
355 $innodb_support = TRUE;
356 break;
357 }
358 }
359 }
360
361 if ($innodb_support) {
362 $results['severity'] = $this::REQUIREMENT_OK;
363 $results['details'] = 'MySQL supports InnoDB';
364 }
365 return $results;
366 }
367
368 /**
369 * @param array $db_config
370 *
371 * @return array
372 */
373 public function checkMysqlTempTables(array $db_config) {
c64f69d9 374 $results = [
d7dea16c
EM
375 'title' => 'CiviCRM MySQL Temp Tables',
376 'severity' => $this::REQUIREMENT_OK,
377 'details' => 'MySQL server supports temporary tables',
c64f69d9 378 ];
d7dea16c 379
9043c4bf 380 $conn = $this->connect($db_config);
d7dea16c
EM
381 if (!$conn) {
382 $results['severity'] = $this::REQUIREMENT_ERROR;
383 $results['details'] = "Could not connect to database";
384 return $results;
385 }
386
fcf908c6 387 if (!@mysqli_select_db($conn, $db_config['database'])) {
d7dea16c
EM
388 $results['severity'] = $this::REQUIREMENT_ERROR;
389 $results['details'] = "Could not select the database";
390 return $results;
391 }
6ef58b18
SL
392 $temporaryTableName = \CRM_Utils_SQL_TempTable::build()->setCategory('install')->getName();
393 $r = mysqli_query($conn, 'CREATE TEMPORARY TABLE ' . $temporaryTableName . ' (test text)');
d7dea16c
EM
394 if (!$r) {
395 $results['severity'] = $this::REQUIREMENT_ERROR;
396 $results['details'] = "Database does not support creation of temporary tables";
397 return $results;
398 }
399
6ef58b18 400 mysqli_query($conn, 'DROP TEMPORARY TABLE ' . $temporaryTableName);
d7dea16c
EM
401 return $results;
402 }
403
404 /**
405 * @param $db_config
406 *
407 * @return array
408 */
409 public function checkMysqlTrigger($db_config) {
c64f69d9 410 $results = [
d7dea16c
EM
411 'title' => 'CiviCRM MySQL Trigger',
412 'severity' => $this::REQUIREMENT_OK,
413 'details' => 'Database supports MySQL triggers',
c64f69d9 414 ];
d7dea16c 415
9043c4bf 416 $conn = $this->connect($db_config);
d7dea16c
EM
417 if (!$conn) {
418 $results['severity'] = $this::REQUIREMENT_ERROR;
419 $results['details'] = 'Could not connect to database';
420 return $results;
421 }
422
fcf908c6 423 if (!@mysqli_select_db($conn, $db_config['database'])) {
d7dea16c
EM
424 $results['severity'] = $this::REQUIREMENT_ERROR;
425 $results['details'] = "Could not select the database";
426 return $results;
427 }
428
fcf908c6 429 $r = mysqli_query($conn, 'CREATE TABLE civicrm_install_temp_table_test (test text)');
d7dea16c
EM
430 if (!$r) {
431 $results['severity'] = $this::REQUIREMENT_ERROR;
432 $results['details'] = 'Could not create a table to run test';
433 return $results;
434 }
435
fcf908c6 436 $r = mysqli_query($conn, 'CREATE TRIGGER civicrm_install_temp_table_test_trigger BEFORE INSERT ON civicrm_install_temp_table_test FOR EACH ROW BEGIN END');
d7dea16c
EM
437 if (!$r) {
438 $results['severity'] = $this::REQUIREMENT_ERROR;
439 $results['details'] = 'Database does not support creation of triggers';
440 }
441 else {
fcf908c6 442 mysqli_query($conn, 'DROP TRIGGER civicrm_install_temp_table_test_trigger');
d7dea16c
EM
443 }
444
fcf908c6 445 mysqli_query($conn, 'DROP TABLE civicrm_install_temp_table_test');
d7dea16c
EM
446 return $results;
447 }
448
449 /**
450 * @param array $db_config
451 *
452 * @return array
453 */
454 public function checkMySQLAutoIncrementIncrementOne(array $db_config) {
c64f69d9 455 $results = [
d7dea16c
EM
456 'title' => 'CiviCRM MySQL AutoIncrementIncrement',
457 'severity' => $this::REQUIREMENT_OK,
458 'details' => 'MySQL server auto_increment_increment is 1',
c64f69d9 459 ];
d7dea16c 460
9043c4bf 461 $conn = $this->connect($db_config);
d7dea16c
EM
462 if (!$conn) {
463 $results['severity'] = $this::REQUIREMENT_ERROR;
464 $results['details'] = 'Could not connect to database';
465 return $results;
466 }
467
fcf908c6 468 $r = mysqli_query($conn, "SHOW variables like 'auto_increment_increment'");
d7dea16c
EM
469 if (!$r) {
470 $results['severity'] = $this::REQUIREMENT_ERROR;
471 $results['details'] = 'Could not query database server variables';
472 return $results;
473 }
474
fcf908c6 475 $values = mysqli_fetch_row($r);
d7dea16c
EM
476 if ($values[1] != 1) {
477 $results['severity'] = $this::REQUIREMENT_ERROR;
478 $results['details'] = 'MySQL server auto_increment_increment is not 1';
479 }
480 return $results;
481 }
482
483 /**
484 * @param $db_config
485 *
486 * @return array
487 */
488 public function checkMysqlThreadStack($db_config) {
489 $min_thread_stack = 192;
490
c64f69d9 491 $results = [
d7dea16c
EM
492 'title' => 'CiviCRM Mysql thread stack',
493 'severity' => $this::REQUIREMENT_OK,
494 'details' => 'MySQL thread_stack is OK',
c64f69d9 495 ];
d7dea16c 496
9043c4bf 497 $conn = $this->connect($db_config);
d7dea16c
EM
498 if (!$conn) {
499 $results['severity'] = $this::REQUIREMENT_ERROR;
500 $results['details'] = 'Could not connect to database';
501 return $results;
502 }
503
fcf908c6 504 if (!@mysqli_select_db($conn, $db_config['database'])) {
d7dea16c
EM
505 $results['severity'] = $this::REQUIREMENT_ERROR;
506 $results['details'] = 'Could not select the database';
507 return $results;
508 }
509
34f3bbd9
SL
510 // bytes => kb
511 $r = mysqli_query($conn, "SHOW VARIABLES LIKE 'thread_stack'");
d7dea16c
EM
512 if (!$r) {
513 $results['severity'] = $this::REQUIREMENT_ERROR;
514 $results['details'] = 'Could not query thread_stack value';
515 }
516 else {
fcf908c6 517 $values = mysqli_fetch_row($r);
d7dea16c
EM
518 if ($values[1] < (1024 * $min_thread_stack)) {
519 $results['severity'] = $this::REQUIREMENT_ERROR;
520 $results['details'] = 'MySQL thread_stack is ' . ($values[1] / 1024) . "kb (minimum required is {$min_thread_stack} kb";
521 }
522 }
523
524 return $results;
525 }
526
527 /**
528 * @param $db_config
529 *
530 * @return array
531 */
00be9182 532 public function checkMysqlLockTables($db_config) {
c64f69d9 533 $results = [
d7dea16c
EM
534 'title' => 'CiviCRM MySQL Lock Tables',
535 'severity' => $this::REQUIREMENT_OK,
536 'details' => 'Can successfully lock and unlock tables',
c64f69d9 537 ];
d7dea16c 538
9043c4bf 539 $conn = $this->connect($db_config);
d7dea16c
EM
540 if (!$conn) {
541 $results['severity'] = $this::REQUIREMENT_ERROR;
46bcf597 542 $results['details'] = 'Could not connect to database';
d7dea16c
EM
543 return $results;
544 }
545
fcf908c6 546 if (!@mysqli_select_db($conn, $db_config['database'])) {
d7dea16c
EM
547 $results['severity'] = $this::REQUIREMENT_ERROR;
548 $results['details'] = 'Could not select the database';
fcf908c6 549 mysqli_close($conn);
d7dea16c
EM
550 return $results;
551 }
552
fcf908c6 553 $r = mysqli_query($conn, 'CREATE TEMPORARY TABLE civicrm_install_temp_table_test (test text)');
d7dea16c
EM
554 if (!$r) {
555 $results['severity'] = $this::REQUIREMENT_ERROR;
556 $results['details'] = 'Could not create a table';
fcf908c6 557 mysqli_close($conn);
d7dea16c
EM
558 return $results;
559 }
560
fcf908c6 561 $r = mysqli_query($conn, 'LOCK TABLES civicrm_install_temp_table_test WRITE');
d7dea16c
EM
562 if (!$r) {
563 $results['severity'] = $this::REQUIREMENT_ERROR;
564 $results['details'] = 'Could not obtain a write lock';
fcf908c6 565 mysqli_close($conn);
d7dea16c
EM
566 return $results;
567 }
568
fcf908c6 569 $r = mysqli_query($conn, 'UNLOCK TABLES');
d7dea16c
EM
570 if (!$r) {
571 $results['severity'] = $this::REQUIREMENT_ERROR;
572 $results['details'] = 'Could not release table lock';
573 }
574
fcf908c6 575 mysqli_close($conn);
d7dea16c
EM
576 return $results;
577 }
578
579 /**
580 * @param $file_paths
581 *
582 * @return array
583 */
584 public function checkFilepathIsWritable($file_paths) {
c64f69d9 585 $results = [
d7dea16c
EM
586 'title' => 'CiviCRM directories are writable',
587 'severity' => $this::REQUIREMENT_OK,
588 'details' => 'All required directories are writable: ' . implode(', ', $file_paths),
c64f69d9 589 ];
d7dea16c 590
c64f69d9 591 $unwritable_dirs = [];
d7dea16c
EM
592 foreach ($file_paths as $path) {
593 if (!is_writable($path)) {
594 $unwritable_dirs[] = $path;
595 }
596 }
597
598 if ($unwritable_dirs) {
599 $results['severity'] = $this::REQUIREMENT_ERROR;
600 $results['details'] = "The following directories need to be made writable by the webserver: " . implode(', ', $unwritable_dirs);
601 }
602
603 return $results;
604 }
96025800 605
75615982 606 /**
607 * @param $db_config
608 *
609 * @return array
610 */
611 public function checkMysqlUtf8mb4($db_config) {
c64f69d9 612 $results = [
75615982 613 'title' => 'CiviCRM MySQL utf8mb4 Support',
614 'severity' => $this::REQUIREMENT_OK,
615 'details' => 'Your system supports the MySQL utf8mb4 character set.',
c64f69d9 616 ];
75615982 617
618 $conn = $this->connect($db_config);
619 if (!$conn) {
620 $results['severity'] = $this::REQUIREMENT_ERROR;
621 $results['details'] = 'Could not connect to database';
622 return $results;
623 }
624
625 if (!@mysqli_select_db($conn, $db_config['database'])) {
626 $results['severity'] = $this::REQUIREMENT_ERROR;
627 $results['details'] = 'Could not select the database';
628 mysqli_close($conn);
629 return $results;
630 }
631
50169eb4 632 mysqli_query($conn, 'DROP TABLE IF EXISTS civicrm_utf8mb4_test');
75615982 633 $r = mysqli_query($conn, 'CREATE TABLE civicrm_utf8mb4_test (id VARCHAR(255), PRIMARY KEY(id(255))) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC ENGINE=INNODB');
634 if (!$r) {
635 $results['severity'] = $this::REQUIREMENT_WARNING;
636 $results['details'] = 'It is recommended, though not yet required, to configure your MySQL server for utf8mb4 support. You will need the following MySQL server configuration: innodb_large_prefix=true innodb_file_format=barracuda innodb_file_per_table=true';
637 mysqli_close($conn);
638 return $results;
639 }
50169eb4 640 mysqli_query($conn, 'DROP TABLE civicrm_utf8mb4_test');
75615982 641
642 // Ensure that the MySQL driver supports utf8mb4 encoding.
e479ac61 643 $version = mysqli_get_client_info();
75615982 644 if (strpos($version, 'mysqlnd') !== FALSE) {
645 // The mysqlnd driver supports utf8mb4 starting at version 5.0.9.
646 $version = preg_replace('/^\D+([\d.]+).*/', '$1', $version);
647 if (version_compare($version, '5.0.9', '<')) {
648 $results['severity'] = $this::REQUIREMENT_WARNING;
649 $results['details'] = 'It is recommended, though not yet required, to upgrade your PHP MySQL driver (mysqlnd) to >= 5.0.9 for utf8mb4 support.';
650 mysqli_close($conn);
651 return $results;
652 }
653 }
654 else {
655 // The libmysqlclient driver supports utf8mb4 starting at version 5.5.3.
656 if (version_compare($version, '5.5.3', '<')) {
657 $results['severity'] = $this::REQUIREMENT_WARNING;
658 $results['details'] = 'It is recommended, though not yet required, to upgrade your PHP MySQL driver (libmysqlclient) to >= 5.5.3 for utf8mb4 support.';
659 mysqli_close($conn);
660 return $results;
661 }
662 }
663
664 mysqli_close($conn);
665 return $results;
666 }
667
d7dea16c 668}