Skip to content

Commit f0249f8

Browse files
authored
refactor(db): Update backup script to central config reads; exclude phpstan info (openemr#10966)
Fixes openemr#10774 (we're done!) #### Short description of what this resolves: Updates the backup tool to use the central config reading. Doesn't try to address any other backup-related issues. #### Changes proposed in this pull request: - Read DB config from now-standard tooling in backup script - Thread its values through to the various commands used during backup - Exclude `tmp-phpstan` from backup (should only affect dev, but makes the process WAY faster to test) #### Does your code include anything generated by an AI Engine? Yes / No No
1 parent 30aafcc commit f0249f8

6 files changed

Lines changed: 66 additions & 97 deletions

File tree

.phpstan/baseline/binaryOp.invalid.php

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3886,11 +3886,6 @@
38863886
'count' => 3,
38873887
'path' => __DIR__ . '/../../interface/main/backup.php',
38883888
];
3889-
$ignoreErrors[] = [
3890-
'message' => '#^Binary operation "\\." between mixed and \'/documents…\' results in an error\\.$#',
3891-
'count' => 6,
3892-
'path' => __DIR__ . '/../../interface/main/backup.php',
3893-
];
38943889
$ignoreErrors[] = [
38953890
'message' => '#^Binary operation "\\." between mixed and \'/eventlog_\' results in an error\\.$#',
38963891
'count' => 1,
@@ -3916,11 +3911,6 @@
39163911
'count' => 1,
39173912
'path' => __DIR__ . '/../../interface/main/backup.php',
39183913
];
3919-
$ignoreErrors[] = [
3920-
'message' => '#^Binary operation "\\." between mixed and \'\\.onsite_activity…\' results in an error\\.$#',
3921-
'count' => 5,
3922-
'path' => __DIR__ . '/../../interface/main/backup.php',
3923-
];
39243914
$ignoreErrors[] = [
39253915
'message' => '#^Binary operation "\\." between non\\-falsy\\-string and mixed results in an error\\.$#',
39263916
'count' => 2,

.phpstan/baseline/cast.string.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@
598598
];
599599
$ignoreErrors[] = [
600600
'message' => '#^Cannot cast mixed to string\\.$#',
601-
'count' => 41,
601+
'count' => 6,
602602
'path' => __DIR__ . '/../../interface/main/backup.php',
603603
];
604604
$ignoreErrors[] = [

.phpstan/baseline/offsetAccess.nonOffsetAccessible.php

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12021,31 +12021,6 @@
1202112021
'count' => 1,
1202212022
'path' => __DIR__ . '/../../interface/main/backup.php',
1202312023
];
12024-
$ignoreErrors[] = [
12025-
'message' => '#^Cannot access offset \'dbase\' on mixed\\.$#',
12026-
'count' => 16,
12027-
'path' => __DIR__ . '/../../interface/main/backup.php',
12028-
];
12029-
$ignoreErrors[] = [
12030-
'message' => '#^Cannot access offset \'host\' on mixed\\.$#',
12031-
'count' => 6,
12032-
'path' => __DIR__ . '/../../interface/main/backup.php',
12033-
];
12034-
$ignoreErrors[] = [
12035-
'message' => '#^Cannot access offset \'login\' on mixed\\.$#',
12036-
'count' => 6,
12037-
'path' => __DIR__ . '/../../interface/main/backup.php',
12038-
];
12039-
$ignoreErrors[] = [
12040-
'message' => '#^Cannot access offset \'pass\' on mixed\\.$#',
12041-
'count' => 6,
12042-
'path' => __DIR__ . '/../../interface/main/backup.php',
12043-
];
12044-
$ignoreErrors[] = [
12045-
'message' => '#^Cannot access offset \'port\' on mixed\\.$#',
12046-
'count' => 6,
12047-
'path' => __DIR__ . '/../../interface/main/backup.php',
12048-
];
1204912024
$ignoreErrors[] = [
1205012025
'message' => '#^Cannot access offset \'tmp_name\' on mixed\\.$#',
1205112026
'count' => 2,

.phpstan/baseline/openemr.forbiddenGlobalsAccess.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -808,7 +808,7 @@
808808
];
809809
$ignoreErrors[] = [
810810
'message' => '#^Direct access to \\$GLOBALS is forbidden\\. Use OEGlobalsBag\\:\\:getInstance\\(\\)\\-\\>get\\(\\) instead\\.$#',
811-
'count' => 19,
811+
'count' => 13,
812812
'path' => __DIR__ . '/../../interface/main/backup.php',
813813
];
814814
$ignoreErrors[] = [

.phpstan/baseline/variable.undefined.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11326,11 +11326,6 @@
1132611326
'count' => 1,
1132711327
'path' => __DIR__ . '/../../interface/main/backup.php',
1132811328
];
11329-
$ignoreErrors[] = [
11330-
'message' => '#^Variable \\$sqlconf might not be defined\\.$#',
11331-
'count' => 40,
11332-
'path' => __DIR__ . '/../../interface/main/backup.php',
11333-
];
1133411329
$ignoreErrors[] = [
1133511330
'message' => '#^Variable \\$srcdir might not be defined\\.$#',
1133611331
'count' => 2,

interface/main/backup.php

Lines changed: 64 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,20 @@
3131
* @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
3232
*/
3333

34-
set_time_limit(0);
35-
require_once("../globals.php");
36-
require_once("$srcdir/layout.inc.php");
37-
require_once("$srcdir/patient.inc.php");
38-
34+
use OpenEMR\BC\DatabaseConnectionOptions;
3935
use OpenEMR\Common\Acl\AccessDeniedHelper;
4036
use OpenEMR\Common\Acl\AclMain;
4137
use OpenEMR\Common\Csrf\CsrfUtils;
4238
use OpenEMR\Common\Logging\EventAuditLogger;
4339
use OpenEMR\Core\Header;
40+
use OpenEMR\Core\OEGlobalsBag;
41+
42+
set_time_limit(0);
43+
$globalsBag = require_once("../globals.php");
44+
assert($globalsBag instanceof OEGlobalsBag);
45+
46+
require_once("$srcdir/layout.inc.php");
47+
require_once("$srcdir/patient.inc.php");
4448

4549
if (!empty($_POST)) {
4650
if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"])) {
@@ -63,6 +67,8 @@ function gzopen($filename, $mode, $use_include_path = 0)
6367
AccessDeniedHelper::denyWithTemplate("ACL check failed for admin/super: Backup", xl("Backup"));
6468
}
6569

70+
$dbOptions = DatabaseConnectionOptions::forSite($globalsBag->getString('OE_SITE_DIR'));
71+
6672
// When automatically including lists used in selected layouts, these lists are not included.
6773
$excluded_lists = [
6874
'allergy_issue_list',
@@ -449,16 +455,11 @@ function export_submit(step) {
449455
$mysql_cmd = $MYSQL_PATH . DIRECTORY_SEPARATOR . 'mysql';
450456
$mysql_dump_cmd = $mysql_cmd . 'dump';
451457
$mysql_ssl = '';
452-
if (file_exists($GLOBALS['OE_SITE_DIR'] . "/documents/certificates/mysql-ca")) {
453-
// Support for mysql SSL encryption
454-
$mysql_ssl = " --ssl-ca=" . escapeshellarg($GLOBALS['OE_SITE_DIR'] . "/documents/certificates/mysql-ca") . " ";
455-
if (
456-
file_exists($GLOBALS['OE_SITE_DIR'] . "/documents/certificates/mysql-key") &&
457-
file_exists($GLOBALS['OE_SITE_DIR'] . "/documents/certificates/mysql-cert")
458-
) {
459-
// Support for mysql SSL client based cert authentication
460-
$mysql_ssl .= "--ssl-cert=" . escapeshellarg($GLOBALS['OE_SITE_DIR'] . "/documents/certificates/mysql-cert") . " ";
461-
$mysql_ssl .= "--ssl-key=" . escapeshellarg($GLOBALS['OE_SITE_DIR'] . "/documents/certificates/mysql-key") . " ";
458+
if ($dbOptions->sslCaPath !== null) {
459+
$mysql_ssl = " --ssl-ca=" . escapeshellarg($dbOptions->sslCaPath) . " ";
460+
if ($dbOptions->sslClientCert !== null) {
461+
$mysql_ssl .= "--ssl-cert=" . escapeshellarg($dbOptions->sslClientCert['cert']) . " ";
462+
$mysql_ssl .= "--ssl-key=" . escapeshellarg($dbOptions->sslClientCert['key']) . " ";
462463
}
463464
}
464465

@@ -517,13 +518,13 @@ function export_submit(step) {
517518

518519
$file_to_compress = "$BACKUP_DIR/openemr.sql"; // gzip this file after creation
519520

520-
$cmd = escapeshellcmd($mysql_dump_cmd) . " -u " . escapeshellarg((string) $sqlconf["login"]) .
521-
" -p" . escapeshellarg((string) $sqlconf["pass"]) .
522-
" -h " . escapeshellarg((string) $sqlconf["host"]) .
523-
" --port=" . escapeshellarg((string) $sqlconf["port"]) .
524-
" --ignore-table=" . escapeshellarg($sqlconf["dbase"] . ".onsite_activity_view") .
521+
$cmd = escapeshellcmd($mysql_dump_cmd) . " -u " . escapeshellarg($dbOptions->user) .
522+
" -p" . escapeshellarg($dbOptions->password) .
523+
" -h " . escapeshellarg((string) $dbOptions->host) .
524+
" --port=" . escapeshellarg((string) $dbOptions->port) .
525+
" --ignore-table=" . escapeshellarg($dbOptions->dbname . ".onsite_activity_view") .
525526
" --hex-blob --opt --quote-names --no-tablespaces -r " . escapeshellarg($file_to_compress) . " $mysql_ssl " .
526-
escapeshellarg((string) $sqlconf["dbase"]);
527+
escapeshellarg($dbOptions->dbname);
527528

528529
$auto_continue = true;
529530
}
@@ -540,6 +541,11 @@ function export_submit(step) {
540541

541542
// Select the files and directories to archive. Basically everything
542543
// except site-specific data for other sites.
544+
$exclude_from_backup = [
545+
// This should never exist in prod, but it makes testing backups
546+
// locally a lot faster.
547+
'tmp-phpstan',
548+
];
543549
$file_list = [];
544550
$dh = opendir($webserver_root);
545551
if (!$dh) {
@@ -550,6 +556,9 @@ function export_submit(step) {
550556
if ($filename == '.' || $filename == '..') {
551557
continue;
552558
}
559+
if (in_array($filename, $exclude_from_backup)) {
560+
continue;
561+
}
553562

554563
if ($filename == 'sites') {
555564
// Omit other sites.
@@ -703,21 +712,21 @@ function export_submit(step) {
703712

704713
if ($tables) {
705714
if (IS_WINDOWS) {
706-
$cmd .= escapeshellcmd('"' . $mysql_dump_cmd . '"') . " -u " . escapeshellarg((string) $sqlconf["login"]) .
707-
" -p" . escapeshellarg((string) $sqlconf["pass"]) .
708-
" -h " . escapeshellarg((string) $sqlconf["host"]) .
709-
" --port=" . escapeshellarg((string) $sqlconf["port"]) .
710-
" --ignore-table=" . escapeshellarg($sqlconf["dbase"] . ".onsite_activity_view") .
715+
$cmd .= escapeshellcmd('"' . $mysql_dump_cmd . '"') . " -u " . escapeshellarg($dbOptions->user) .
716+
" -p" . escapeshellarg($dbOptions->password) .
717+
" -h " . escapeshellarg((string) $dbOptions->host) .
718+
" --port=" . escapeshellarg((string) $dbOptions->port) .
719+
" --ignore-table=" . escapeshellarg($dbOptions->dbname . ".onsite_activity_view") .
711720
" --hex-blob --opt --quote-names --skip-comments --no-tablespaces $mysql_ssl " .
712-
escapeshellarg((string) $sqlconf["dbase"]) . " $tables";
721+
escapeshellarg($dbOptions->dbname) . " $tables";
713722
} else {
714-
$cmd .= escapeshellcmd($mysql_dump_cmd) . " -u " . escapeshellarg((string) $sqlconf["login"]) .
715-
" -p" . escapeshellarg((string) $sqlconf["pass"]) .
716-
" -h " . escapeshellarg((string) $sqlconf["host"]) .
717-
" --port=" . escapeshellarg((string) $sqlconf["port"]) .
718-
" --ignore-table=" . escapeshellarg($sqlconf["dbase"] . ".onsite_activity_view") .
723+
$cmd .= escapeshellcmd($mysql_dump_cmd) . " -u " . escapeshellarg($dbOptions->user) .
724+
" -p" . escapeshellarg($dbOptions->password) .
725+
" -h " . escapeshellarg((string) $dbOptions->host) .
726+
" --port=" . escapeshellarg((string) $dbOptions->port) .
727+
" --ignore-table=" . escapeshellarg($dbOptions->dbname . ".onsite_activity_view") .
719728
" --hex-blob --opt --quote-names --skip-comments --no-tablespaces $mysql_ssl " .
720-
escapeshellarg((string) $sqlconf["dbase"]) . " $tables";
729+
escapeshellarg($dbOptions->dbname) . " $tables";
721730
}
722731
if (IS_WINDOWS) {
723732
# The Perl script differs in windows also.
@@ -729,11 +738,11 @@ function export_submit(step) {
729738
}
730739
}
731740

732-
$dumppfx = escapeshellcmd($mysql_dump_cmd) . " -u " . escapeshellarg((string) $sqlconf["login"]) .
733-
" -p" . escapeshellarg((string) $sqlconf["pass"]) .
734-
" -h " . escapeshellarg((string) $sqlconf["host"]) .
735-
" --port=" . escapeshellarg((string) $sqlconf["port"]) .
736-
" --ignore-table=" . escapeshellarg($sqlconf["dbase"] . ".onsite_activity_view") .
741+
$dumppfx = escapeshellcmd($mysql_dump_cmd) . " -u " . escapeshellarg($dbOptions->user) .
742+
" -p" . escapeshellarg($dbOptions->password) .
743+
" -h " . escapeshellarg((string) $dbOptions->host) .
744+
" --port=" . escapeshellarg((string) $dbOptions->port) .
745+
" --ignore-table=" . escapeshellarg($dbOptions->dbname . ".onsite_activity_view") .
737746
" --hex-blob --skip-opt --quote-names --no-tablespaces --complete-insert" .
738747
" --no-create-info --skip-comments $mysql_ssl";
739748

@@ -776,7 +785,7 @@ function export_submit(step) {
776785
# windows uses the & to join statements.
777786
$cmd .= $dumppfx . " --where=\"list_id = 'lists' AND option_id = '$listid' OR list_id = '$listid' " .
778787
"ORDER BY list_id != 'lists', seq, title\" " .
779-
escapeshellarg((string) $sqlconf["dbase"]) . " list_options";
788+
escapeshellarg($dbOptions->dbname) . " list_options";
780789
$cmd .= " >> " . escapeshellarg($EXPORT_FILE) . " & ";
781790
} else {
782791
$cmdarr[] = "echo 'DELETE FROM list_options WHERE list_id = \"" .
@@ -786,7 +795,7 @@ function export_submit(step) {
786795
$dumppfx . " --where='list_id = \"lists\" AND option_id = \"" .
787796
add_escape_custom($listid) . "\" OR list_id = \"" .
788797
add_escape_custom($listid) . "\" " . "ORDER BY list_id != \"lists\", seq, title' " .
789-
escapeshellarg((string) $sqlconf["dbase"]) . " list_options" .
798+
escapeshellarg($dbOptions->dbname) . " list_options" .
790799
" >> " . escapeshellarg($EXPORT_FILE) . ";";
791800
}
792801
}
@@ -825,17 +834,17 @@ function export_submit(step) {
825834
if (IS_WINDOWS) {
826835
# windows uses the & to join statements.
827836
$cmd .= $dumppfx . ' --where="grp_form_id = \'' . add_escape_custom($layoutid) . "'\" " .
828-
escapeshellarg((string) $sqlconf["dbase"]) . " layout_group_properties";
837+
escapeshellarg($dbOptions->dbname) . " layout_group_properties";
829838
$cmd .= " >> " . escapeshellarg($EXPORT_FILE) . " & ";
830839
$cmd .= $dumppfx . ' --where="form_id = \'' . add_escape_custom($layoutid) . '\' ORDER BY group_id, seq, title" ' .
831-
escapeshellarg((string) $sqlconf["dbase"]) . " layout_options" ;
840+
escapeshellarg($dbOptions->dbname) . " layout_options" ;
832841
$cmd .= " >> " . escapeshellarg($EXPORT_FILE) . " & ";
833842
} else {
834843
$cmd .= $dumppfx . " --where='grp_form_id = \"" . add_escape_custom($layoutid) . "\"' " .
835-
escapeshellarg((string) $sqlconf["dbase"]) . " layout_group_properties";
844+
escapeshellarg($dbOptions->dbname) . " layout_group_properties";
836845
$cmd .= " >> " . escapeshellarg($EXPORT_FILE) . ";";
837846
$cmd .= $dumppfx . " --where='form_id = \"" . add_escape_custom($layoutid) . "\" ORDER BY group_id, seq, title' " .
838-
escapeshellarg((string) $sqlconf["dbase"]) . " layout_options" ;
847+
escapeshellarg($dbOptions->dbname) . " layout_options" ;
839848
$cmd .= " >> " . escapeshellarg($EXPORT_FILE) . ";";
840849
}
841850
// History and demographics exports will get special treatment.
@@ -940,12 +949,12 @@ function export_submit(step) {
940949
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $EXPORT_FILE)) {
941950
$form_status .= xl('Applying') . "...||br-placeholder||";
942951
echo brCustomPlaceholder(text($form_status));
943-
$cmd = escapeshellcmd($mysql_cmd) . " -u " . escapeshellarg((string) $sqlconf["login"]) .
944-
" -p" . escapeshellarg((string) $sqlconf["pass"]) .
945-
" -h " . escapeshellarg((string) $sqlconf["host"]) .
946-
" --port=" . escapeshellarg((string) $sqlconf["port"]) .
952+
$cmd = escapeshellcmd($mysql_cmd) . " -u " . escapeshellarg($dbOptions->user) .
953+
" -p" . escapeshellarg($dbOptions->password) .
954+
" -h " . escapeshellarg((string) $dbOptions->host) .
955+
" --port=" . escapeshellarg((string) $dbOptions->port) .
947956
" $mysql_ssl " .
948-
escapeshellarg((string) $sqlconf["dbase"]) .
957+
escapeshellarg($dbOptions->dbname) .
949958
" < " . escapeshellarg($EXPORT_FILE);
950959
} else {
951960
echo xlt('Internal error accessing uploaded file!');
@@ -987,13 +996,13 @@ function export_submit(step) {
987996
$res = sqlStatement("create table if not exists api_log_new like api_log");
988997
$res = sqlStatement("rename table api_log to api_log_backup, api_log_new to api_log");
989998
echo "<br />";
990-
$cmd = escapeshellcmd($mysql_dump_cmd) . " -u " . escapeshellarg((string) $sqlconf["login"]) .
991-
" -p" . escapeshellarg((string) $sqlconf["pass"]) .
992-
" -h " . escapeshellarg((string) $sqlconf["host"]) .
993-
" --port=" . escapeshellarg((string) $sqlconf["port"]) .
994-
" --ignore-table=" . escapeshellarg($sqlconf["dbase"] . ".onsite_activity_view") .
999+
$cmd = escapeshellcmd($mysql_dump_cmd) . " -u " . escapeshellarg($dbOptions->user) .
1000+
" -p" . escapeshellarg($dbOptions->password) .
1001+
" -h " . escapeshellarg((string) $dbOptions->host) .
1002+
" --port=" . escapeshellarg((string) $dbOptions->port) .
1003+
" --ignore-table=" . escapeshellarg($dbOptions->dbname . ".onsite_activity_view") .
9951004
" --hex-blob --opt --quote-names --no-tablespaces -r " . escapeshellarg($BACKUP_EVENTLOG_FILE) . " $mysql_ssl " .
996-
escapeshellarg((string) $sqlconf["dbase"]) . " --tables log_comment_encrypt_backup log_backup api_log_backup";
1005+
escapeshellarg($dbOptions->dbname) . " --tables log_comment_encrypt_backup log_backup api_log_backup";
9971006
# Set Eventlog Flag when it is done
9981007
$eventlog = 1;
9991008
// 301 If ends here.

0 commit comments

Comments
 (0)