Skip to content
120 changes: 120 additions & 0 deletions docker/openemr/8.0.1/auto_import_codes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#!/usr/bin/env php
<?php
/**
* =======================================
* OpenEMR Automated Code Import
* =======================================
* This script walks through a directory tree up to one level to find archives of Code System databases.
*
* The import limit here is dictated by available functionality in OpenEMR. Currently, expect to import RXNORM,
* SNOMED, ICD9, ICD10 CM, ICD10 PCS, CQM_VALUESET, and any arbitrary dataset that conforms to the VALUESET format.
*
* Usage:
* php auto_import_codes.php [dir_root]
*
* Example:
* php auto_import_codes.php
* php auto_import_codes.php codes
* ============================================================================
* @package OpenEMR
* @link https://www.open-emr.org
* @author Luis M. Santos, MD <lsantos@medicalmasses.com>
* @copyright Copyright (c) 2026 Luis M. Santos, MD <lsantos@medicalmasses.com>
* @copyright Copyright (c) 2026 MedicalMasses L.L.C. <https://medicalmasses.com>
* @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
*/
$sitePath = '/var/www/localhost/htdocs/openemr';
$_GET['site'] = 'default';
$ignoreAuth = true;
$sessionAllowWrite = true;
chdir($sitePath);

// Load OpenEMR's Composer autoloader
// This gives us access to all OpenEMR classes, including the Installer class
require_once 'interface/globals.php';
require_once 'library/standard_tables_capture.inc.php';

function import_dir(string $type, $importFunction): void {
foreach (glob("*.zip") as $file) {
# Copy to temp
echo " [" . $type . "] Copying file => " . $file . "!\n";
if (!temp_copy($file, $type)) {
error_log("Failed to copy " . $file . " of type " . $type);
return;
}

# Unpack
echo " [" . $type . "] Uncompressing file => " . $file . "!\n";
if (!temp_unarchive($file, $type)) {
error_log("Failed to unzip " . $file . " of type " . $type);
}

# Import data
echo " [" . $type . "] Importing file => " . $file . "!\n";
$importFunction($type);

# Cleanup
echo " [" . $type . "] Cleaning up import for file => " . $file . "!\n";
temp_dir_cleanup($type);
}
}

function import_snomed(string $path): void {
// TODO: Consider including auto detection in OpenEMR at a later date.
try {
snomedRF2_import();
} catch (Exception $e) {
try {
snomed_import(true);
} catch (Exception $e) {
snomed_import();
}
}
}

function import(string $path): void {
# Change to import directory
chdir($path);

# Scan directory
$dirs = scandir('./');
echo "Available directories => ". $dirs . "\n";
foreach ($dirs as $dir) {
if ($dir == "." || $dir == "..") {
continue;
}

if(is_dir($dir)) {
# Go into directory
echo "Entering directory => ". $dir . "\n";
chdir($dir);

match ($dir) {
"icd9" => import_dir("ICD9", function ($type) {icd_import($type);}),
"icd10" => import_dir("ICD10", function ($type) {icd_import($type);}),
"rxnorm" => import_dir("RXNORM", function () {rxnorm_import(false);}),
"snomed" => import_dir("SNOMED", function ($file) {import_snomed($file);}),
"cqm", "cqm_valueset" => import_dir("CQM_VALUESET", function ($type) {valueset_import($type);}),
default => import_dir("VALUESET", function ($type) {valueset_import($type);}),
};

# Restore parent path for the next iteration
echo "Exiting directory => ". $dir . " back to ". $path . "\n";
chdir($path);
}
}
}

// Ensure we're running from CLI
if (php_sapi_name() !== 'cli') {
throw RuntimeException('This tool can only be run from the command line');
}

$contribPath = realpath($sitePath . '/contrib');
if ($argc > 1) {
if (strlen($argv[1])) {
$contribPath = realpath($argv[1]);
}
}

import($contribPath);
3 changes: 2 additions & 1 deletion docker/openemr/8.1.0/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,9 @@ RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin -
# - Branch: --build-arg OPENEMR_VERSION=master
# - Tag: --build-arg OPENEMR_VERSION=v7.0.5
ARG OPENEMR_VERSION=rel-810
ARG OPENEMR_GIT=https://github.com/openemr/openemr.git
FROM base AS openemr-source
RUN git clone https://github.com/openemr/openemr.git --branch "${OPENEMR_VERSION}" --depth 1 \
RUN git clone "${OPENEMR_GIT}" --branch "${OPENEMR_VERSION}" --depth 1 \
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the off chance the repo name ends with something other than 'openemr', the directory created won't be named 'openemr'. So an explicit name would be good.

Copy link
Copy Markdown
Author

@luissantosHCIT luissantosHCIT Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll wait and update this once the other changes are merged. Thank you for the headsup!

One question (I am new to the project), why are the docker directories explicitly versioned as opposed to having a "latest" that gets backed up as the versioned directory prior to updating it further?

Thank you!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point @luissantosHCIT, that would be a simpler strategy to have the workflows use next and dev and then stamp them with the version upon release

it'll be worth thinking about moving there after we release 8.1.0 in about a month

&& rm -rf openemr/.git

# Stage 2: Install PHP dependencies (Composer)
Expand Down
9 changes: 9 additions & 0 deletions docker/openemr/binary/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ docker build -t openemr-binary:latest .
### Build Arguments

- `OPENEMR_VERSION`: OpenEMR version (default: `7_0_4`)
- `OPENEMR_GIT`: OpenEMR git repository to build from (default: `https://github.com/openemr/openemr.git`)
- `BINARY_RELEASE_DATE`: Release date for binary package (default: `12282025`)
- `PHP_VERSION`: PHP version used in binaries (default: `8.5`)
- `ALPINE_VERSION`: Alpine Linux version (default: `3.22`)
Expand All @@ -37,6 +38,14 @@ docker build \
-t openemr-binary:latest .
```

```bash
docker build \
--build-arg OPENEMR_GIT=https://github.com/myuser/openemr.git \
--build-arg OPENEMR_VERSION=7_0_4 \
--build-arg BINARY_RELEASE_DATE=12292025 \
-t openemr-binary:latest .
```

## Usage

### Basic Usage with docker-compose
Expand Down
120 changes: 120 additions & 0 deletions docker/openemr/flex/auto_import_codes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#!/usr/bin/env php
<?php
/**
* =======================================
* OpenEMR Automated Code Import
* =======================================
* This script walks through a directory tree up to one level to find archives of Code System databases.
*
* The import limit here is dictated by available functionality in OpenEMR. Currently, expect to import RXNORM,
* SNOMED, ICD9, ICD10 CM, ICD10 PCS, CQM_VALUESET, and any arbitrary dataset that conforms to the VALUESET format.
*
* Usage:
* php auto_import_codes.php [dir_root]
*
* Example:
* php auto_import_codes.php
* php auto_import_codes.php codes
* ============================================================================
* @package OpenEMR
* @link https://www.open-emr.org
* @author Luis M. Santos, MD <lsantos@medicalmasses.com>
* @copyright Copyright (c) 2026 Luis M. Santos, MD <lsantos@medicalmasses.com>
* @copyright Copyright (c) 2026 MedicalMasses L.L.C. <https://medicalmasses.com>
* @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
*/
$sitePath = '/var/www/localhost/htdocs/openemr';
$_GET['site'] = 'default';
$ignoreAuth = true;
$sessionAllowWrite = true;
chdir($sitePath);

// Load OpenEMR's Composer autoloader
// This gives us access to all OpenEMR classes, including the Installer class
require_once 'interface/globals.php';
require_once 'library/standard_tables_capture.inc.php';

function import_dir(string $type, $importFunction): void {
foreach (glob("*.zip") as $file) {
# Copy to temp
echo " [" . $type . "] Copying file => " . $file . "!\n";
if (!temp_copy($file, $type)) {
error_log("Failed to copy " . $file . " of type " . $type);
return;
}

# Unpack
echo " [" . $type . "] Uncompressing file => " . $file . "!\n";
if (!temp_unarchive($file, $type)) {
error_log("Failed to unzip " . $file . " of type " . $type);
}

# Import data
echo " [" . $type . "] Importing file => " . $file . "!\n";
$importFunction($type);

# Cleanup
echo " [" . $type . "] Cleaning up import for file => " . $file . "!\n";
temp_dir_cleanup($type);
}
}

function import_snomed(string $path): void {
// TODO: Consider including auto detection in OpenEMR at a later date.
try {
snomedRF2_import();
} catch (Exception $e) {
try {
snomed_import(true);
} catch (Exception $e) {
snomed_import();
}
}
}

function import(string $path): void {
# Change to import directory
chdir($path);

# Scan directory
$dirs = scandir('./');
echo "Available directories => ". $dirs . "\n";
foreach ($dirs as $dir) {
if ($dir == "." || $dir == "..") {
continue;
}

if(is_dir($dir)) {
# Go into directory
echo "Entering directory => ". $dir . "\n";
chdir($dir);

match ($dir) {
"icd9" => import_dir("ICD9", function ($type) {icd_import($type);}),
"icd10" => import_dir("ICD10", function ($type) {icd_import($type);}),
"rxnorm" => import_dir("RXNORM", function () {rxnorm_import(false);}),
"snomed" => import_dir("SNOMED", function ($file) {import_snomed($file);}),
"cqm", "cqm_valueset" => import_dir("CQM_VALUESET", function ($type) {valueset_import($type);}),
default => import_dir("VALUESET", function ($type) {valueset_import($type);}),
};

# Restore parent path for the next iteration
echo "Exiting directory => ". $dir . " back to ". $path . "\n";
chdir($path);
}
}
}

// Ensure we're running from CLI
if (php_sapi_name() !== 'cli') {
throw RuntimeException('This tool can only be run from the command line');
}

$contribPath = realpath($sitePath . '/contrib');
if ($argc > 1) {
if (strlen($argv[1])) {
$contribPath = realpath($argv[1]);
}
}

import($contribPath);