diff --git a/.github/workflows/isolated-tests.yml b/.github/workflows/isolated-tests.yml index 6f6ae963b9f5..f492b0b412d1 100644 --- a/.github/workflows/isolated-tests.yml +++ b/.github/workflows/isolated-tests.yml @@ -77,10 +77,23 @@ jobs: --coverage-html=htmlcov \ --testdox + - name: Check if coverage files exist + if: ${{ (success() || failure()) }} + id: check-files + run: | + echo "clover_exists=$(test -f clover.xml && echo true || echo false)" >> $GITHUB_OUTPUT + echo "htmlcov_exists=$(test -d ./htmlcov && echo true || echo false)" >> $GITHUB_OUTPUT - name: Upload coverage reports + if: ${{ steps.check-files.outputs.clover_exists == 'true' && steps.check-files.outputs.html_exists == 'true' && (success() || failure()) }} uses: actions/upload-artifact@v4 with: name: coverage-isolated-tests-php-${{ matrix.php-version }} path: | clover.xml htmlcov/ + - name: Upload coverage reports to Codecov + if: ${{ steps.check-files.outputs.clover_exists == 'true' && (success() || failure()) }} + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: clover.xml diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml index c0fc1a193e0f..92839da0c9d0 100644 --- a/.github/workflows/shellcheck.yml +++ b/.github/workflows/shellcheck.yml @@ -61,7 +61,7 @@ jobs: # if only the workflow file itself is changed in a PR. # Thus we validate changes to the workflow file. continue-on-error: true - uses: tj-actions/changed-files@v46 + uses: tj-actions/changed-files@v47 with: # Keep the paths in sync with the paths in the on.push and on.pull_request sections # See https://github.com/tj-actions/changed-files/blob/v46/README.md#inputs-%EF%B8%8F diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 869c2af01943..c2a2caf52e6c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -305,9 +305,9 @@ jobs: with: name: htmlcov path: ./htmlcov/ - # - name: Upload coverage reports to Codecov - # if: ${{ env.ENABLE_COVERAGE == 'true' && steps.check-files.outputs.clover_exists == 'true' && (success() || failure()) }} - # uses: codecov/codecov-action@v5 - # with: - # token: ${{ secrets.CODECOV_TOKEN }} - # files: coverage.clover.xml + - name: Upload coverage reports to Codecov + if: ${{ env.ENABLE_COVERAGE == 'true' && steps.check-files.outputs.clover_exists == 'true' && (success() || failure()) }} + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: coverage.clover.xml diff --git a/API_README.md b/API_README.md index 32ff80b4f08a..c70ae1b5c986 100644 --- a/API_README.md +++ b/API_README.md @@ -448,11 +448,10 @@ REST API endpoints are defined in the [primary routes file](_rest_routes.inc.php endpoint to the OpenEMR controller which handles the request, and also handles the JSON data conversions. ```php -"POST /api/patient" => function () { - RestConfig::authorization_check("patients", "demo"); +"POST /api/patient" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "demo"); $data = (array) (json_decode(file_get_contents("php://input"))); $return = (new PatientRestController())->post($data); - RestConfig::apiLog($return, $data); return $return; } ``` diff --git a/FHIR_README.md b/FHIR_README.md index c66065c924ca..48b3a3c4f7bd 100644 --- a/FHIR_README.md +++ b/FHIR_README.md @@ -73,7 +73,7 @@ When registering an API client to use with Swagger the following for the redirec Request: ```sh -curl -X GET 'https://localhost:9300/apis/fhir/Patient' \ +curl -X GET 'https://localhost:9300/apis/default/fhir/Patient' \ -H 'Authorization: Bearer eyJ0b2tlbiI6IjAwNnZ3eGJZYmFrOXlxUjF4U290Y1g4QVVDd3JOcG5yYXZEaFlqaHFjWXJXRGNDQUtFZmJONkh2cElTVkJiaWFobHBqOTBYZmlNRXpiY2FtU01pSHk1UzFlMmgxNmVqZEhcL1ZENlNtaVpTRFRLMmtsWDIyOFRKZzNhQmxMdUloZmNJM3FpMGFKZ003OXdtOGhYT3dpVkx5b3BFRXQ1TlNYNTE3UW5TZ0dsUVdQbG56WjVxOVYwc21tdDlSQ3RvcDV3TEkiLCJzaXRlX2lkIjoiZGVmYXVsdCIsImFwaSI6ImZoaXIifQ==' ``` @@ -246,9 +246,8 @@ endpoint to the OpenEMR FHIR controller which handles the request, and also hand ```php "GET /fhir/Patient" => function () { - RestConfig::authorization_check("patients", "demo"); + RestConfig::request_authorization_check($request, "patients", "demo"); $return = (new FhirPatientRestController())->getAll($_GET); - RestConfig::apiLog($return); return $return; } ``` diff --git a/README-Isolated-Testing.md b/README-Isolated-Testing.md index 88d1a35c9126..f5763beb2f16 100644 --- a/README-Isolated-Testing.md +++ b/README-Isolated-Testing.md @@ -108,4 +108,4 @@ The isolated bootstrap only loads: - **Fast**: No database connection overhead - **Reliable**: No external service dependencies - **Portable**: Runs in any environment with PHP and Composer -- **Isolated**: Tests don't affect each other through shared database state \ No newline at end of file +- **Isolated**: Tests don't affect each other through shared database state diff --git a/README.md b/README.md index e47d2f6f6b25..d1501516140b 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ [![PHPStan](https://github.com/openemr/openemr/actions/workflows/phpstan.yml/badge.svg)](https://github.com/openemr/openemr/actions/workflows/phpstan.yml) [![Rector](https://github.com/openemr/openemr/actions/workflows/rector.yml/badge.svg)](https://github.com/openemr/openemr/actions/workflows/rector.yml) [![ShellCheck](https://github.com/openemr/openemr/actions/workflows/shellcheck.yml/badge.svg)](https://github.com/openemr/openemr/actions/workflows/shellcheck.yml) +[![codecov](https://codecov.io/gh/openemr/openemr/graph/badge.svg?token=7Eu3U1Ozdq)](https://codecov.io/gh/openemr/openemr) [![Backers on Open Collective](https://opencollective.com/openemr/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/openemr/sponsors/badge.svg)](#sponsors) diff --git a/_rest_config.php b/_rest_config.php deleted file mode 100644 index b9a1edfa1a4e..000000000000 --- a/_rest_config.php +++ /dev/null @@ -1,600 +0,0 @@ - - * @author Brady Miller - * @copyright Copyright (c) 2018-2020 Jerry Padgett - * @copyright Copyright (c) 2019 Brady Miller - * @copyright Copyright (c) 2024 Care Management Solutions, Inc. - * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 - */ - -// Need access to classes, so run autoloader now instead of in globals.php. -$GLOBALS['already_autoloaded'] = true; -require_once __DIR__ . '/vendor/autoload.php'; - -use Laminas\HttpHandlerRunner\Emitter\SapiEmitter; -use League\OAuth2\Server\Exception\OAuthServerException; -use League\OAuth2\Server\ResourceServer; -use Nyholm\Psr7\Factory\Psr17Factory; -use Nyholm\Psr7Server\ServerRequestCreator; -use OpenEMR\Common\Acl\AclMain; -use OpenEMR\Common\Auth\OpenIDConnect\Repositories\AccessTokenRepository; -use OpenEMR\Common\Http\HttpRestRequest; -use OpenEMR\Common\Logging\EventAuditLogger; -use OpenEMR\Common\Logging\SystemLogger; -use OpenEMR\Common\Session\SessionUtil; -use OpenEMR\FHIR\Config\ServerConfig; -use OpenEMR\Services\TrustedUserService; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; - - -// also a handy place to add utility methods -// TODO before v6 release: refactor http_response_code(); for psr responses. -// -class RestConfig -{ - /** @var routemap is an array of patterns and routes */ - public static $ROUTE_MAP; - - /** @var fhir routemap is an of patterns and routes */ - public static $FHIR_ROUTE_MAP; - - /** @var portal routemap is an of patterns and routes */ - public static $PORTAL_ROUTE_MAP; - - /** @var app root is the root directory of the application */ - public static $APP_ROOT; - - /** @var root url of the application */ - public static $ROOT_URL; - // you can guess what the rest are! - public static $VENDOR_DIR; - public static $SITE; - public static $apisBaseFullUrl; - public static $webserver_root; - public static $web_root; - public static $server_document_root; - public static $publicKey; - private static $INSTANCE; - private static $IS_INITIALIZED = false; - /** @var set to true if local api call */ - private static $localCall = false; - /** @var set to true if not rest call */ - private static $notRestCall = false; - - /** prevents external construction */ - private function __construct() - { - } - - /** - * Returns an instance of the RestConfig singleton - * - * @return RestConfig - */ - public static function GetInstance(): \RestConfig - { - if (!self::$IS_INITIALIZED) { - self::Init(); - } - - if (!self::$INSTANCE instanceof self) { - self::$INSTANCE = new self(); - } - - return self::$INSTANCE; - } - - /** - * Initialize the RestConfig object - */ - public static function Init(): void - { - if (self::$IS_INITIALIZED) { - return; - } - // The busy stuff. - self::setPaths(); - self::setSiteFromEndpoint(); - $serverConfig = new ServerConfig(); - $serverConfig->setWebServerRoot(self::$webserver_root); - $serverConfig->setSiteId(self::$SITE); - self::$ROOT_URL = self::$web_root . "/apis"; - self::$VENDOR_DIR = self::$webserver_root . "/vendor"; - self::$publicKey = $serverConfig->getPublicRestKey(); - self::$IS_INITIALIZED = true; - } - - /** - * Basic paths when GLOBALS are not yet available. - * - * @return void - */ - private static function SetPaths(): void - { - $isWindows = (stripos(PHP_OS_FAMILY, 'WIN') === 0); - // careful if moving this class to modify where's root. - self::$webserver_root = __DIR__; - if ($isWindows) { - //convert windows path separators - self::$webserver_root = str_replace("\\", "/", self::$webserver_root); - } - // Collect the apache server document root (and convert to windows slashes, if needed) - self::$server_document_root = realpath($_SERVER['DOCUMENT_ROOT']); - if ($isWindows) { - //convert windows path separators - self::$server_document_root = str_replace("\\", "/", self::$server_document_root); - } - self::$web_root = substr(self::$webserver_root, strspn(self::$webserver_root ^ self::$server_document_root, "\0")); - // Ensure web_root starts with a path separator - if (preg_match("/^[^\/]/", self::$web_root)) { - self::$web_root = "/" . self::$web_root; - } - // Will need these occasionally. sql init comes to mind! - $GLOBALS['rootdir'] = self::$web_root . "/interface"; - // Absolute path to the source code include and headers file directory (Full path): - $GLOBALS['srcdir'] = self::$webserver_root . "/library"; - // Absolute path to the location of documentroot directory for use with include statements: - $GLOBALS['fileroot'] = self::$webserver_root; - // Absolute path to the location of interface directory for use with include statements: - $GLOBALS['incdir'] = self::$webserver_root . "/interface"; - // Absolute path to the location of documentroot directory for use with include statements: - $GLOBALS['webroot'] = self::$web_root; - // Static assets directory, relative to the webserver root. - $GLOBALS['assets_static_relative'] = self::$web_root . "/public/assets"; - // Relative themes directory, relative to the webserver root. - $GLOBALS['themes_static_relative'] = self::$web_root . "/public/themes"; - // Relative images directory, relative to the webserver root. - $GLOBALS['images_static_relative'] = self::$web_root . "/public/images"; - // Static images directory, absolute to the webserver root. - $GLOBALS['images_static_absolute'] = self::$webserver_root . "/public/images"; - //Composer vendor directory, absolute to the webserver root. - $GLOBALS['vendor_dir'] = self::$webserver_root . "/vendor"; - } - - private static function setSiteFromEndpoint(): void - { - // Get site from endpoint if available. Unsure about this though! - // Will fail during sql init otherwise. - $endPointParts = self::parseEndPoint(self::getRequestEndPoint()); - if (count($endPointParts) > 1) { - $site_id = $endPointParts[0] ?? ''; - if ($site_id) { - self::$SITE = $site_id; - } - } - } - - public static function parseEndPoint($resource): array - { - if ($resource[0] === '/') { - $resource = substr($resource, 1); - } - return explode('/', $resource); - } - - public static function getRequestEndPoint(): string - { - $resource = null; - if (!empty($_REQUEST['_REWRITE_COMMAND'])) { - $resource = "/" . $_REQUEST['_REWRITE_COMMAND']; - } elseif (!empty($_SERVER['REDIRECT_QUERY_STRING'])) { - $resource = str_replace('_REWRITE_COMMAND=', '/', $_SERVER['REDIRECT_QUERY_STRING']); - } else { - if (!empty($_SERVER['REQUEST_URI'])) { - if (strpos($_SERVER['REQUEST_URI'], '?') > 0) { - $resource = strstr($_SERVER['REQUEST_URI'], '?', true); - } else { - $resource = str_replace(self::$ROOT_URL ?? '', '', $_SERVER['REQUEST_URI']); - } - } - } - - return $resource; - } - - public static function verifyAccessToken() - { - $logger = new SystemLogger(); - $response = self::createServerResponse(); - $request = self::createServerRequest(); - try { - // if we there's a key problem need to catch the exception - $server = new ResourceServer( - new AccessTokenRepository(), - self::$publicKey - ); - $raw = $server->validateAuthenticatedRequest($request); - } catch (OAuthServerException $exception) { - $logger->error("RestConfig->verifyAccessToken() OAuthServerException", ["message" => $exception->getMessage()]); - return $exception->generateHttpResponse($response); - } catch (\Exception $exception) { - if ($exception instanceof LogicException) { - $logger->error( - "RestConfig->verifyAccessToken() LogicException, likely oauth2 public key is missing, corrupted, or misconfigured", - ["message" => $exception->getMessage()] - ); - return (new OAuthServerException("Invalid access token", 0, 'invalid_token', 401)) - ->generateHttpResponse($response); - } else { - $logger->error("RestConfig->verifyAccessToken() Exception", ["message" => $exception->getMessage()]); - // do NOT reveal what happened at the server level if we have a server exception - return (new OAuthServerException("Server Error", 0, 'unknown_error', 500)) - ->generateHttpResponse($response); - } - } - - return $raw; - } - - /** - * Returns true if the access token for the given token id is valid. Otherwise returns the access denied response. - * @param $tokenId - * @return bool|ResponseInterface - */ - public static function validateAccessTokenRevoked($tokenId) - { - $repository = new AccessTokenRepository(); - if ($repository->isAccessTokenRevokedInDatabase($tokenId)) { - $response = self::createServerResponse(); - return OAuthServerException::accessDenied('Access token has been revoked')->generateHttpResponse($response); - } - return true; - } - - public static function isTrustedUser($clientId, $userId) - { - $trustedUserService = new TrustedUserService(); - $response = self::createServerResponse(); - try { - if (!$trustedUserService->isTrustedUser($clientId, $userId)) { - (new SystemLogger())->debug( - "invalid Trusted User. Refresh Token revoked or logged out", - ['clientId' => $clientId, 'userId' => $userId] - ); - throw new OAuthServerException('Refresh Token revoked or logged out', 0, 'invalid _request', 400); - } - return $trustedUserService->getTrustedUser($clientId, $userId); - } catch (OAuthServerException $exception) { - return $exception->generateHttpResponse($response); - } catch (\Exception $exception) { - return (new OAuthServerException($exception->getMessage(), 0, 'unknown_error', 500)) - ->generateHttpResponse($response); - } - } - - public static function createServerResponse(): ResponseInterface - { - $psr17Factory = new Psr17Factory(); - - return $psr17Factory->createResponse(); - } - - public static function createServerRequest(): ServerRequestInterface - { - $psr17Factory = new Psr17Factory(); - $creator = new ServerRequestCreator( - $psr17Factory, // ServerRequestFactory - $psr17Factory, // UriFactory - $psr17Factory, // UploadedFileFactory - $psr17Factory // StreamFactory - ); - - return $creator->fromGlobals(); - } - - public static function destroySession(): void - { - SessionUtil::apiSessionCookieDestroy(); - } - - public static function getPostData($data) - { - if (count($_POST)) { - return $_POST; - } - - if ($post_data = file_get_contents('php://input')) { - if ($post_json = json_decode($post_data, true)) { - return $post_json; - } - parse_str($post_data, $post_variables); - if (count($post_variables)) { - return $post_variables; - } - } - - return null; - } - - public static function authorization_check($section, $value, $user = '', $aclPermission = ''): void - { - $result = AclMain::aclCheckCore($section, $value, $user, $aclPermission); - if (!$result) { - if (!self::$notRestCall) { - http_response_code(401); - } - exit(); - } - } - - // Main function to check scope - // Use cases: - // Only sending $scopeType would be for something like 'openid' - // For using all 3 parameters would be for something like 'user/Organization.write' - // $scopeType = 'user', $resource = 'Organization', $permission = 'write' - public static function scope_check($scopeType, $resource = null, $permission = null): void - { - if (!empty($GLOBALS['oauth_scopes'])) { - // Need to ensure has scope - if (empty($resource)) { - // Simply check to see if $scopeType is an allowed scope - $scope = $scopeType; - } else { - // Resource scope check - $scope = $scopeType . '/' . $resource . '.' . $permission; - } - if (!in_array($scope, $GLOBALS['oauth_scopes'])) { - (new SystemLogger())->debug("RestConfig::scope_check scope not in access token", ['scope' => $scope, 'scopes_granted' => $GLOBALS['oauth_scopes']]); - http_response_code(401); - exit; - } - } else { - (new SystemLogger())->error("RestConfig::scope_check global scope array is empty"); - http_response_code(401); - exit; - } - } - - public static function setLocalCall(): void - { - self::$localCall = true; - } - - public static function setNotRestCall(): void - { - self::$notRestCall = true; - } - - public static function is_fhir_request($resource): bool - { - return stripos(strtolower($resource), "/fhir/") !== false; - } - - public static function is_portal_request($resource): bool - { - return stripos(strtolower($resource), "/portal/") !== false; - } - - public static function is_api_request($resource): bool - { - return stripos(strtolower($resource), "/api/") !== false; - } - - public static function skipApiAuth($resource): bool - { - if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { - // we don't authenticate OPTIONS requests - return true; - } - - // ensure 1) sane site and 2) ensure the site exists on filesystem before even considering for skip api auth - if (empty(self::$SITE) || preg_match('/[^A-Za-z0-9\\-.]/', self::$SITE) || !file_exists(__DIR__ . '/sites/' . self::$SITE)) { - error_log("OpenEMR Error - api site error, so forced exit"); - http_response_code(400); - exit(); - } - // let the capability statement for FHIR or the SMART-on-FHIR through - $resource = str_replace('/' . self::$SITE, '', $resource); - if ( - // TODO: @adunsulag we need to centralize our auth skipping logic... as we have this duplicated in HttpRestRouteHandler - // however, at the point of this method we don't have the resource identified and haven't gone through our parsing - // routine to handle that logic... - $resource === ("/fhir/metadata") || - $resource === ("/fhir/.well-known/smart-configuration") || - // skip list and single instance routes - 0 === strpos("/fhir/OperationDefinition", $resource) - ) { - return true; - } else { - return false; - } - } - - public static function apiLog($response = '', $requestBody = ''): void - { - $logResponse = $response; - - // only log when using standard api calls (skip when using local api calls from within OpenEMR) - // and when api log option is set - if (!$GLOBALS['is_local_api'] && !self::$notRestCall && $GLOBALS['api_log_option']) { - if ($GLOBALS['api_log_option'] == 1) { - // Do not log the response and requestBody - $logResponse = ''; - $requestBody = ''; - } - if ($response instanceof ResponseInterface) { - if (self::shouldLogResponse($response)) { - $body = $response->getBody(); - $logResponse = $body->getContents(); - $body->rewind(); - } else { - $logResponse = 'Content not application/json - Skip binary data'; - } - } else { - $logResponse = (!empty($logResponse)) ? json_encode($response) : ''; - } - - // convert pertinent elements to json - $requestBody = (!empty($requestBody)) ? json_encode($requestBody) : ''; - - // prepare values and call the log function - $event = 'api'; - $category = 'api'; - $method = $_SERVER['REQUEST_METHOD']; - $url = $_SERVER['REQUEST_URI']; - $patientId = (int)($_SESSION['pid'] ?? 0); - $userId = (int)($_SESSION['authUserID'] ?? 0); - $api = [ - 'user_id' => $userId, - 'patient_id' => $patientId, - 'method' => $method, - 'request' => $GLOBALS['resource'], - 'request_url' => $url, - 'request_body' => $requestBody, - 'response' => $logResponse - ]; - if ($patientId === 0) { - $patientId = null; //entries in log table are blank for no patient_id, whereas in api_log are 0, which is why above $api value uses 0 when empty - } - EventAuditLogger::instance()->recordLogItem(1, $event, ($_SESSION['authUser'] ?? ''), ($_SESSION['authProvider'] ?? ''), 'api log', $patientId, $category, 'open-emr', null, null, '', $api); - } - } - - public static function emitResponse($response, $build = false): void - { - if (headers_sent()) { - throw new RuntimeException('Headers already sent.'); - } - $statusLine = sprintf( - 'HTTP/%s %s %s', - $response->getProtocolVersion(), - $response->getStatusCode(), - $response->getReasonPhrase() - ); - header($statusLine, true); - foreach ($response->getHeaders() as $name => $values) { - $responseHeader = sprintf('%s: %s', $name, $response->getHeaderLine($name)); - header($responseHeader, false); - } - echo $response->getBody(); - } - - /** - * If the FHIR System scopes enabled or not. True if its turned on, false otherwise. - * @return bool - */ - public static function areSystemScopesEnabled() - { - return $GLOBALS['rest_system_scopes_api'] === '1'; - } - - public function authenticateUserToken($tokenId, $clientId, $userId): bool - { - $ip = collectIpAddresses(); - - // check for token - $accessTokenRepo = new AccessTokenRepository(); - $authTokenExpiration = $accessTokenRepo->getTokenExpiration($tokenId, $clientId, $userId); - - if (empty($authTokenExpiration)) { - EventAuditLogger::instance()->newEvent('api', '', '', 0, "API failure: " . $ip['ip_string'] . ". Token not found for client[" . $clientId . "] and user " . $userId . "."); - return false; - } - - // Ensure token not expired (note an expired token should have already been caught by oauth2, however will also check here) - $currentDateTime = date("Y-m-d H:i:s"); - $expiryDateTime = date("Y-m-d H:i:s", strtotime($authTokenExpiration)); - if ($expiryDateTime <= $currentDateTime) { - EventAuditLogger::instance()->newEvent('api', '', '', 0, "API failure: " . $ip['ip_string'] . ". Token expired for client[" . $clientId . "] and user " . $userId . "."); - return false; - } - - // Token authentication passed - EventAuditLogger::instance()->newEvent('api', '', '', 1, "API success: " . $ip['ip_string'] . ". Token successfully used for client[" . $clientId . "] and user " . $userId . "."); - return true; - } - - /** - * Checks if we should log the response interface (we don't want to log binary documents or anything like that) - * We only log requests with a content-type of any form of json fhir+application/json or application/json - * @param ResponseInterface $response - * @return bool If the request should be logged, false otherwise - */ - private static function shouldLogResponse(ResponseInterface $response) - { - if ($response->hasHeader("Content-Type")) { - $contentType = $response->getHeaderLine("Content-Type"); - if ($contentType === 'application/json') { - return true; - } - } - - return false; - } - - /** - * Grabs all of the context information for the request's access token and populates any context variables the - * request needs (such as patient binding information). Returns the populated request - * @param HttpRestRequest $restRequest - * @return HttpRestRequest - */ - public function populateTokenContextForRequest(HttpRestRequest $restRequest) - { - - $context = $this->getTokenContextForRequest($restRequest); - // note that the context here is the SMART value that is returned in the response for an AccessToken in this - // case it is the patient value which is the logical id (ie uuid) of the patient. - $patientUuid = $context['patient'] ?? null; - if (!empty($patientUuid)) { - // we only set the bound patient access if the underlying user can still access the patient - if ($this->checkUserHasAccessToPatient($restRequest->getRequestUserId(), $patientUuid)) { - $restRequest->setPatientUuidString($patientUuid); - } else { - (new SystemLogger())->error("OpenEMR Error: api had patient launch scope but user did not have access to patient uuid." - . " Resources restricted with patient scopes will not return results"); - } - } else { - (new SystemLogger())->error("OpenEMR Error: api had patient launch scope but no patient was set in the " - . " session cache. Resources restricted with patient scopes will not return results"); - } - return $restRequest; - } - - public function getTokenContextForRequest(HttpRestRequest $restRequest) - { - $accessTokenRepo = new AccessTokenRepository(); - // note this is pretty confusing as getAccessTokenId comes from the oauth_access_id which is the token NOT - // the database id even though this is called accessTokenId.... - $token = $accessTokenRepo->getTokenByToken($restRequest->getAccessTokenId()); - $context = $token['context'] ?? "{}"; // if there is no populated context we just return an empty return - try { - return json_decode($context, true); - } catch (\Exception $exception) { - (new SystemLogger())->error("OpenEMR Error: failed to decode token context json", ['exception' => $exception->getMessage() - , 'tokenId' => $restRequest->getAccessTokenId()]); - } - return []; - } - - - /** - * Checks whether a user has access to the patient. Returns true if the user can access the given patient, false otherwise - * @param $userId The id from the users table that represents the user - * @param $patientUuid The uuid from the patient_data table that represents the patient - * @return bool True if has access, false otherwise - */ - private function checkUserHasAccessToPatient($userId, $patientUuid) - { - // TODO: the session should never be populated with the pid from the access token unless the user had access to - // it. However, if we wanted an additional check or if we wanted to fire off any kind of event that does - // patient filtering by provider / clinic we would handle that here. - return true; - } - - - /** prevents external cloning */ - private function __clone() - { - } -} - -// Include our routes and init routes global -// -require_once(__DIR__ . "/_rest_routes.inc.php"); diff --git a/_rest_routes.inc.php b/_rest_routes.inc.php index f985e7803221..a5ab0e41306c 100644 --- a/_rest_routes.inc.php +++ b/_rest_routes.inc.php @@ -19,6 +19,8 @@ * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ +use OpenEMR\RestControllers\Config\RestConfig; + /** * @OA\Info(title="OpenEMR API", version="7.0.4") * @OA\Server(url="/apis/default/") @@ -307,13663 +309,14 @@ // Lets keep our controller classes with the routes. // -use OpenEMR\Common\Acl\AccessDeniedException; -use OpenEMR\Common\Http\HttpRestRequest; -use OpenEMR\Common\Logging\SystemLogger; -use OpenEMR\Common\Uuid\UuidRegistry; -use OpenEMR\RestControllers\AllergyIntoleranceRestController; -use OpenEMR\RestControllers\AppointmentRestController; -use OpenEMR\RestControllers\ConditionRestController; -use OpenEMR\RestControllers\DocumentRestController; -use OpenEMR\RestControllers\DrugRestController; -use OpenEMR\RestControllers\EmployerRestController; -use OpenEMR\RestControllers\EncounterRestController; -use OpenEMR\RestControllers\FacilityRestController; -use OpenEMR\RestControllers\ImmunizationRestController; -use OpenEMR\RestControllers\InsuranceCompanyRestController; -use OpenEMR\RestControllers\InsuranceRestController; -use OpenEMR\RestControllers\ListRestController; -use OpenEMR\RestControllers\MessageRestController; -use OpenEMR\RestControllers\ONoteRestController; -use OpenEMR\RestControllers\PatientRestController; -use OpenEMR\RestControllers\PractitionerRestController; -use OpenEMR\RestControllers\PrescriptionRestController; -use OpenEMR\RestControllers\ProcedureRestController; -use OpenEMR\RestControllers\ProductRegistrationRestController; -use OpenEMR\RestControllers\RestControllerHelper; -use OpenEMR\RestControllers\TransactionRestController; -use OpenEMR\RestControllers\UserRestController; -use OpenEMR\RestControllers\VersionRestController; -use OpenEMR\Services\Search\SearchQueryConfig; // Note some Http clients may not send auth as json so a function // is implemented to determine and parse encoding on auth route's. // Note that the api route is only for users role // (there is a mechanism in place to ensure only user role can access the api route) -RestConfig::$ROUTE_MAP = array( - /** - * @OA\Get( - * path="/api/facility", - * description="Returns a single facility.", - * tags={"standard"}, - * @OA\Parameter( - * name="name", - * in="query", - * description="The name for the facility.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="facility_npi", - * in="query", - * description="The facility_npi for the facility.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="phone", - * in="query", - * description="The phone for the facility.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="fax", - * in="query", - * description="The fax for the facility.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="street", - * in="query", - * description="The street for the facility.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="city", - * in="query", - * description="The city for the facility.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="state", - * in="query", - * description="The state for the facility.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="postal_code", - * in="query", - * description="The postal_code for the facility.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="country_code", - * in="query", - * description="The country_code for the facility.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="federal_ein", - * in="query", - * description="The federal_ein for the facility.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="website", - * in="query", - * description="The website for the facility.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="email", - * in="query", - * description="The email for the facility.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="domain_identifier", - * in="query", - * description="The domain_identifier for the facility.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="facility_taxonomy", - * in="query", - * description="The facility_taxonomy for the facility.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="facility_code", - * in="query", - * description="The facility_code for the facility.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="billing_location", - * in="query", - * description="The billing_location setting for the facility.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="accepts_assignment", - * in="query", - * description="The accepts_assignment setting for the facility.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="oid", - * in="query", - * description="The oid for the facility.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="service_location", - * in="query", - * description="The service_location setting for the facility.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/facility" => function () { - RestConfig::authorization_check("admin", "users"); - $return = (new FacilityRestController())->getAll($_GET); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/facility/{fuuid}", - * description="Returns a single facility.", - * tags={"standard"}, - * @OA\Parameter( - * name="fuuid", - * in="path", - * description="The uuid for the facility.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/facility/:fuuid" => function ($fuuid) { - RestConfig::authorization_check("admin", "users"); - $return = (new FacilityRestController())->getOne($fuuid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Post( - * path="/api/facility", - * description="Creates a facility in the system", - * tags={"standard"}, - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="name", - * description="The name for the facility.", - * type="string" - * ), - * @OA\Property( - * property="facility_npi", - * description="The facility_npi for the facility.", - * type="string" - * ), - * @OA\Property( - * property="phone", - * description="The phone for the facility.", - * type="string" - * ), - * @OA\Property( - * property="fax", - * description="The fax for the facility.", - * type="string" - * ), - * @OA\Property( - * property="street", - * description="The street for the facility.", - * type="string" - * ), - * @OA\Property( - * property="city", - * description="The city for the facility.", - * type="string" - * ), - * @OA\Property( - * property="state", - * description="The state for the facility.", - * type="string" - * ), - * @OA\Property( - * property="postal_code", - * description="The postal_code for the facility.", - * type="string" - * ), - * @OA\Property( - * property="country_code", - * description="The country_code for the facility.", - * type="string" - * ), - * @OA\Property( - * property="federal_ein", - * description="The federal_ein for the facility.", - * type="string" - * ), - * @OA\Property( - * property="website", - * description="The website for the facility.", - * type="string" - * ), - * @OA\Property( - * property="email", - * description="The email for the facility.", - * type="string" - * ), - * @OA\Property( - * property="domain_identifier", - * description="The domain_identifier for the facility.", - * type="string" - * ), - * @OA\Property( - * property="facility_taxonomy", - * description="The facility_taxonomy for the facility.", - * type="string" - * ), - * @OA\Property( - * property="facility_code", - * description="The facility_code for the facility.", - * type="string" - * ), - * @OA\Property( - * property="billing_location", - * description="The billing_location setting for the facility.", - * type="string" - * ), - * @OA\Property( - * property="accepts_assignment", - * description="The accepts_assignment setting for the facility.", - * type="string" - * ), - * @OA\Property( - * property="oid", - * description="The oid for the facility.", - * type="string" - * ), - * @OA\Property( - * property="service_location", - * description="The service_location setting for the facility.", - * type="string" - * ), - * required={"name", "facility_npi"}, - * example={ - * "name": "Aquaria", - * "facility_npi": "123456789123", - * "phone": "808-606-3030", - * "fax": "808-606-3031", - * "street": "1337 Bit Shifter Ln", - * "city": "San Lorenzo", - * "state": "ZZ", - * "postal_code": "54321", - * "country_code": "US", - * "federal_ein": "4343434", - * "website": "https://example.com", - * "email": "foo@bar.com", - * "domain_identifier": "", - * "facility_taxonomy": "", - * "facility_code": "", - * "billing_location": "1", - * "accepts_assignment": "1", - * "oid": "", - * "service_location": "1" - * } - * ) - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "POST /api/facility" => function () { - RestConfig::authorization_check("admin", "super"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new FacilityRestController())->post($data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Put( - * path="/api/facility/{fuuid}", - * description="Updates a facility in the system", - * tags={"standard"}, - * @OA\Parameter( - * name="fuuid", - * in="path", - * description="The uuid for the facility.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="name", - * description="The name for the facility.", - * type="string" - * ), - * @OA\Property( - * property="facility_npi", - * description="The facility_npi for the facility.", - * type="string" - * ), - * @OA\Property( - * property="phone", - * description="The phone for the facility.", - * type="string" - * ), - * @OA\Property( - * property="fax", - * description="The fax for the facility.", - * type="string" - * ), - * @OA\Property( - * property="street", - * description="The street for the facility.", - * type="string" - * ), - * @OA\Property( - * property="city", - * description="The city for the facility.", - * type="string" - * ), - * @OA\Property( - * property="state", - * description="The state for the facility.", - * type="string" - * ), - * @OA\Property( - * property="postal_code", - * description="The postal_code for the facility.", - * type="string" - * ), - * @OA\Property( - * property="country_code", - * description="The country_code for the facility.", - * type="string" - * ), - * @OA\Property( - * property="federal_ein", - * description="The federal_ein for the facility.", - * type="string" - * ), - * @OA\Property( - * property="website", - * description="The website for the facility.", - * type="string" - * ), - * @OA\Property( - * property="email", - * description="The email for the facility.", - * type="string" - * ), - * @OA\Property( - * property="domain_identifier", - * description="The domain_identifier for the facility.", - * type="string" - * ), - * @OA\Property( - * property="facility_taxonomy", - * description="The facility_taxonomy for the facility.", - * type="string" - * ), - * @OA\Property( - * property="facility_code", - * description="The facility_code for the facility.", - * type="string" - * ), - * @OA\Property( - * property="billing_location", - * description="The billing_location setting for the facility.", - * type="string" - * ), - * @OA\Property( - * property="accepts_assignment", - * description="The accepts_assignment setting for the facility.", - * type="string" - * ), - * @OA\Property( - * property="oid", - * description="The oid for the facility.", - * type="string" - * ), - * @OA\Property( - * property="service_location", - * description="The service_location setting for the facility.", - * type="string" - * ), - * example={ - * "name": "Aquaria", - * "facility_npi": "123456789123", - * "phone": "808-606-3030", - * "fax": "808-606-3031", - * "street": "1337 Bit Shifter Ln", - * "city": "San Lorenzo", - * "state": "ZZ", - * "postal_code": "54321", - * "country_code": "US", - * "federal_ein": "4343434", - * "website": "https://example.com", - * "email": "foo@bar.com", - * "domain_identifier": "", - * "facility_taxonomy": "", - * "facility_code": "", - * "billing_location": "1", - * "accepts_assignment": "1", - * "oid": "", - * "service_location": "1" - * } - * ) - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "PUT /api/facility/:fuuid" => function ($fuuid) { - RestConfig::authorization_check("admin", "super"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new FacilityRestController())->patch($fuuid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient", - * description="Retrieves a list of patients", - * tags={"standard"}, - * @OA\Parameter( - * ref="#/components/parameters/_sort" - * ), - * @OA\Parameter( - * name="fname", - * in="query", - * description="The first name for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="lname", - * in="query", - * description="The last name for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="ss", - * in="query", - * description="The social security number for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="street", - * in="query", - * description="The street for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="postal_code", - * in="query", - * description="The postal code for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="city", - * in="query", - * description="The city for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="state", - * in="query", - * description="The state for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="phone_home", - * in="query", - * description="The home phone for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="phone_biz", - * in="query", - * description="The business phone for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="phone_cell", - * in="query", - * description="The cell phone for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="postal_contact", - * in="query", - * description="The postal_contact for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="sex", - * in="query", - * description="The gender for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="country_code", - * in="query", - * description="The country code for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="email", - * in="query", - * description="The email for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="DOB", - * in="query", - * description="The DOB for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="date", - * in="query", - * description="The date this patient resource was last modified.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_offset", - * in="query", - * description="The number of records to offset from this index in the search result.", - * required=false, - * @OA\Schema( - * type="integer" - * ) - * ), - * @OA\Parameter( - * name="_limit", - * in="query", - * description="The maximum number of resources to return in the result set. 0 means unlimited.", - * required=false, - * @OA\Schema( - * type="integer" - * ,minimum=0 - * ,maximum=200 - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient" => function () { - RestConfig::authorization_check("patients", "demo"); - $config = SearchQueryConfig::createConfigFromQueryParams($_GET); - $return = (new PatientRestController())->getAll($_GET, $config); - RestConfig::apiLog($return); - return $return; - }, - - /** - * Schema for the patient request - * - * @OA\Schema( - * schema="api_patient_request", - * @OA\Property( - * property="title", - * description="The title of patient.", - * type="string" - * ), - * @OA\Property( - * property="fname", - * description="The fname of patient.", - * type="string" - * ), - * @OA\Property( - * property="mname", - * description="The mname of patient.", - * type="string" - * ), - * @OA\Property( - * property="lname", - * description="The lname of patient.", - * type="string" - * ), - * @OA\Property( - * property="street", - * description="The street address of patient.", - * type="string" - * ), - * @OA\Property( - * property="postal_code", - * description="The postal code of patient.", - * type="string" - * ), - * @OA\Property( - * property="city", - * description="The city of patient.", - * type="string" - * ), - * @OA\Property( - * property="state", - * description="The state of patient.", - * type="string" - * ), - * @OA\Property( - * property="country_code", - * description="The country code of patient.", - * type="string" - * ), - * @OA\Property( - * property="phone_contact", - * description="The phone contact of patient.", - * type="string" - * ), - * @OA\Property( - * property="DOB", - * description="The DOB of patient.", - * type="string" - * ), - * @OA\Property( - * property="sex", - * description="The lname of patient.", - * type="string" - * ), - * @OA\Property( - * property="race", - * description="The race of patient.", - * type="string" - * ), - * @OA\Property( - * property="ethnicity", - * description="The ethnicity of patient.", - * type="string" - * ), - * required={"fname", "lname", "DOB", "sex"}, - * example={ - * "title": "Mr", - * "fname": "Foo", - * "mname": "", - * "lname": "Bar", - * "street": "456 Tree Lane", - * "postal_code": "08642", - * "city": "FooTown", - * "state": "FL", - * "country_code": "US", - * "phone_contact": "123-456-7890", - * "DOB": "1992-02-02", - * "sex": "Male", - * "race": "", - * "ethnicity": "" - * } - * ) - */ - /** - * @OA\Post( - * path="/api/patient", - * description="Creates a new patient", - * tags={"standard"}, - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_patient_request") - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="validationErrors", - * description="Validation errors.", - * type="array", - * @OA\Items( - * type="object", - * ), - * ), - * @OA\Property( - * property="internalErrors", - * description="Internal errors.", - * type="array", - * @OA\Items( - * type="object", - * ), - * ), - * @OA\Property( - * property="data", - * description="Returned data.", - * type="array", - * @OA\Items( - * @OA\Property( - * property="pid", - * description="patient pid", - * type="integer", - * ) - * ), - * ), - * example={ - * "validationErrors": {}, - * "error_description": {}, - * "data": { - * "pid": 1 - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "POST /api/patient" => function () { - RestConfig::authorization_check("patients", "demo"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new PatientRestController())->post($data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * Schema for the patient response - * - * @OA\Schema( - * schema="api_patient_response", - * @OA\Property( - * property="validationErrors", - * description="Validation errors.", - * type="array", - * @OA\Items( - * type="object", - * ), - * ), - * @OA\Property( - * property="internalErrors", - * description="Internal errors.", - * type="array", - * @OA\Items( - * type="object", - * ), - * ), - * @OA\Property( - * property="data", - * description="Returned data.", - * type="array", - * @OA\Items( - * @OA\Property( - * property="id", - * description="patient id", - * type="string", - * ), - * @OA\Property( - * property="pid", - * description="patient pid", - * type="string", - * ), - * @OA\Property( - * property="pubpid", - * description="patient public id", - * type="string", - * ), - * @OA\Property( - * property="title", - * description="patient title", - * type="string", - * ), - * @OA\Property( - * property="fname", - * description="patient first name", - * type="string", - * ), - * @OA\Property( - * property="mname", - * description="patient middle name", - * type="string", - * ), - * @OA\Property( - * property="lname", - * description="patient last name", - * type="string", - * ), - * @OA\Property( - * property="ss", - * description="patient social security number", - * type="string", - * ), - * @OA\Property( - * property="street", - * description="patient street address", - * type="string", - * ), - * @OA\Property( - * property="postal_code", - * description="patient postal code", - * type="string", - * ), - * @OA\Property( - * property="city", - * description="patient city", - * type="string", - * ), - * @OA\Property( - * property="state", - * description="patient state", - * type="string", - * ), - * @OA\Property( - * property="county", - * description="patient county", - * type="string", - * ), - * @OA\Property( - * property="country_code", - * description="patient country code", - * type="string", - * ), - * @OA\Property( - * property="drivers_license", - * description="patient drivers license id", - * type="string", - * ), - * @OA\Property( - * property="contact_relationship", - * description="patient contact relationship", - * type="string", - * ), - * @OA\Property( - * property="phone_contact", - * description="patient phone contact", - * type="string", - * ), - * @OA\Property( - * property="phone_home", - * description="patient home phone", - * type="string", - * ), - * @OA\Property( - * property="phone_biz", - * description="patient work phone", - * type="string", - * ), - * @OA\Property( - * property="phone_cell", - * description="patient mobile phone", - * type="string", - * ), - * @OA\Property( - * property="email", - * description="patient email", - * type="string", - * ), - * @OA\Property( - * property="DOB", - * description="patient DOB", - * type="string", - * ), - * @OA\Property( - * property="sex", - * description="patient sex (gender)", - * type="string", - * ), - * @OA\Property( - * property="race", - * description="patient race", - * type="string", - * ), - * @OA\Property( - * property="ethnicity", - * description="patient ethnicity", - * type="string", - * ), - * @OA\Property( - * property="status", - * description="patient status", - * type="string", - * ), - * ), - * ), - * example={ - * "validationErrors": {}, - * "error_description": {}, - * "data": { - * "id": "193", - * "pid": "1", - * "pubpid": "", - * "title": "Mr", - * "fname": "Baz", - * "mname": "", - * "lname": "Bop", - * "ss": "", - * "street": "456 Tree Lane", - * "postal_code": "08642", - * "city": "FooTown", - * "state": "FL", - * "county": "", - * "country_code": "US", - * "drivers_license": "", - * "contact_relationship": "", - * "phone_contact": "123-456-7890", - * "phone_home": "", - * "phone_biz": "", - * "phone_cell": "", - * "email": "", - * "DOB": "1992-02-03", - * "sex": "Male", - * "race": "", - * "ethnicity": "", - * "status": "" - * } - * } - * ) - */ - /** - * @OA\Put( - * path="/api/patient/{puuid}", - * description="Updates a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="puuid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_patient_request") - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_patient_response") - * ) - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "PUT /api/patient/:puuid" => function ($puuid) { - RestConfig::authorization_check("patients", "demo"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new PatientRestController())->put($puuid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{puuid}", - * description="Retrieves a single patient by their uuid", - * tags={"standard"}, - * @OA\Parameter( - * name="puuid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_patient_response") - * ) - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:puuid" => function ($puuid) { - RestConfig::authorization_check("patients", "demo"); - $return = (new PatientRestController())->getOne($puuid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{puuid}/encounter", - * description="Retrieves a list of encounters for a single patient", - * tags={"standard"}, - * @OA\Parameter( - * name="puuid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:puuid/encounter" => function ($puuid) { - RestConfig::authorization_check("encounters", "auth_a"); - $return = (new EncounterRestController())->getAll($puuid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * Schema for the encounter request - * - * @OA\Schema( - * schema="api_encounter_request", - * @OA\Property( - * property="date", - * description="The date of encounter.", - * type="string" - * ), - * @OA\Property( - * property="onset_date", - * description="The onset date of encounter.", - * type="string" - * ), - * @OA\Property( - * property="reason", - * description="The reason of encounter.", - * type="string" - * ), - * @OA\Property( - * property="facility", - * description="The facility of encounter.", - * type="string" - * ), - * @OA\Property( - * property="pc_catid", - * description="The pc_catid of encounter.", - * type="string" - * ), - * @OA\Property( - * property="facility_id", - * description="The facility id of encounter.", - * type="string" - * ), - * @OA\Property( - * property="billing_facility", - * description="The billing facility id of encounter.", - * type="string" - * ), - * @OA\Property( - * property="sensitivity", - * description="The sensitivity of encounter.", - * type="string" - * ), - * @OA\Property( - * property="referral_source", - * description="The referral source of encounter.", - * type="string" - * ), - * @OA\Property( - * property="pos_code", - * description="The pos_code of encounter.", - * type="string" - * ), - * @OA\Property( - * property="external_id", - * description="The external id of encounter.", - * type="string" - * ), - * @OA\Property( - * property="provider_id", - * description="The provider id of encounter.", - * type="string" - * ), - * @OA\Property( - * property="class_code", - * description="The class_code of encounter.", - * type="string" - * ), - * required={"pc_catid", "class_code"}, - * example={ - * "date":"2020-11-10", - * "onset_date": "", - * "reason": "Pregnancy Test", - * "facility": "Owerri General Hospital", - * "pc_catid": "5", - * "facility_id": "3", - * "billing_facility": "3", - * "sensitivity": "normal", - * "referral_source": "", - * "pos_code": "0", - * "external_id": "", - * "provider_id": "1", - * "class_code" : "AMB" - * } - * ) - */ - /** - * @OA\Post( - * path="/api/patient/{puuid}/encounter", - * description="Creates a new encounter", - * tags={"standard"}, - * @OA\Parameter( - * name="puuid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_encounter_request") - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="validationErrors", - * description="Validation errors.", - * type="array", - * @OA\Items( - * type="object", - * ), - * ), - * @OA\Property( - * property="internalErrors", - * description="Internal errors.", - * type="array", - * @OA\Items( - * type="object", - * ), - * ), - * @OA\Property( - * property="data", - * description="Returned data.", - * type="array", - * @OA\Items( - * @OA\Property( - * property="encounter", - * description="encounter id", - * type="integer", - * ), - * @OA\Property( - * property="uuid", - * description="encounter uuid", - * type="string", - * ) - * ), - * ), - * example={ - * "validationErrors": {}, - * "error_description": {}, - * "data": { - * "encounter": 1, - * "uuid": "90c196f2-51cc-4655-8858-3a80aebff3ef" - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "POST /api/patient/:puuid/encounter" => function ($puuid) { - RestConfig::authorization_check("encounters", "auth_a"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new EncounterRestController())->post($puuid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * Schema for the encounter response - * - * @OA\Schema( - * schema="api_encounter_response", - * @OA\Property( - * property="validationErrors", - * description="Validation errors.", - * type="array", - * @OA\Items( - * type="object", - * ), - * ), - * @OA\Property( - * property="internalErrors", - * description="Internal errors.", - * type="array", - * @OA\Items( - * type="object", - * ), - * ), - * @OA\Property( - * property="data", - * description="Returned data.", - * type="array", - * @OA\Items( - * @OA\Property( - * property="id", - * description="encounter id", - * type="string", - * ), - * @OA\Property( - * property="uuid", - * description="encounter uuid", - * type="string", - * ), - * @OA\Property( - * property="date", - * description="encounter date", - * type="string", - * ), - * @OA\Property( - * property="reason", - * description="encounter reason", - * type="string", - * ), - * @OA\Property( - * property="facility", - * description="encounter facility name", - * type="string", - * ), - * @OA\Property( - * property="facility_id", - * description="encounter facility id name", - * type="string", - * ), - * @OA\Property( - * property="pid", - * description="encounter for patient pid", - * type="string", - * ), - * @OA\Property( - * property="onset_date", - * description="encounter onset date", - * type="string", - * ), - * @OA\Property( - * property="sensitivity", - * description="encounter sensitivity", - * type="string", - * ), - * @OA\Property( - * property="billing_note", - * description="encounter billing note", - * type="string", - * ), - * @OA\Property( - * property="pc_catid", - * description="encounter pc_catid", - * type="string", - * ), - * @OA\Property( - * property="last_level_billed", - * description="encounter last_level_billed", - * type="string", - * ), - * @OA\Property( - * property="last_level_closed", - * description="encounter last_level_closed", - * type="string", - * ), - * @OA\Property( - * property="last_stmt_date", - * description="encounter last_stmt_date", - * type="string", - * ), - * @OA\Property( - * property="stmt_count", - * description="encounter stmt_count", - * type="string", - * ), - * @OA\Property( - * property="provider_id", - * description="provider id", - * type="string", - * ), - * @OA\Property( - * property="supervisor_id", - * description="encounter supervisor id", - * type="string", - * ), - * @OA\Property( - * property="invoice_refno", - * description="encounter invoice_refno", - * type="string", - * ), - * @OA\Property( - * property="referral_source", - * description="encounter referral source", - * type="string", - * ), - * @OA\Property( - * property="billing_facility", - * description="encounter billing facility id", - * type="string", - * ), - * @OA\Property( - * property="external_id", - * description="encounter external id", - * type="string", - * ), - * @OA\Property( - * property="pos_code", - * description="encounter pos_code", - * type="string", - * ), - * @OA\Property( - * property="class_code", - * description="encounter class_code", - * type="string", - * ), - * @OA\Property( - * property="class_title", - * description="encounter class_title", - * type="string", - * ), - * @OA\Property( - * property="pc_catname", - * description="encounter pc_catname", - * type="string", - * ), - * @OA\Property( - * property="billing_facility_name", - * description="encounter billing facility name", - * type="string", - * ), - * ), - * ), - * example={ - * "validationErrors": {}, - * "error_description": {}, - * "data": { - * "id": "1", - * "uuid": "90c196f2-51cc-4655-8858-3a80aebff3ef", - * "date": "2019-09-14 00:00:00", - * "reason": "Pregnancy Test", - * "facility": "Owerri General Hospital", - * "facility_id": "3", - * "pid": "1", - * "onset_date": "2019-04-20 00:00:00", - * "sensitivity": "normal", - * "billing_note": null, - * "pc_catid": "5", - * "last_level_billed": "0", - * "last_level_closed": "0", - * "last_stmt_date": null, - * "stmt_count": "0", - * "provider_id": "1", - * "supervisor_id": "0", - * "invoice_refno": "", - * "referral_source": "", - * "billing_facility": "3", - * "external_id": "", - * "pos_code": "0", - * "class_code": "AMB", - * "class_title": "ambulatory", - * "pc_catname": "Office Visit", - * "billing_facility_name": "Owerri General Hospital" - * } - * } - * ) - */ - /** - * @OA\Put( - * path="/api/patient/{puuid}/encounter/{euuid}", - * description="Modify a encounter", - * tags={"standard"}, - * @OA\Parameter( - * name="puuid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="euuid", - * in="path", - * description="The uuid for the encounter.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_encounter_request") - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_encounter_response") - * ) - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "PUT /api/patient/:puuid/encounter/:euuid" => function ($puuid, $euuid) { - RestConfig::authorization_check("encounters", "auth_a"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new EncounterRestController())->put($puuid, $euuid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{puuid}/encounter/{euuid}", - * description="Retrieves a single encounter for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="puuid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="euuid", - * in="path", - * description="The uuid for the encounter.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_encounter_response") - * ) - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:puuid/encounter/:euuid" => function ($puuid, $euuid) { - RestConfig::authorization_check("encounters", "auth_a"); - $return = (new EncounterRestController())->getOne($puuid, $euuid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{pid}/encounter/{eid}/soap_note", - * description="Retrieves soap notes from an encounter for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The pid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="eid", - * in="path", - * description="The id for the encounter.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:pid/encounter/:eid/soap_note" => function ($pid, $eid) { - RestConfig::authorization_check("encounters", "notes"); - $return = (new EncounterRestController())->getSoapNotes($pid, $eid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * Schema for the vital request - * - * @OA\Schema( - * schema="api_vital_request", - * @OA\Property( - * property="bps", - * description="The bps of vitals.", - * type="string" - * ), - * @OA\Property( - * property="bpd", - * description="The bpd of vitals.", - * type="string" - * ), - * @OA\Property( - * property="weight", - * description="The weight of vitals. (unit is lb)", - * type="string" - * ), - * @OA\Property( - * property="height", - * description="The height of vitals. (unit is inches)", - * type="string" - * ), - * @OA\Property( - * property="temperature", - * description="The temperature of temperature. (unit is F)", - * type="string" - * ), - * @OA\Property( - * property="temp_method", - * description="The temp_method of vitals.", - * type="string" - * ), - * @OA\Property( - * property="pulse", - * description="The pulse of vitals.", - * type="string" - * ), - * @OA\Property( - * property="respiration", - * description="The respiration of vitals.", - * type="string" - * ), - * @OA\Property( - * property="note", - * description="The note (ie. comments) of vitals.", - * type="string" - * ), - * @OA\Property( - * property="waist_circ", - * description="The waist circumference of vitals. (unit is inches)", - * type="string" - * ), - * @OA\Property( - * property="head_circ", - * description="The head circumference of vitals. (unit is inches)", - * type="string" - * ), - * @OA\Property( - * property="oxygen_saturation", - * description="The oxygen_saturation of vitals.", - * type="string" - * ), - * example={ - * "bps": "130", - * "bpd": "80", - * "weight": "220", - * "height": "70", - * "temperature": "98", - * "temp_method": "Oral", - * "pulse": "60", - * "respiration": "20", - * "note": "Patient with difficulty standing, which made weight measurement difficult.", - * "waist_circ": "37", - * "head_circ": "22.2", - * "oxygen_saturation": "96" - * } - * ) - */ - /** - * @OA\Post( - * path="/api/patient/{pid}/encounter/{eid}/vital", - * description="Submits a new vitals form", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The id for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="eid", - * in="path", - * description="The id for the encounter.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_vital_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "POST /api/patient/:pid/encounter/:eid/vital" => function ($pid, $eid) { - RestConfig::authorization_check("encounters", "notes"); - $data = json_decode(file_get_contents("php://input"), true) ?? []; - $return = (new EncounterRestController())->postVital($pid, $eid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Put( - * path="/api/patient/{pid}/encounter/{eid}/vital/{vid}", - * description="Edit a vitals form", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The id for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="eid", - * in="path", - * description="The id for the encounter.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="vid", - * in="path", - * description="The id for the vitalss form.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_vital_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "PUT /api/patient/:pid/encounter/:eid/vital/:vid" => function ($pid, $eid, $vid) { - RestConfig::authorization_check("encounters", "notes"); - $data = json_decode(file_get_contents("php://input"), true) ?? []; - $return = (new EncounterRestController())->putVital($pid, $eid, $vid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{pid}/encounter/{eid}/vital", - * description="Retrieves all vitals from an encounter for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The pid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="eid", - * in="path", - * description="The id for the encounter.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:pid/encounter/:eid/vital" => function ($pid, $eid) { - RestConfig::authorization_check("encounters", "notes"); - $return = (new EncounterRestController())->getVitals($pid, $eid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{pid}/encounter/{eid}/vital/{vid}", - * description="Retrieves a vitals form from an encounter for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The pid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="eid", - * in="path", - * description="The id for the encounter.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="vid", - * in="path", - * description="The id for the vitals form.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:pid/encounter/:eid/vital/:vid" => function ($pid, $eid, $vid) { - RestConfig::authorization_check("encounters", "notes"); - $return = (new EncounterRestController())->getVital($pid, $eid, $vid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{pid}/encounter/{eid}/soap_note/{sid}", - * description="Retrieves a soap note from an encounter for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The pid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="eid", - * in="path", - * description="The id for the encounter.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="sid", - * in="path", - * description="The id for the soap note.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:pid/encounter/:eid/soap_note/:sid" => function ($pid, $eid, $sid) { - RestConfig::authorization_check("encounters", "notes"); - $return = (new EncounterRestController())->getSoapNote($pid, $eid, $sid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * Schema for the soap_note request - * - * @OA\Schema( - * schema="api_soap_note_request", - * @OA\Property( - * property="subjective", - * description="The subjective of soap note.", - * type="string" - * ), - * @OA\Property( - * property="objective", - * description="The objective of soap note.", - * type="string" - * ), - * @OA\Property( - * property="assessment", - * description="The assessment of soap note.", - * type="string" - * ), - * @OA\Property( - * property="plan", - * description="The plan of soap note.", - * type="string" - * ), - * example={ - * "subjective": "The patient with mechanical fall and cut finger.", - * "objective": "The patient with finger laceration on exam.", - * "assessment": "The patient with finger laceration requiring sutures.", - * "plan": "Sutured finger laceration." - * } - * ) - */ - /** - * @OA\Post( - * path="/api/patient/{pid}/encounter/{eid}/soap_note", - * description="Submits a new soap note", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The id for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="eid", - * in="path", - * description="The id for the encounter.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_soap_note_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "POST /api/patient/:pid/encounter/:eid/soap_note" => function ($pid, $eid) { - RestConfig::authorization_check("encounters", "notes"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new EncounterRestController())->postSoapNote($pid, $eid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Put( - * path="/api/patient/{pid}/encounter/{eid}/soap_note/{sid}", - * description="Edit a soap note", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The id for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="eid", - * in="path", - * description="The id for the encounter.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="sid", - * in="path", - * description="The id for the soap noted.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_soap_note_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "PUT /api/patient/:pid/encounter/:eid/soap_note/:sid" => function ($pid, $eid, $sid) { - RestConfig::authorization_check("encounters", "notes"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new EncounterRestController())->putSoapNote($pid, $eid, $sid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - - /** - * @OA\Get( - * path="/api/practitioner", - * description="Retrieves a list of practitioners", - * tags={"standard"}, - * @OA\Parameter( - * name="title", - * in="query", - * description="The title for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="fname", - * in="query", - * description="The first name for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="lname", - * in="query", - * description="The last name for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="mname", - * in="query", - * description="The middle name for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="federaltaxid", - * in="query", - * description="The federal tax id for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="federaldrugid", - * in="query", - * description="The federal drug id for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="upin", - * in="query", - * description="The upin for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="facility_id", - * in="query", - * description="The facility id for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="facility", - * in="query", - * description="The facility for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="npi", - * in="query", - * description="The npi for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="email", - * in="query", - * description="The email for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="specialty", - * in="query", - * description="The specialty for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="billname", - * in="query", - * description="The billname for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="url", - * in="query", - * description="The url for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="assistant", - * in="query", - * description="The assistant for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="organization", - * in="query", - * description="The organization for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="valedictory", - * in="query", - * description="The valedictory for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="street", - * in="query", - * description="The street for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="streetb", - * in="query", - * description="The street (line 2) for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="city", - * in="query", - * description="The city for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="state", - * in="query", - * description="The state for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="zip", - * in="query", - * description="The zip for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="phone", - * in="query", - * description="The phone for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="fax", - * in="query", - * description="The fax for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="phonew1", - * in="query", - * description="The phonew1 for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="phonecell", - * in="query", - * description="The phonecell for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="notes", - * in="query", - * description="The notes for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="state_license_number2", - * in="query", - * description="The state license number for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="username", - * in="query", - * description="The username for the practitioner.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/practitioner" => function () { - RestConfig::authorization_check("admin", "users"); - $return = (new PractitionerRestController())->getAll($_GET); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/practitioner/{pruuid}", - * description="Retrieves a single practitioner by their uuid", - * tags={"standard"}, - * @OA\Parameter( - * name="pruuid", - * in="path", - * description="The uuid for the practitioner.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/practitioner/:pruuid" => function ($pruuid) { - RestConfig::authorization_check("admin", "users"); - $return = (new PractitionerRestController())->getOne($pruuid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Post( - * path="/api/practitioner", - * description="Submits a new practitioner", - * tags={"standard"}, - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="title", - * description="The title for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="fname", - * description="The first name for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="mname", - * description="The middle name for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="lname", - * description="The last name for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="federaltaxid", - * description="The federal tax id for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="federaldrugid", - * description="The federal drug id for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="upin", - * description="The upin for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="facility_id", - * description="The facility_id for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="facility", - * description="The facility name for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="npi", - * description="The npi for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="email", - * description="The email for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="specialty", - * description="The specialty for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="billname", - * description="The billname for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="url", - * description="The url for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="assistant", - * description="The assistant for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="valedictory", - * description="The valedictory for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="street", - * description="The street address for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="streetb", - * description="The streetb address for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="city", - * description="The city for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="state", - * description="The state for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="zip", - * description="The zip for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="phone", - * description="The phone for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="fax", - * description="The fax for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="phonew1", - * description="The phonew1 for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="phonecell", - * description="The phonecell for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="notes", - * description="The notes for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="state_license_number", - * description="The state license number for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="username", - * description="The username for the practitioner.", - * type="string" - * ), - * required={"fname", "lname", "npi"}, - * example={ - * "title": "Mrs.", - * "fname": "Eduardo", - * "mname": "Kathy", - * "lname": "Perez", - * "federaltaxid": "", - * "federaldrugid": "", - * "upin": "", - * "facility_id": "3", - * "facility": "Your Clinic Name Here", - * "npi": "12345678901", - * "email": "info@pennfirm.com", - * "specialty": "", - * "billname": null, - * "url": null, - * "assistant": null, - * "organization": null, - * "valedictory": null, - * "street": "789 Third Avenue", - * "streetb": "123 Cannaut Street", - * "city": "San Diego", - * "state": "CA", - * "zip": "90210", - * "phone": "(619) 555-9827", - * "fax": null, - * "phonew1": "(619) 555-7822", - * "phonecell": "(619) 555-7821", - * "notes": null, - * "state_license_number": "123456", - * "username": "eduardoperez" - * } - * ) - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="validationErrors", - * description="Validation errors.", - * type="array", - * @OA\Items( - * type="object", - * ), - * ), - * @OA\Property( - * property="internalErrors", - * description="Internal errors.", - * type="array", - * @OA\Items( - * type="object", - * ), - * ), - * @OA\Property( - * property="data", - * description="Returned data.", - * type="array", - * @OA\Items( - * @OA\Property( - * property="id", - * description="practitioner id", - * type="integer", - * ), - * @OA\Property( - * property="uuid", - * description="practitioner uuid", - * type="string", - * ), - * ), - * ), - * example={ - * "validationErrors": {}, - * "error_description": {}, - * "data": { - * "id": 7, - * "uuid": "90d453fb-0248-4c0d-9575-d99d02b169f5" - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "POST /api/practitioner" => function () { - RestConfig::authorization_check("admin", "users"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new PractitionerRestController())->post($data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Put( - * path="/api/practitioner/{pruuid}", - * description="Edit a practitioner", - * tags={"standard"}, - * @OA\Parameter( - * name="pruuid", - * in="path", - * description="The uuid for the practitioner.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="title", - * description="The title for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="fname", - * description="The first name for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="mname", - * description="The middle name for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="lname", - * description="The last name for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="federaltaxid", - * description="The federal tax id for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="federaldrugid", - * description="The federal drug id for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="upin", - * description="The upin for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="facility_id", - * description="The facility_id for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="facility", - * description="The facility name for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="npi", - * description="The npi for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="email", - * description="The email for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="specialty", - * description="The specialty for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="billname", - * description="The billname for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="url", - * description="The url for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="assistant", - * description="The assistant for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="valedictory", - * description="The valedictory for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="street", - * description="The street address for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="streetb", - * description="The streetb address for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="city", - * description="The city for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="state", - * description="The state for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="zip", - * description="The zip for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="phone", - * description="The phone for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="fax", - * description="The fax for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="phonew1", - * description="The phonew1 for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="phonecell", - * description="The phonecell for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="notes", - * description="The notes for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="state_license_number", - * description="The state license number for the practitioner.", - * type="string" - * ), - * @OA\Property( - * property="username", - * description="The username for the practitioner.", - * type="string" - * ), - * example={ - * "title": "Mr", - * "fname": "Baz", - * "mname": "", - * "lname": "Bop", - * "street": "456 Tree Lane", - * "zip": "08642", - * "city": "FooTown", - * "state": "FL", - * "phone": "123-456-7890" - * } - * ) - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="validationErrors", - * description="Validation errors.", - * type="array", - * @OA\Items( - * type="object", - * ), - * ), - * @OA\Property( - * property="internalErrors", - * description="Internal errors.", - * type="array", - * @OA\Items( - * type="object", - * ), - * ), - * @OA\Property( - * property="data", - * description="Returned data.", - * type="array", - * @OA\Items( - * @OA\Property( - * property="id", - * description="practitioner id", - * type="string", - * ), - * @OA\Property( - * property="uuid", - * description="practitioner uuid", - * type="string", - * ), - * @OA\Property( - * property="title", - * description="practitioner title", - * type="string", - * ), - * @OA\Property( - * property="fname", - * description="practitioner fname", - * type="string", - * ), - * @OA\Property( - * property="lname", - * description="practitioner lname", - * type="string", - * ), - * @OA\Property( - * property="mname", - * description="practitioner mname", - * type="string", - * ), - * @OA\Property( - * property="federaltaxid", - * description="practitioner federaltaxid", - * type="string", - * ), - * @OA\Property( - * property="federaldrugid", - * description="practitioner federaldrugid", - * type="string", - * ), - * @OA\Property( - * property="upin", - * description="practitioner upin", - * type="string", - * ), - * @OA\Property( - * property="facility_id", - * description="practitioner facility_id", - * type="string", - * ), - * @OA\Property( - * property="facility", - * description="practitioner facility", - * type="string", - * ), - * @OA\Property( - * property="npi", - * description="practitioner npi", - * type="string", - * ), - * @OA\Property( - * property="email", - * description="practitioner email", - * type="string", - * ), - * @OA\Property( - * property="active", - * description="practitioner active setting", - * type="string", - * ), - * @OA\Property( - * property="specialty", - * description="practitioner specialty", - * type="string", - * ), - * @OA\Property( - * property="billname", - * description="practitioner billname", - * type="string", - * ), - * @OA\Property( - * property="url", - * description="practitioner url", - * type="string", - * ), - * @OA\Property( - * property="assistant", - * description="practitioner assistant", - * type="string", - * ), - * @OA\Property( - * property="organization", - * description="practitioner organization", - * type="string", - * ), - * @OA\Property( - * property="valedictory", - * description="practitioner valedictory", - * type="string", - * ), - * @OA\Property( - * property="street", - * description="practitioner street", - * type="string", - * ), - * @OA\Property( - * property="streetb", - * description="practitioner streetb", - * type="string", - * ), - * @OA\Property( - * property="city", - * description="practitioner city", - * type="string", - * ), - * @OA\Property( - * property="state", - * description="practitioner state", - * type="string", - * ), - * @OA\Property( - * property="zip", - * description="practitioner zip", - * type="string", - * ), - * @OA\Property( - * property="phone", - * description="practitioner phone", - * type="string", - * ), - * @OA\Property( - * property="fax", - * description="fax", - * type="string", - * ), - * @OA\Property( - * property="phonew1", - * description="practitioner phonew1", - * type="string", - * ), - * @OA\Property( - * property="phonecell", - * description="practitioner phonecell", - * type="string", - * ), - * @OA\Property( - * property="notes", - * description="practitioner notes", - * type="string", - * ), - * @OA\Property( - * property="state_license_number", - * description="practitioner state license number", - * type="string", - * ), - * @OA\Property( - * property="abook_title", - * description="practitioner abook title", - * type="string", - * ), - * @OA\Property( - * property="physician_title", - * description="practitioner physician title", - * type="string", - * ), - * @OA\Property( - * property="physician_code", - * description="practitioner physician code", - * type="string", - * ) - * ), - * ), - * example={ - * "validationErrors": {}, - * "error_description": {}, - * "data": { - * "id": 7, - * "uuid": "90d453fb-0248-4c0d-9575-d99d02b169f5", - * "title": "Mr", - * "fname": "Baz", - * "lname": "Bop", - * "mname": "", - * "federaltaxid": "", - * "federaldrugid": "", - * "upin": "", - * "facility_id": "3", - * "facility": "Your Clinic Name Here", - * "npi": "0123456789", - * "email": "info@pennfirm.com", - * "active": "1", - * "specialty": "", - * "billname": "", - * "url": "", - * "assistant": "", - * "organization": "", - * "valedictory": "", - * "street": "456 Tree Lane", - * "streetb": "123 Cannaut Street", - * "city": "FooTown", - * "state": "FL", - * "zip": "08642", - * "phone": "123-456-7890", - * "fax": "", - * "phonew1": "(619) 555-7822", - * "phonecell": "(619) 555-7821", - * "notes": "", - * "state_license_number": "123456", - * "abook_title": null, - * "physician_title": null, - * "physician_code": null - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "PUT /api/practitioner/:pruuid" => function ($pruuid) { - RestConfig::authorization_check("admin", "users"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new PractitionerRestController())->patch($pruuid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Get( - * path="/api/medical_problem", - * description="Retrieves a list of medical problems", - * tags={"standard"}, - * @OA\Parameter( - * name="puuid", - * in="query", - * description="The uuid for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="condition_uuid", - * in="query", - * description="The uuid for the medical problem.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="title", - * in="query", - * description="The title for the medical problem.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="begdate", - * in="query", - * description="The start date for the medical problem.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="enddate", - * in="query", - * description="The end date for the medical problem.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="diagnosis", - * in="query", - * description="The diagnosis for the medical problem.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/medical_problem" => function () { - RestConfig::authorization_check("encounters", "notes"); - $return = (new ConditionRestController())->getAll(); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/medical_problem/{muuid}", - * description="Retrieves a single medical problem by their uuid", - * tags={"standard"}, - * @OA\Parameter( - * name="muuid", - * in="path", - * description="The uuid for the medical problem.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/medical_problem/:muuid" => function ($muuid) { - RestConfig::authorization_check("encounters", "notes"); - $return = (new ConditionRestController())->getOne($muuid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{puuid}/medical_problem", - * description="Retrieves all medical problems for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="puuid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:puuid/medical_problem" => function ($puuid) { - RestConfig::authorization_check("encounters", "notes"); - $return = (new ConditionRestController())->getAll(['puuid' => $puuid]); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{puuid}/medical_problem/{muuid}", - * description="Retrieves a medical problem for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="puuid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="muuid", - * in="path", - * description="The uuid for the medical problem.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:puuid/medical_problem/:muuid" => function ($puuid, $muuid) { - RestConfig::authorization_check("patients", "med"); - $return = (new ConditionRestController())->getAll(['puuid' => $puuid, 'condition_uuid' => $muuid]); - RestConfig::apiLog($return); - return $return; - }, - - /** - * Schema for the medical_problem request - * - * @OA\Schema( - * schema="api_medical_problem_request", - * @OA\Property( - * property="title", - * description="The title of medical problem.", - * type="string" - * ), - * @OA\Property( - * property="begdate", - * description="The beginning date of medical problem.", - * type="string" - * ), - * @OA\Property( - * property="enddate", - * description="The end date of medical problem.", - * type="string" - * ), - * @OA\Property( - * property="diagnosis", - * description="The diagnosis of medical problem. In format `:`", - * type="string" - * ), - * required={"title", "begdate"}, - * example={ - * "title": "Dermatochalasis", - * "begdate": "2010-10-13", - * "enddate": null, - * "diagnosis": "ICD10:H02.839" - * } - * ) - */ - /** - * @OA\Post( - * path="/api/patient/{puuid}/medical_problem", - * description="Submits a new medical problem", - * tags={"standard"}, - * @OA\Parameter( - * name="puuid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_medical_problem_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "POST /api/patient/:puuid/medical_problem" => function ($puuid) { - RestConfig::authorization_check("patients", "med"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new ConditionRestController())->post($puuid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Put( - * path="/api/patient/{puuid}/medical_problem/{muuid}", - * description="Edit a medical problem", - * tags={"standard"}, - * @OA\Parameter( - * name="puuid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="muuid", - * in="path", - * description="The uuid for the medical problem.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_medical_problem_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "PUT /api/patient/:puuid/medical_problem/:muuid" => function ($puuid, $muuid) { - RestConfig::authorization_check("patients", "med"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new ConditionRestController())->put($puuid, $muuid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Delete( - * path="/api/patient/{puuid}/medical_problem/{muuid}", - * description="Delete a medical problem", - * tags={"standard"}, - * @OA\Parameter( - * name="puuid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="muuid", - * in="path", - * description="The uuid for the medical problem.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "DELETE /api/patient/:puuid/medical_problem/:muuid" => function ($puuid, $muuid) { - RestConfig::authorization_check("patients", "med"); - $return = (new ConditionRestController())->delete($puuid, $muuid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/allergy", - * description="Retrieves a list of allergies", - * tags={"standard"}, - * @OA\Parameter( - * name="lists.pid", - * in="query", - * description="The uuid for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="lists.id", - * in="query", - * description="The uuid for the allergy.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="title", - * in="query", - * description="The title for the allergy.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="begdate", - * in="query", - * description="The start date for the allergy.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="enddate", - * in="query", - * description="The end date for the allergy.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="diagnosis", - * in="query", - * description="The diagnosis for the allergy.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/allergy" => function () { - RestConfig::authorization_check("patients", "med"); - $return = (new AllergyIntoleranceRestController())->getAll(); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/allergy/{auuid}", - * description="Retrieves a single allergy by their uuid", - * tags={"standard"}, - * @OA\Parameter( - * name="auuid", - * in="path", - * description="The uuid for the allergy.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/allergy/:auuid" => function ($auuid) { - RestConfig::authorization_check("patients", "med"); - $return = (new AllergyIntoleranceRestController())->getOne($auuid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{puuid}/allergy", - * description="Retrieves all allergies for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="puuid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:puuid/allergy" => function ($puuid) { - RestConfig::authorization_check("patients", "med"); - $return = (new AllergyIntoleranceRestController())->getAll(['lists.pid' => $puuid]); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{puuid}/allergy/{auuid}", - * description="Retrieves a allergy for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="puuid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="auuid", - * in="path", - * description="The uuid for the allergy.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:puuid/allergy/:auuid" => function ($puuid, $auuid) { - RestConfig::authorization_check("patients", "med"); - $return = (new AllergyIntoleranceRestController())->getAll(['lists.pid' => $puuid, 'lists.id' => $auuid]); - RestConfig::apiLog($return); - return $return; - }, - - /** - * Schema for the allergy request - * - * @OA\Schema( - * schema="api_allergy_request", - * @OA\Property( - * property="title", - * description="The title of allergy.", - * type="string" - * ), - * @OA\Property( - * property="begdate", - * description="The beginning date of allergy.", - * type="string" - * ), - * @OA\Property( - * property="enddate", - * description="The end date of allergy.", - * type="string" - * ), - * @OA\Property( - * property="diagnosis", - * description="The diagnosis of allergy. In format `:`", - * type="string" - * ), - * required={"title", "begdate"}, - * example={ - * "title": "Iodine", - * "begdate": "2010-10-13", - * "enddate": null - * } - * ) - */ - /** - * @OA\Post( - * path="/api/patient/{puuid}/allergy", - * description="Submits a new allergy", - * tags={"standard"}, - * @OA\Parameter( - * name="puuid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_allergy_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "POST /api/patient/:puuid/allergy" => function ($puuid) { - RestConfig::authorization_check("patients", "med"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new AllergyIntoleranceRestController())->post($puuid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Put( - * path="/api/patient/{puuid}/allergy/{auuid}", - * description="Edit a allergy", - * tags={"standard"}, - * @OA\Parameter( - * name="puuid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="auuid", - * in="path", - * description="The uuid for the allergy.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_allergy_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "PUT /api/patient/:puuid/allergy/:auuid" => function ($puuid, $auuid) { - RestConfig::authorization_check("patients", "med"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new AllergyIntoleranceRestController())->put($puuid, $auuid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Delete( - * path="/api/patient/{puuid}/allergy/{auuid}", - * description="Delete a medical problem", - * tags={"standard"}, - * @OA\Parameter( - * name="puuid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="auuid", - * in="path", - * description="The uuid for the allergy.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "DELETE /api/patient/:puuid/allergy/:auuid" => function ($puuid, $auuid) { - RestConfig::authorization_check("patients", "med"); - $return = (new AllergyIntoleranceRestController())->delete($puuid, $auuid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{pid}/medication", - * description="Retrieves all medications for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The pid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:pid/medication" => function ($pid) { - RestConfig::authorization_check("patients", "med"); - $return = (new ListRestController())->getAll($pid, "medication"); - RestConfig::apiLog($return); - return $return; - }, - - /** - * Schema for the medication request - * - * @OA\Schema( - * schema="api_medication_request", - * @OA\Property( - * property="title", - * description="The title of medication.", - * type="string" - * ), - * @OA\Property( - * property="begdate", - * description="The beginning date of medication.", - * type="string" - * ), - * @OA\Property( - * property="enddate", - * description="The end date of medication.", - * type="string" - * ), - * @OA\Property( - * property="diagnosis", - * description="The diagnosis of medication. In format `:`", - * type="string" - * ), - * required={"title", "begdate"}, - * example={ - * "title": "Norvasc", - * "begdate": "2013-04-13", - * "enddate": null - * } - * ) - */ - /** - * @OA\Post( - * path="/api/patient/{pid}/medication", - * description="Submits a new medication", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The pid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_medication_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "POST /api/patient/:pid/medication" => function ($pid) { - RestConfig::authorization_check("patients", "med"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new ListRestController())->post($pid, "medication", $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Put( - * path="/api/patient/{pid}/medication/{mid}", - * description="Edit a medication", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The pid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="mid", - * in="path", - * description="The id for the medication.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_medication_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "PUT /api/patient/:pid/medication/:mid" => function ($pid, $mid) { - RestConfig::authorization_check("patients", "med"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new ListRestController())->put($pid, $mid, "medication", $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{pid}/medication/{mid}", - * description="Retrieves a medication for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The id for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="mid", - * in="path", - * description="The id for the medication.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:pid/medication/:mid" => function ($pid, $mid) { - RestConfig::authorization_check("patients", "med"); - $return = (new ListRestController())->getOne($pid, "medication", $mid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Delete( - * path="/api/patient/{pid}/medication/{mid}", - * description="Delete a medication", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The id for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="mid", - * in="path", - * description="The id for the medication.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "DELETE /api/patient/:pid/medication/:mid" => function ($pid, $mid) { - RestConfig::authorization_check("patients", "med"); - $return = (new ListRestController())->delete($pid, $mid, "medication"); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{pid}/surgery", - * description="Retrieves all surgeries for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The pid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:pid/surgery" => function ($pid) { - RestConfig::authorization_check("patients", "med"); - $return = (new ListRestController())->getAll($pid, "surgery"); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{pid}/surgery/{sid}", - * description="Retrieves a surgery for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The id for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="sid", - * in="path", - * description="The id for the surgery.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:pid/surgery/:sid" => function ($pid, $sid) { - RestConfig::authorization_check("patients", "med"); - $return = (new ListRestController())->getOne($pid, "surgery", $sid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Delete( - * path="/api/patient/{pid}/surgery/{sid}", - * description="Delete a surgery", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The id for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="sid", - * in="path", - * description="The id for the surgery.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "DELETE /api/patient/:pid/surgery/:sid" => function ($pid, $sid) { - RestConfig::authorization_check("patients", "med"); - $return = (new ListRestController())->delete($pid, $sid, "surgery"); - RestConfig::apiLog($return); - return $return; - }, - - /** - * Schema for the surgery request - * - * @OA\Schema( - * schema="api_surgery_request", - * @OA\Property( - * property="title", - * description="The title of surgery.", - * type="string" - * ), - * @OA\Property( - * property="begdate", - * description="The beginning date of surgery.", - * type="string" - * ), - * @OA\Property( - * property="enddate", - * description="The end date of surgery.", - * type="string" - * ), - * @OA\Property( - * property="diagnosis", - * description="The diagnosis of surgery. In format `:`", - * type="string" - * ), - * required={"title", "begdate"}, - * example={ - * "title": "Blepharoplasty", - * "begdate": "2013-10-14", - * "enddate": null, - * "diagnosis": "CPT4:15823-50" - * } - * ) - */ - /** - * @OA\Post( - * path="/api/patient/{pid}/surgery", - * description="Submits a new surgery", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The pid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_surgery_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "POST /api/patient/:pid/surgery" => function ($pid) { - RestConfig::authorization_check("patients", "med"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new ListRestController())->post($pid, "surgery", $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Put( - * path="/api/patient/{pid}/surgery/{sid}", - * description="Edit a surgery", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The pid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="sid", - * in="path", - * description="The id for the surgery.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_surgery_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "PUT /api/patient/:pid/surgery/:sid" => function ($pid, $sid) { - RestConfig::authorization_check("patients", "med"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new ListRestController())->put($pid, $sid, "surgery", $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{pid}/dental_issue", - * description="Retrieves all dental issues for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The pid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:pid/dental_issue" => function ($pid) { - RestConfig::authorization_check("patients", "med"); - $return = (new ListRestController())->getAll($pid, "dental"); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{pid}/dental_issue/{did}", - * description="Retrieves a dental issue for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The id for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="did", - * in="path", - * description="The id for the dental issue.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:pid/dental_issue/:did" => function ($pid, $did) { - RestConfig::authorization_check("patients", "med"); - $return = (new ListRestController())->getOne($pid, "dental", $did); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Delete( - * path="/api/patient/{pid}/dental_issue/{did}", - * description="Delete a dental issue", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The id for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="did", - * in="path", - * description="The id for the dental issue.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "DELETE /api/patient/:pid/dental_issue/:did" => function ($pid, $did) { - RestConfig::authorization_check("patients", "med"); - $return = (new ListRestController())->delete($pid, $did, "dental"); - RestConfig::apiLog($return); - return $return; - }, - - /** - * Schema for the dental_issue request - * - * @OA\Schema( - * schema="api_dental_issue_request", - * @OA\Property( - * property="title", - * description="The title of dental issue.", - * type="string" - * ), - * @OA\Property( - * property="begdate", - * description="The beginning date of dental issue.", - * type="string" - * ), - * @OA\Property( - * property="enddate", - * description="The end date of dental issue.", - * type="string" - * ), - * @OA\Property( - * property="diagnosis", - * description="The diagnosis of dental issue. In format `:`", - * type="string" - * ), - * required={"title", "begdate"}, - * example={ - * "title": "Halitosis", - * "begdate": "2015-03-17", - * "enddate": null, - * } - * ) - */ - /** - * @OA\Post( - * path="/api/patient/{pid}/dental_issue", - * description="Submits a new dental issue", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The pid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_dental_issue_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "POST /api/patient/:pid/dental_issue" => function ($pid) { - RestConfig::authorization_check("patients", "med"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new ListRestController())->post($pid, "dental", $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Put( - * path="/api/patient/{pid}/dental_issue/{did}", - * description="Edit a dental issue", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The pid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="did", - * in="path", - * description="The id for the dental issue.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_dental_issue_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "PUT /api/patient/:pid/dental_issue/:did" => function ($pid, $did) { - RestConfig::authorization_check("patients", "med"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new ListRestController())->put($pid, $did, "dental", $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{pid}/appointment", - * description="Retrieves all appointments for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The pid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:pid/appointment" => function ($pid) { - RestConfig::authorization_check("patients", "appt"); - $return = (new AppointmentRestController())->getAllForPatient($pid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Post( - * path="/api/patient/{pid}/appointment", - * description="Submits a new appointment", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The id for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="pc_catid", - * description="The category of the appointment.", - * type="string" - * ), - * @OA\Property( - * property="pc_title", - * description="The title of the appointment.", - * type="string" - * ), - * @OA\Property( - * property="pc_duration", - * description="The duration of the appointment.", - * type="string" - * ), - * @OA\Property( - * property="pc_hometext", - * description="Comments for the appointment.", - * type="string" - * ), - * @OA\Property( - * property="pc_apptstatus", - * description="use an option from resource=/api/list/apptstat", - * type="string" - * ), - * @OA\Property( - * property="pc_eventDate", - * description="The date of the appointment.", - * type="string" - * ), - * @OA\Property( - * property="pc_startTime", - * description="The time of the appointment.", - * type="string" - * ), - * @OA\Property( - * property="pc_facility", - * description="The facility id of the appointment.", - * type="string" - * ), - * @OA\Property( - * property="pc_billing_location", - * description="The billinag location id of the appointment.", - * type="string" - * ), - * @OA\Property( - * property="pc_aid", - * description="The provider id for the appointment.", - * type="string" - * ), - * required={"pc_catid", "pc_title", "pc_duration", "pc_hometext", "pc_apptstatus", "pc_eventDate", "pc_startTime", "pc_facility", "pc_billing_location"}, - * example={ - * "pc_catid": "5", - * "pc_title": "Office Visit", - * "pc_duration": "900", - * "pc_hometext": "Test", - * "pc_apptstatus": "-", - * "pc_eventDate": "2018-10-19", - * "pc_startTime": "09:00", - * "pc_facility": "9", - * "pc_billing_location": "10", - * "pc_aid": "1" - * } - * ) - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "POST /api/patient/:pid/appointment" => function ($pid) { - RestConfig::authorization_check("patients", "appt"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new AppointmentRestController())->post($pid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Get( - * path="/api/appointment", - * description="Retrieves all appointments", - * tags={"standard"}, - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/appointment" => function () { - RestConfig::authorization_check("patients", "appt"); - $return = (new AppointmentRestController())->getAll(); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/appointment/{eid}", - * description="Retrieves an appointment", - * tags={"standard"}, - * @OA\Parameter( - * name="eid", - * in="path", - * description="The eid for the appointment.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/appointment/:eid" => function ($eid) { - RestConfig::authorization_check("patients", "appt"); - $return = (new AppointmentRestController())->getOne($eid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Delete( - * path="/api/patient/{pid}/appointment/{eid}", - * description="Delete a appointment", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The id for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="eid", - * in="path", - * description="The eid for the appointment.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "DELETE /api/patient/:pid/appointment/:eid" => function ($pid, $eid) { - RestConfig::authorization_check("patients", "appt"); - $return = (new AppointmentRestController())->delete($eid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{pid}/appointment/{eid}", - * description="Retrieves a appointment for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The id for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="eid", - * in="path", - * description="The eid for the appointment.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:pid/appointment/:eid" => function ($pid, $eid) { - RestConfig::authorization_check("patients", "appt"); - $return = (new AppointmentRestController())->getOne($eid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/list/{list_name}", - * description="Retrieves a list", - * tags={"standard"}, - * @OA\Parameter( - * name="list_name", - * in="path", - * description="The list_id of the list.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/list/:list_name" => function ($list_name) { - RestConfig::authorization_check("lists", "default"); - $return = (new ListRestController())->getOptions($list_name); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/user", - * description="Retrieves a list of users", - * tags={"standard"}, - * @OA\Parameter( - * name="id", - * in="query", - * description="The id for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="title", - * in="query", - * description="The title for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="fname", - * in="query", - * description="The first name for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="lname", - * in="query", - * description="The last name for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="mname", - * in="query", - * description="The middle name for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="federaltaxid", - * in="query", - * description="The federal tax id for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="federaldrugid", - * in="query", - * description="The federal drug id for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="upin", - * in="query", - * description="The upin for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="facility_id", - * in="query", - * description="The facility id for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="facility", - * in="query", - * description="The facility for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="npi", - * in="query", - * description="The npi for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="email", - * in="query", - * description="The email for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="specialty", - * in="query", - * description="The specialty for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="billname", - * in="query", - * description="The billname for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="url", - * in="query", - * description="The url for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="assistant", - * in="query", - * description="The assistant for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="organization", - * in="query", - * description="The organization for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="valedictory", - * in="query", - * description="The valedictory for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="street", - * in="query", - * description="The street for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="streetb", - * in="query", - * description="The street (line 2) for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="city", - * in="query", - * description="The city for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="state", - * in="query", - * description="The state for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="zip", - * in="query", - * description="The zip for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="phone", - * in="query", - * description="The phone for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="fax", - * in="query", - * description="The fax for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="phonew1", - * in="query", - * description="The phonew1 for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="phonecell", - * in="query", - * description="The phonecell for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="notes", - * in="query", - * description="The notes for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="state_license_number2", - * in="query", - * description="The state license number for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="username", - * in="query", - * description="The username for the user.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/user" => function () { - RestConfig::authorization_check("admin", "users"); - $return = (new UserRestController())->getAll($_GET); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/user/{uuid}", - * description="Retrieves a single user by their uuid", - * tags={"standard"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the user.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/user/:uuid" => function ($uuid) { - RestConfig::authorization_check("admin", "users"); - $return = (new UserRestController())->getOne($uuid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/version", - * description="Retrieves the OpenEMR version information", - * tags={"standard"}, - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/version" => function () { - $return = (new VersionRestController())->getOne(); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/product", - * description="Retrieves the OpenEMR product registration information", - * tags={"standard"}, - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/product" => function () { - $return = (new ProductRegistrationRestController())->getOne(); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/insurance_company", - * description="Retrieves all insurance companies", - * tags={"standard"}, - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/insurance_company" => function () { - $return = (new InsuranceCompanyRestController())->getAll(); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/insurance_company/{iid}", - * description="Retrieves insurance company", - * tags={"standard"}, - * @OA\Parameter( - * name="iid", - * in="path", - * description="The id of the insurance company.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/insurance_company/:iid" => function ($iid) { - $return = (new InsuranceCompanyRestController())->getOne($iid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/insurance_type", - * description="Retrieves all insurance types", - * tags={"standard"}, - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/insurance_type" => function () { - $return = (new InsuranceCompanyRestController())->getInsuranceTypes(); - RestConfig::apiLog($return); - return $return; - }, - - /** - * Schema for the insurance_company request - * - * @OA\Schema( - * schema="api_insurance_company_request", - * @OA\Property( - * property="name", - * description="The name of insurance company.", - * type="string" - * ), - * @OA\Property( - * property="attn", - * description="The attn of insurance company.", - * type="string" - * ), - * @OA\Property( - * property="cms_id", - * description="The cms id of insurance company.", - * type="string" - * ), - * @OA\Property( - * property="ins_type_code", - * description="The insurance type code of insurance company. The insurance type code can be found by inspecting the route at (/api/insurance_type).", - * type="string" - * ), - * @OA\Property( - * property="x12_receiver_id", - * description="The x12 receiver id of insurance company.", - * type="string" - * ), - * @OA\Property( - * property="x12_default_partner_id", - * description="The x12 default partner id of insurance company.", - * type="string" - * ), - * @OA\Property( - * property="alt_cms_id", - * description="The alternate cms id of insurance company.", - * type="string" - * ), - * @OA\Property( - * property="line1", - * description="The line1 address of insurance company.", - * type="string" - * ), - * @OA\Property( - * property="line2", - * description="The line2 address of insurance company.", - * type="string" - * ), - * @OA\Property( - * property="city", - * description="The city of insurance company.", - * type="string" - * ), - * @OA\Property( - * property="state", - * description="The state of insurance company.", - * type="string" - * ), - * @OA\Property( - * property="zip", - * description="The zip of insurance company.", - * type="string" - * ), - * @OA\Property( - * property="country", - * description="The country of insurance company.", - * type="string" - * ), - * required={"name"}, - * example={ - * "name": "Cool Insurance Company", - * "attn": null, - * "cms_id": null, - * "ins_type_code": "2", - * "x12_receiver_id": null, - * "x12_default_partner_id": null, - * "alt_cms_id": "", - * "line1": "123 Cool Lane", - * "line2": "Suite 123", - * "city": "Cooltown", - * "state": "CA", - * "zip": "12245", - * "country": "USA" - * } - * ) - */ - /** - * @OA\Post( - * path="/api/insurance_company", - * description="Submits a new insurance company", - * tags={"standard"}, - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_insurance_company_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "POST /api/insurance_company" => function () { - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new InsuranceCompanyRestController())->post($data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Put( - * path="/api/insurance_company/{iid}", - * description="Edit a insurance company", - * tags={"standard"}, - * @OA\Parameter( - * name="iid", - * in="path", - * description="The id for the insurance company.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_insurance_company_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "PUT /api/insurance_company/:iid" => function ($iid) { - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new InsuranceCompanyRestController())->put($iid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Post( - * path="/api/patient/{pid}/document", - * description="Submits a new patient document", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The pid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="path", - * in="query", - * description="The category of the document.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="multipart/form-data", - * @OA\Schema( - * @OA\Property( - * property="document", - * description="document", - * type="string", - * format="binary" - * ), - * ), - * ), - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "POST /api/patient/:pid/document" => function ($pid) { - $return = (new DocumentRestController())->postWithPath($pid, $_GET['path'], $_FILES['document']); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{pid}/document", - * description="Retrieves all file information of documents from a category for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The pid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="path", - * in="query", - * description="The category of the documents.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:pid/document" => function ($pid) { - $return = (new DocumentRestController())->getAllAtPath($pid, $_GET['path']); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{pid}/document/{did}", - * description="Retrieves a document for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The pid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="did", - * in="path", - * description="The id for the patient document.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:pid/document/:did" => function ($pid, $did) { - $return = (new DocumentRestController())->downloadFile($pid, $did); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{puuid}/employer", - * description="Retrieves all the employer data for a patient. Returns an array of the employer data for the patient.", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{"user/employer.read", "patient/employer.read"}}} - * ) - */ - "GET /api/patient/:puuid/employer" => function ($puuid, HttpRestRequest $request) { - if (!UuidRegistry::isValidStringUUID($puuid)) { - $errorReturn = [ - 'validationErrors' => [ 'uuid' => ['Invalid UUID format']] - ]; - RestConfig::apiLog($errorReturn); - return RestControllerHelper::responseHandler($errorReturn, null, 400); - } - - $searchParams = $request->getQueryParams(); - if ($request->isPatientRequest()) { - // For patient portal users, force the UUID to match the authenticated patient. - $searchParams['puuid'] = $request->getPatientUUIDString(); - } else { - // For staff users, verify they have permission to view demographic data. - RestConfig::authorization_check("patients", "demo"); - $searchParams['puuid'] = $puuid; - } - - // Try to get the data. The service layer will handle non-existent UUIDs. - $return = (new EmployerRestController())->getAll($searchParams); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{puuid}/insurance", - * description="Retrieves all insurances for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:puuid/insurance" => function ($puuid, HttpRestRequest $request) { - $searchParams = $request->getQueryParams(); - $searchParams['puuid'] = $puuid; - if ($request->isPatientRequest()) { - $searchParams['puuid'] = $request->getPatientUUIDString(); - } - $return = (new InsuranceRestController())->getAll($searchParams); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{puuid}/insurance/$swap-insurance", - * description="Updates the insurance for the passed in uuid to be a policy of type `type` and updates (if one exists) the current or most recent insurance for the passed in `type` for a patient to be the `type` of the insurance for the given `uuid`. Validations on the swap operation are performed to make sure the effective `date` of the src and target policies being swapped can be received in each given policy `type` as a policy `type` and `date` must together be unique per patient.", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="type", - * in="query", - * description="The type or category of OpenEMR insurance policy, 'primary', 'secondary', or 'tertiary'.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="uuid", - * in="query", - * description="The insurance uuid that will be swapped into the list of insurances for the type query parameter", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - 'GET /api/patient/:puuid/insurance/$swap-insurance' => function ($puuid, HttpRestRequest $request) { - if ($request->isPatientRequest()) { - $puuid = $request->getPatientUUIDString(); - } - $type = $request->getQueryParam('type'); - $insuranceUuid = $request->getQueryParam('uuid'); - - $return = (new InsuranceRestController())->operationSwapInsurance($puuid, $type, $insuranceUuid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{puuid}/insurance/{uuid}", - * description="Retrieves all insurances for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/patient/:puuid/insurance/:uuid" => function ($puuid, $uuid, HttpRestRequest $request) { - if ($request->isPatientRequest()) { - $puuid = $request->getPatientUUIDString(); - } - $return = (new InsuranceRestController())->getOne($uuid, $puuid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * Schema for the insurance request. Note the following additional validation checks on the request. - * If the subscriber_relationship value is of type 'self' then the subscriber_fname and subscriber_lname fields - * must match the patient's first and last name or a patient's previous first and last name. - * - * If the subscriber_relationship value is of type 'self' then the subscriber_ss field must match the patient's - * social security number. - * - * If the subscriber_relationship value is not of type 'self' then the subscriber_ss field MUST not be the current patient's social security number. - * - * If the system's global configuration permits only a single insurance type option then any insurance rquest where the type is NOT 'primary' will fail. - * - * An insurance is considered the current policy for the policy type if the policy date_end field is null. Only one of these records per policy type can exist for a patient. - * @OA\Schema( - * schema="api_insurance_request", - * @OA\Property( - * property="provider", - * description="The insurance company id.", - * type="string" - * ), - * @OA\Property( - * property="plan_name", - * description="The plan name of insurance. (2-255 characters)", - * type="string" - * ), - * @OA\Property( - * property="policy_number", - * description="The policy number of insurance. (2-255 characters)", - * type="string" - * ), - * @OA\Property( - * property="group_number", - * description="The group number of insurance.(2-255 characters)", - * type="string" - * ), - * @OA\Property( - * property="subscriber_lname", - * description="The subscriber last name of insurance.(2-255 characters).", - * type="string" - * ), - * @OA\Property( - * property="subscriber_mname", - * description="The subscriber middle name of insurance.", - * type="string" - * ), - * @OA\Property( - * property="subscriber_fname", - * description="The subscriber first name of insurance.", - * type="string" - * ), - * @OA\Property( - * property="subscriber_relationship", - * description="The subscriber relationship of insurance. `subscriber_relationship` can be found by querying `resource=/api/list/subscriber_relationship`", - * type="string" - * ), - * @OA\Property( - * property="subscriber_ss", - * description="The subscriber ss number of insurance.", - * type="string" - * ), - * @OA\Property( - * property="subscriber_DOB", - * description="The subscriber DOB of insurance.", - * type="string" - * ), - * @OA\Property( - * property="subscriber_street", - * description="The subscriber street address of insurance.", - * type="string" - * ), - * @OA\Property( - * property="subscriber_postal_code", - * description="The subscriber postal code of insurance.", - * type="string" - * ), - * @OA\Property( - * property="subscriber_city", - * description="The subscriber city of insurance.", - * type="string" - * ), - * @OA\Property( - * property="subscriber_state", - * description="The subscriber state of insurance. `state` can be found by querying `resource=/api/list/state`", - * type="string" - * ), - * @OA\Property( - * property="subscriber_country", - * description="The subscriber country of insurance. `country` can be found by querying `resource=/api/list/country`", - * type="string" - * ), - * @OA\Property( - * property="subscriber_phone", - * description="The subscriber phone of insurance.", - * type="string" - * ), - * @OA\Property( - * property="subscriber_employer", - * description="The subscriber employer of insurance.", - * type="string" - * ), - * @OA\Property( - * property="subscriber_employer_street", - * description="The subscriber employer street of insurance.", - * type="string" - * ), - * @OA\Property( - * property="subscriber_employer_postal_code", - * description="The subscriber employer postal code of insurance.", - * type="string" - * ), - * @OA\Property( - * property="subscriber_employer_state", - * description="The subscriber employer state of insurance.", - * type="string" - * ), - * @OA\Property( - * property="subscriber_employer_country", - * description="The subscriber employer country of insurance.", - * type="string" - * ), - * @OA\Property( - * property="subscriber_employer_city", - * description="The subscriber employer city of insurance.", - * type="string" - * ), - * @OA\Property( - * property="copay", - * description="The copay of insurance.", - * type="string" - * ), - * @OA\Property( - * property="date", - * description="The effective date of insurance in YYYY-MM-DD format. This value cannot be after the date_end property and cannot be the same date as any other insurance policy for the same insurance type ('primary, 'secondary', etc).", - * type="string" - * ), - * @OA\Property( - * property="date_end", - * description="The effective end date of insurance in YYYY-MM-DD format. This value cannot be before the date property. If it is null then this policy is the current policy for this policy type for the patient. There can only be one current policy per type and the request will fail if there is already a current policy for this type.", - * type="string" - * ), - * @OA\Property( - * property="subscriber_sex", - * description="The subscriber sex of insurance.", - * type="string" - * ), - * @OA\Property( - * property="accept_assignment", - * description="The accept_assignment of insurance.", - * type="string" - * ), - * @OA\Property( - * property="policy_type", - * description="The 837p list of policy types for an insurance. See src/Billing/InsurancePolicyType.php for the list of valid values.", - * type="string" - * ), - * @OA\Property( - * property="type", - * description="The type or category of OpenEMR insurance policy, 'primary', 'secondary', or 'tertiary'. If this field is missing it will default to 'primary'.", - * type="string" - * ), - * required={"provider", "policy_number", "subscriber_fname", "subscriber_lname", "subscriber_relationship", "subscriber_ss", "subscriber_DOB", "subscriber_street", "subscriber_postal_code", "subscriber_city", "subscriber_state", "subscriber_sex", "accept_assignment"}, - * example={ - * "provider": "33", - * "plan_name": "Some Plan", - * "policy_number": "12345", - * "group_number": "252412", - * "subscriber_lname": "Tester", - * "subscriber_mname": "Xi", - * "subscriber_fname": "Foo", - * "subscriber_relationship": "other", - * "subscriber_ss": "234231234", - * "subscriber_DOB": "2018-10-03", - * "subscriber_street": "183 Cool St", - * "subscriber_postal_code": "23418", - * "subscriber_city": "Cooltown", - * "subscriber_state": "AZ", - * "subscriber_country": "USA", - * "subscriber_phone": "234-598-2123", - * "subscriber_employer": "Some Employer", - * "subscriber_employer_street": "123 Heather Lane", - * "subscriber_employer_postal_code": "23415", - * "subscriber_employer_state": "AZ", - * "subscriber_employer_country": "USA", - * "subscriber_employer_city": "Cooltown", - * "copay": "35", - * "date": "2018-10-15", - * "subscriber_sex": "Female", - * "accept_assignment": "TRUE", - * "policy_type": "a", - * "type": "primary" - * } - * ) - */ - - /** - * @OA\Put( - * path="/api/patient/{puuid}/insurance/{insuranceUuid}", - * description="Edit a specific patient insurance policy. Requires the patients/demo/write ACL to call. This method is the preferred method for updating a patient insurance policy. The {insuranceId} can be found by querying /api/patient/{pid}/insurance", - * tags={"standard"}, - * @OA\Parameter( - * name="puuid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="insuranceUuid", - * in="path", - * description="The insurance policy uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_insurance_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "PUT /api/patient/:puuid/insurance/:insuranceUuid" => function ($puuid, $insuranceUuid, HttpRestRequest $request) { - RestConfig::authorization_check("patients", "demo", '', 'write'); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new InsuranceRestController())->put($puuid, $insuranceUuid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Post( - * path="/api/patient/{puuid}/insurance", - * description="Submits a new patient insurance.", - * tags={"standard"}, - * @OA\Parameter( - * name="puuid", - * in="path", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_insurance_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "POST /api/patient/:puuid/insurance" => function ($puuid) { - RestConfig::authorization_check("patients", "demo", '', ['write','addonly']); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new InsuranceRestController())->post($puuid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - /** - * Schema for the message request - * - * @OA\Schema( - * schema="api_message_request", - * @OA\Property( - * property="body", - * description="The body of message.", - * type="string" - * ), - * @OA\Property( - * property="groupname", - * description="The group name (usually is 'Default').", - * type="string" - * ), - * @OA\Property( - * property="from", - * description="The sender of the message.", - * type="string" - * ), - * @OA\Property( - * property="to", - * description="The recipient of the message.", - * type="string" - * ), - * @OA\Property( - * property="title", - * description="use an option from resource=/api/list/note_type", - * type="string" - * ), - * @OA\Property( - * property="message_status", - * description="use an option from resource=/api/list/message_status", - * type="string" - * ), - * required={"body", "groupname", "from", "to", "title", "message_status"}, - * example={ - * "body": "Test 456", - * "groupname": "Default", - * "from": "Matthew", - * "to": "admin", - * "title": "Other", - * "message_status": "New" - * } - * ) - */ - /** - * @OA\Post( - * path="/api/patient/{pid}/message", - * description="Submits a pnote message", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The id for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_message_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "POST /api/patient/:pid/message" => function ($pid) { - RestConfig::authorization_check("patients", "notes"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new MessageRestController())->post($pid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Get( - * path="/api/patient/{pid}/transaction", - * description="Get Transactions for a patient", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The pid for the patient", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - - "GET /api/patient/:pid/transaction" => function ($pid) { - RestConfig::authorization_check("patients", "trans"); - $cont = new TransactionRestController(); - $return = (new TransactionRestController())->GetPatientTransactions($pid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * Schema for the transaction request - * - * @OA\Schema( - * schema="api_transaction_request", - * @OA\Property( - * property="message", - * description="The message of the transaction.", - * type="string" - * ), - * @OA\Property( - * property="type", - * description="The type of transaction. Use an option from resource=/api/transaction_type", - * type="string" - * ), - * @OA\Property( - * property="groupname", - * description="The group name (usually is 'Default').", - * type="string" - * ), - * @OA\Property( - * property="referByNpi", - * description="NPI of the person creating the referral.", - * type="string" - * ), - * @OA\Property( - * property="referToNpi", - * description="NPI of the person getting the referral.", - * type="string" - * ), - * @OA\Property( - * property="referDiagnosis", - * description="The referral diagnosis.", - * type="string" - * ), - * @OA\Property( - * property="riskLevel", - * description="The risk level. (Low, Medium, High)", - * type="string" - * ), - * @OA\Property( - * property="includeVitals", - * description="Are vitals included (0,1)", - * type="string" - * ), - * @OA\Property( - * property="referralDate", - * description="The date of the referral", - * type="string" - * ), - * @OA\Property( - * property="authorization", - * description="The authorization for the referral", - * type="string" - * ), - * @OA\Property( - * property="visits", - * description="The number of vists for the referral", - * type="string" - * ), - * @OA\Property( - * property="validFrom", - * description="The date the referral is valid from", - * type="string" - * ), - * @OA\Property( - * property="validThrough", - * description="The date the referral is valid through", - * type="string" - * ), - * required={"message", "groupname", "title"}, - * example={ - * "message": "Message", - * "type": "LBTref", - * "groupname": "Default", - * "referByNpi":"9999999999", - * "referToNpi":"9999999999", - * "referDiagnosis":"Diag 1", - * "riskLevel":"Low", - * "includeVitals":"1", - * "referralDate":"2022-01-01", - * "authorization":"Auth_123", - * "visits": "1", - * "validFrom": "2022-01-02", - * "validThrough": "2022-01-03", - * "body": "Reason 1" - * } - * ) - */ - /** - * @OA\Post( - * path="/api/patient/{pid}/transaction", - * description="Submits a transaction", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The pid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_transaction_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "POST /api/patient/:pid/transaction" => function ($pid) { - RestConfig::authorization_check("patients", "trans"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new TransactionRestController())->CreateTransaction($pid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\PUT( - * path="/api/transaction/{tid}", - * description="Updates a transaction", - * tags={"standard"}, - * @OA\Parameter( - * name="tid", - * in="path", - * description="The id for the transaction.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_transaction_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "PUT /api/transaction/:tid" => function ($tid) { - RestConfig::authorization_check("patients", "trans"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new TransactionRestController())->UpdateTransaction($tid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Put( - * path="/api/patient/{pid}/message/{mid}", - * description="Edit a pnote message", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The id for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="mid", - * in="path", - * description="The id for the pnote message.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_message_request") - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "PUT /api/patient/:pid/message/:mid" => function ($pid, $mid) { - RestConfig::authorization_check("patients", "notes"); - $data = (array) (json_decode(file_get_contents("php://input"))); - $return = (new MessageRestController())->put($pid, $mid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Delete( - * path="/api/patient/{pid}/message/{mid}", - * description="Delete a pnote message", - * tags={"standard"}, - * @OA\Parameter( - * name="pid", - * in="path", - * description="The id for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="mid", - * in="path", - * description="The id for the pnote message.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "DELETE /api/patient/:pid/message/:mid" => function ($pid, $mid) { - RestConfig::authorization_check("patients", "notes"); - $return = (new MessageRestController())->delete($pid, $mid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/immunization", - * description="Retrieves a list of immunizations", - * tags={"standard"}, - * @OA\Parameter( - * name="patient_id", - * in="query", - * description="The pid for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="id", - * in="query", - * description="The id for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="uuid", - * in="query", - * description="The uuid for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="administered_date", - * in="query", - * description="The administered date for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="immunization_id", - * in="query", - * description="The immunization list_id for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="cvx_code", - * in="query", - * description="The cvx code for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="manufacturer", - * in="query", - * description="The manufacturer for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="lot_number", - * in="query", - * description="The lot number for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="administered_by_id", - * in="query", - * description="The administered by id for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="administered_by", - * in="query", - * description="The administered by for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="education_date", - * in="query", - * description="The education date for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="vis_date", - * in="query", - * description="The vis date for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="note", - * in="query", - * description="The note for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="create_date", - * in="query", - * description="The create date for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="update_date", - * in="query", - * description="The update date for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="created_by", - * in="query", - * description="The created_by for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="updated_by", - * in="query", - * description="The updated_by for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="amount_administered", - * in="query", - * description="The amount administered for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="amount_administered_unit", - * in="query", - * description="The amount administered unit for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="expiration_date", - * in="query", - * description="The expiration date for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="route", - * in="query", - * description="The route for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="administration_site", - * in="query", - * description="The administration site for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="added_erroneously", - * in="query", - * description="The added_erroneously for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="external_id", - * in="query", - * description="The external_id for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="completion_status", - * in="query", - * description="The completion status for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="information_source", - * in="query", - * description="The information source for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="refusal_reason", - * in="query", - * description="The refusal reason for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="ordering_provider", - * in="query", - * description="The ordering provider for the immunization.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/immunization" => function () { - RestConfig::authorization_check("patients", "med"); - $return = (new ImmunizationRestController())->getAll($_GET); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/immunization/{uuid}", - * description="Retrieves a immunization", - * tags={"standard"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the immunization.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/immunization/:uuid" => function ($uuid) { - RestConfig::authorization_check("patients", "med"); - $return = (new ImmunizationRestController())->getOne($uuid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/procedure", - * description="Retrieves a list of all procedures", - * tags={"standard"}, - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/procedure" => function () { - RestConfig::authorization_check("patients", "med"); - $return = (new ProcedureRestController())->getAll(); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/procedure/{uuid}", - * description="Retrieves a procedure", - * tags={"standard"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the procedure.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/procedure/:uuid" => function ($uuid) { - RestConfig::authorization_check("patients", "med"); - $return = (new ProcedureRestController())->getOne($uuid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/drug", - * description="Retrieves a list of all drugs", - * tags={"standard"}, - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/drug" => function () { - RestConfig::authorization_check("patients", "med"); - $return = (new DrugRestController())->getAll(); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/drug/{uuid}", - * description="Retrieves a drug", - * tags={"standard"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the drug.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/drug/:uuid" => function ($uuid) { - RestConfig::authorization_check("patients", "med"); - $return = (new DrugRestController())->getOne($uuid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/prescription", - * description="Retrieves a list of all prescriptions", - * tags={"standard"}, - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/prescription" => function () { - RestConfig::authorization_check("patients", "med"); - $return = (new PrescriptionRestController())->getAll(); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/api/prescription/{uuid}", - * description="Retrieves a prescription", - * tags={"standard"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the prescription.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /api/prescription/:uuid" => function ($uuid) { - RestConfig::authorization_check("patients", "med"); - $return = (new PrescriptionRestController())->getOne($uuid); - RestConfig::apiLog($return); - return $return; - } -); - -use OpenEMR\Common\Http\StatusCode; -use OpenEMR\Common\Http\Psr17Factory; -use OpenEMR\RestControllers\FHIR\FhirAllergyIntoleranceRestController; -use OpenEMR\RestControllers\FHIR\FhirAppointmentRestController; -use OpenEMR\RestControllers\FHIR\FhirCarePlanRestController; -use OpenEMR\RestControllers\FHIR\FhirCareTeamRestController; -use OpenEMR\RestControllers\FHIR\FhirConditionRestController; -use OpenEMR\RestControllers\FHIR\FhirCoverageRestController; -use OpenEMR\RestControllers\FHIR\FhirDeviceRestController; -use OpenEMR\RestControllers\FHIR\FhirDiagnosticReportRestController; -use OpenEMR\RestControllers\FHIR\FhirDocumentReferenceRestController; -use OpenEMR\RestControllers\FHIR\FhirEncounterRestController; -use OpenEMR\RestControllers\FHIR\FhirObservationRestController; -use OpenEMR\RestControllers\FHIR\FhirImmunizationRestController; -use OpenEMR\RestControllers\FHIR\FhirGoalRestController; -use OpenEMR\RestControllers\FHIR\FhirGroupRestController; -use OpenEMR\RestControllers\FHIR\FhirLocationRestController; -use OpenEMR\RestControllers\FHIR\FhirMedicationRestController; -use OpenEMR\RestControllers\FHIR\FhirMedicationRequestRestController; -use OpenEMR\RestControllers\FHIR\FhirOrganizationRestController; -use OpenEMR\RestControllers\FHIR\FhirPatientRestController; -use OpenEMR\RestControllers\FHIR\FhirPersonRestController; -use OpenEMR\RestControllers\FHIR\FhirPractitionerRoleRestController; -use OpenEMR\RestControllers\FHIR\FhirPractitionerRestController; -use OpenEMR\RestControllers\FHIR\FhirProcedureRestController; -use OpenEMR\RestControllers\FHIR\FhirProvenanceRestController; -use OpenEMR\RestControllers\FHIR\FhirValueSetRestController; -use OpenEMR\RestControllers\FHIR\FhirMetaDataRestController; -use OpenEMR\RestControllers\FHIR\Operations\FhirOperationExportRestController; -use OpenEMR\RestControllers\FHIR\Operations\FhirOperationDocRefRestController; -use OpenEMR\RestControllers\FHIR\Operations\FhirOperationDefinitionRestController; -use OpenEMR\Services\FHIR\Questionnaire\FhirQuestionnaireFormService; -use OpenEMR\Services\FHIR\FhirQuestionnaireService; -use OpenEMR\RestControllers\FHIR\FhirQuestionnaireRestController; -use OpenEMR\Services\FHIR\QuestionnaireResponse\FhirQuestionnaireResponseFormService; -use OpenEMR\Services\FHIR\FhirQuestionnaireResponseService; -use OpenEMR\RestControllers\FHIR\FhirQuestionnaireResponseRestController; - -// Note that the fhir route includes both user role and patient role -// (there is a mechanism in place to ensure patient role is binded -// to only see the data of the one patient) -RestConfig::$FHIR_ROUTE_MAP = array( - /** - * @OA\Get( - * path="/fhir/AllergyIntolerance", - * description="Returns a list of AllergyIntolerance resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the AllergyIntolerance resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="patient", - * in="query", - * description="The uuid for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/AllergyIntolerance" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/AllergyIntolerance" => function (HttpRestRequest $request) { - $getParams = $request->getQueryParams(); - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirAllergyIntoleranceRestController($request))->getAll($getParams, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("patients", "med"); - $return = (new FhirAllergyIntoleranceRestController($request))->getAll($getParams); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/AllergyIntolerance/{uuid}", - * description="Returns a single AllergyIntolerance resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the AllergyIntolerance resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "94682fe5-f383-4885-9505-64b02e34906f", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2021-09-16T00:27:32+00:00" - * }, - * "resourceType": "AllergyIntolerance", - * "text": { - * "status": "additional", - * "div": "
penicillin
" - * }, - * "clinicalStatus": { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical", - * "code": "active", - * "display": "Active" - * } - * } - * }, - * "verificationStatus": { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/allergyintolerance-verification", - * "code": "confirmed", - * "display": "Confirmed" - * } - * } - * }, - * "category": { - * "medication" - * }, - * "criticality": "low", - * "code": { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/data-absent-reason", - * "code": "unknown", - * "display": "Unknown" - * } - * } - * }, - * "patient": { - * "reference": "Patient/94682ef5-b0e3-4289-b19a-11b9592e9c92" - * }, - * "reaction": { - * { - * "manifestation": { - * { - * "coding": { - * { - * "system": "http://snomed.info/sct", - * "code": "422587007", - * "display": "Nausea" - * } - * }, - * "text": "Nausea" - * } - * } - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/AllergyIntolerance/:uuid" => function ($uuid, HttpRestRequest $request) { - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirAllergyIntoleranceRestController($request))->getOne($uuid, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("patients", "med"); - $return = (new FhirAllergyIntoleranceRestController($request))->getOne($uuid); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Appointment", - * description="Returns a list of Appointment resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the Appointment resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="patient", - * in="query", - * description="The uuid for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/AllergyIntolerance" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Appointment" => function (HttpRestRequest $request) { - $getParams = $request->getQueryParams(); - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirAppointmentRestController($request))->getAll($getParams, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("patients", "appt"); - $return = (new FhirAppointmentRestController($request))->getAll($getParams); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Appointment/{uuid}", - * description="Returns a single Appointment resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the Appointment resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={} - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Appointment/:uuid" => function ($uuid, HttpRestRequest $request) { - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirAppointmentRestController($request))->getOne($uuid, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("patients", "appt"); - $return = (new FhirAppointmentRestController($request))->getOne($uuid); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/CarePlan", - * description="Returns a list of CarePlan resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the CarePlan resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="patient", - * in="query", - * description="The uuid for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="category", - * in="query", - * description="The category of the CarePlan resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/CarePlan" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/CarePlan" => function (HttpRestRequest $request) { - $getParams = $request->getQueryParams(); - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirCarePlanRestController())->getAll($getParams, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("patients", "med"); - $return = (new FhirCarePlanRestController())->getAll($getParams); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/CarePlan/{uuid}", - * description="Returns a single CarePlan resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the CarePlan resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "94682f08-8fbc-451e-b1ec-f922d765c38f_1", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2021-09-16T00:54:18+00:00" - * }, - * "resourceType": "CarePlan", - * "text": { - * "status": "generated", - * "div": "

Treat flu.

" - * }, - * "status": "active", - * "intent": "plan", - * "category": { - * { - * "coding": { - * { - * "system": "http://hl7.org/fhir/us/core/CodeSystem/careplan-category", - * "code": "assess-plan" - * } - * } - * } - * }, - * "description": "Treat flu.", - * "subject": { - * "reference": "Patient/94682ef5-b0e3-4289-b19a-11b9592e9c92", - * "type": "Patient" - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/CarePlan/:uuid" => function ($uuid, HttpRestRequest $request) { - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirCarePlanRestController())->getOne($uuid, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("patients", "med"); - $return = (new FhirCarePlanRestController())->getOne($uuid); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/CareTeam", - * description="Returns a list of CareTeam resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the CareTeam resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="patient", - * in="query", - * description="The uuid for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="status", - * in="query", - * description="The status of the CarePlan resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/CareTeam" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/CareTeam" => function (HttpRestRequest $request) { - $getParams = $request->getQueryParams(); - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirCareTeamRestController())->getAll($getParams, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("patients", "med"); - $return = (new FhirCareTeamRestController())->getAll($getParams); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/CareTeam/{uuid}", - * description="Returns a single CareTeam resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the CareTeam resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "94682f09-69fe-4ada-8ea6-753a52bd1516", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2021-09-16T01:07:22+00:00" - * }, - * "resourceType": "CareTeam", - * "status": "active", - * "subject": { - * "reference": "Patient/94682ef5-b0e3-4289-b19a-11b9592e9c92", - * "type": "Patient" - * }, - * "participant": { - * { - * "role": { - * { - * "coding": { - * { - * "system": "http://nucc.org/provider-taxonomy", - * "code": "102L00000X", - * "display": "Psychoanalyst" - * } - * } - * } - * }, - * "member": { - * "reference": "Practitioner/94682c68-f712-4c39-9158-ff132a08f26b", - * "type": "Practitioner" - * }, - * "onBehalfOf": { - * "reference": "Organization/94682c62-b801-4498-84a1-13f158bb2a18", - * "type": "Organization" - * } - * }, - * { - * "role": { - * { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/data-absent-reason", - * "code": "unknown", - * "display": "Unknown" - * } - * } - * } - * }, - * "member": { - * "reference": "Organization/94682c62-b801-4498-84a1-13f158bb2a18", - * "type": "Organization" - * } - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/CareTeam/:uuid" => function ($uuid, HttpRestRequest $request) { - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirCareTeamRestController())->getOne($uuid, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("patients", "med"); - $return = (new FhirCareTeamRestController())->getOne($uuid); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Condition", - * description="Returns a list of Condition resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the Condition resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="patient", - * in="query", - * description="The uuid for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/Condition" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Condition" => function (HttpRestRequest $request) { - $getParams = $request->getQueryParams(); - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirConditionRestController())->getAll($getParams, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("patients", "med"); - $return = (new FhirConditionRestController())->getAll($getParams); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Condition/{uuid}", - * description="Returns a single Condition resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the Condition resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "94682c68-e5bb-4c5c-859a-cebaa5a1e582", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2021-09-16T02:41:53+00:00" - * }, - * "resourceType": "Condition", - * "clinicalStatus": { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/condition-clinical", - * "code": "inactive", - * "display": "Inactive" - * } - * } - * }, - * "verificationStatus": { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/condition-ver-status", - * "code": "unconfirmed", - * "display": "Unconfirmed" - * } - * } - * }, - * "category": { - * { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/condition-category", - * "code": "problem-list-item", - * "display": "Problem List Item" - * } - * } - * } - * }, - * "code": { - * "coding": { - * { - * "system": "http://snomed.info/sct", - * "code": "444814009", - * "display": "" - * } - * } - * }, - * "subject": { - * "reference": "Patient/94682c62-d37e-48b5-8018-c5f6f3566609" - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Condition/:uuid" => function ($uuid, HttpRestRequest $request) { - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirConditionRestController())->getOne($uuid, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("patients", "med"); - $return = (new FhirConditionRestController())->getOne($uuid); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Coverage", - * description="Returns a list of Coverage resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the Coverage resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="patient", - * in="query", - * description="The uuid for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="payor", - * in="query", - * description="The payor of the Coverage resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/Coverage" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Coverage" => function (HttpRestRequest $request) { - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirCoverageRestController())->getAll($request->getQueryParams(), $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("admin", "super"); - $return = (new FhirCoverageRestController())->getAll($request->getQueryParams()); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Coverage/{uuid}", - * description="Returns a single Coverage resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the Coverage resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "960d5f10-edc6-4c65-a6d4-39a1e1da87a8", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2022-04-14T07:58:45+00:00" - * }, - * "resourceType": "Coverage", - * "status": "active", - * "beneficiary": { - * "reference": "Patient/960d5f08-9fdf-4bdc-9108-84a149e28bac" - * }, - * "relationship": { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/subscriber-relationship", - * "code": "" - * } - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Coverage/:uuid" => function ($uuid, HttpRestRequest $request) { - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirCoverageRestController())->getOne($uuid, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("admin", "super"); - $return = (new FhirCoverageRestController())->getOne($uuid); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Device", - * description="Returns a list of Device resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the Device resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="patient", - * in="query", - * description="The uuid for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/Device" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Device" => function (HttpRestRequest $request) { - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirDeviceRestController())->getAll($request->getQueryParams(), $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("admin", "super"); - $return = (new FhirDeviceRestController())->getAll($request->getQueryParams()); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Device/{uuid}", - * description="Returns a single Device resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the Device resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "946dce19-c80a-402c-862a-eadf3f2377f0", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2021-09-18T19:28:59+00:00" - * }, - * "resourceType": "Device", - * "udiCarrier": { - * { - * "deviceIdentifier": "08717648200274", - * "carrierHRF": "=/08717648200274=,000025=A99971312345600=>014032=}013032&,1000000000000XYZ123" - * } - * }, - * "distinctIdentifier": "A99971312345600", - * "manufactureDate": "2013-02-01", - * "expirationDate": "2014-02-01", - * "lotNumber": "000000000000XYZ123", - * "serialNumber": "000025", - * "type": { - * "extension": { - * { - * "valueCode": "unknown", - * "url": "http://hl7.org/fhir/StructureDefinition/data-absent-reason" - * } - * } - * }, - * "patient": { - * "reference": "Patient/946da619-c631-431a-a282-487cd6fb7802", - * "type": "Patient" - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Device/:uuid" => function ($uuid, HttpRestRequest $request) { - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirDeviceRestController())->getOne($uuid, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("admin", "super"); - $return = (new FhirDeviceRestController())->getOne($uuid); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/DiagnosticReport", - * description="Returns a list of DiagnosticReport resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the DiagnosticReport resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="patient", - * in="query", - * description="The uuid for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="code", - * in="query", - * description="The code of the DiagnosticReport resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="category", - * in="query", - * description="The category of the DiagnosticReport resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="date", - * in="query", - * description="The datetime of the DiagnosticReport resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/DiagnosticReport" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/DiagnosticReport" => function (HttpRestRequest $request) { - $getParams = $request->getQueryParams(); - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirDiagnosticReportRestController())->getAll($getParams, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("admin", "super"); - $return = (new FhirDiagnosticReportRestController())->getAll($getParams); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/DiagnosticReport/{uuid}", - * description="Returns a single DiagnosticReport resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the DiagnosticReport resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "93fb2d6a-77ac-48ca-a12d-1a17e40007e3", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2021-09-18T20:52:34+00:00" - * }, - * "resourceType": "DiagnosticReport", - * "status": "final", - * "category": { - * { - * "coding": { - * { - * "system": "http://loinc.org", - * "code": "LP7839-6", - * "display": "Pathology" - * } - * } - * } - * }, - * "code": { - * "coding": { - * { - * "system": "http://loinc.org", - * "code": "11502-2", - * "display": "Laboratory report" - * } - * } - * }, - * "subject": { - * "reference": "Patient/9353b8f5-0a87-4e2a-afd4-25341fdb0fbc", - * "type": "Patient" - * }, - * "encounter": { - * "reference": "Encounter/93540818-cb5f-49df-b73b-83901bb793b6", - * "type": "Encounter" - * }, - * "effectiveDateTime": "2015-06-22T00:00:00+00:00", - * "issued": "2015-06-22T00:00:00+00:00", - * "performer": { - * { - * "reference": "Organization/935249b5-0ba6-4b5b-8863-a7a27d4c6350", - * "type": "Organization" - * } - * }, - * "presentedForm": { - * { - * "contentType": "text/plain", - * "data": "TXMgQWxpY2UgTmV3bWFuIHdhcyB0ZXN0ZWQgZm9yIHRoZSBVcmluYW5hbHlzaXMgbWFjcm8gcGFuZWwgYW5kIHRoZSByZXN1bHRzIGhhdmUgYmVlbiBmb3VuZCB0byBiZSANCm5vcm1hbC4=" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/DiagnosticReport/:uuid" => function ($uuid, HttpRestRequest $request) { - $getParams = $request->getQueryParams(); - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirDiagnosticReportRestController())->getOne($uuid, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("admin", "super"); - $return = (new FhirDiagnosticReportRestController())->getOne($uuid); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/DocumentReference", - * description="Returns a list of DocumentReference resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the DocumentReference resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="patient", - * in="query", - * description="The uuid for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="type", - * in="query", - * description="The type of the DocumentReference resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="category", - * in="query", - * description="The category of the DocumentReference resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="date", - * in="query", - * description="The datetime of the DocumentReference resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/DocumentReference" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - 'GET /fhir/DocumentReference' => function (HttpRestRequest $request) { - $getParams = $request->getQueryParams(); - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirDocumentReferenceRestController($request))->getAll($getParams, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("admin", "super"); - $return = (new FhirDocumentReferenceRestController($request))->getAll($getParams); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\POST( - * path="/fhir/DocumentReference/$docref", - * description="The $docref operation is used to request the server generates a document based on the specified parameters. If no additional parameters are specified then a DocumentReference to the patient's most current Clinical Summary of Care Document (CCD) is returned. The document itself is retrieved using the DocumentReference.content.attachment.url element. See http://hl7.org/fhir/us/core/OperationDefinition-docref.html for more details.", - * tags={"fhir"}, - * @OA\ExternalDocumentation(description="Detailed documentation on this operation", url="https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API"), - * @OA\Parameter( - * name="patient", - * in="query", - * description="The uuid for the patient.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="start", - * in="query", - * description="The datetime refers to care dates not record currency dates. All records relating to care provided in a certain date range. If no start date is provided then all documents prior to the end date are in scope. If no start and end date are provided, the most recent or current document is in scope.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="end", - * in="query", - * description="The datetime refers to care dates not record currency dates. All records relating to care provided in a certain date range. If no end date is provided then all documents subsequent to the start date are in scope. If no start and end date are provided, the most recent or current document is in scope.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="type", - * in="query", - * description="The type refers to the document type. This is a LOINC code from the valueset of http://hl7.org/fhir/R4/valueset-c80-doc-typecodes.html. The server currently only supports the LOINC code of 34133-9 (Summary of episode node).", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="A search bundle of DocumentReferences is returned" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - 'POST /fhir/DocumentReference/$docref' => function (HttpRestRequest $request) { - - // NOTE: The order of this route is IMPORTANT as it needs to come before the DocumentReference single request. - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirOperationDocRefRestController($request))->getAll($request->getQueryParams(), $request->getPatientUUIDString()); - } else { - // TODO: it seems like regular users should be able to grab authorship / provenance information - RestConfig::authorization_check("patients", "demo"); - $return = (new FhirOperationDocRefRestController($request))->getAll($request->getQueryParams()); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/DocumentReference/{uuid}", - * description="Returns a single DocumentReference resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the DocumentReference resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "946e7553-1aaa-49f8-8f81-ae15ccaa9165", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2021-09-19T03:17:51+00:00" - * }, - * "resourceType": "DocumentReference", - * "identifier": { - * { - * "value": "946e7553-1aaa-49f8-8f81-ae15ccaa9165" - * } - * }, - * "status": "current", - * "type": { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/v3-NullFlavor", - * "code": "UNK", - * "display": "unknown" - * } - * } - * }, - * "category": { - * { - * "coding": { - * { - * "system": "https://localhost:9300/apis/default/fhir/ValueSet/openemr-document-types", - * "code": "openemr-document", - * "display": "OpenEMR Document" - * } - * } - * } - * }, - * "subject": { - * "reference": "Patient/946da619-c631-431a-a282-487cd6fb7802", - * "type": "Patient" - * }, - * "date": "2021-09-19T03:15:56+00:00", - * "author": { - * null - * }, - * "content": { - * { - * "attachment": { - * "contentType": "image/gif", - * "url": "https://localhost:9300/apis/default/fhir/Binary/7" - * }, - * "format": { - * "system": "http://ihe.net/fhir/ValueSet/IHE.FormatCode.codesystem", - * "code": "urn:ihe:iti:xds:2017:mimeTypeSufficient", - * "display": "mimeType Sufficient" - * } - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/DocumentReference/:uuid" => function ($uuid, HttpRestRequest $request) { - $getParams = $request->getQueryParams(); - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirDocumentReferenceRestController($request))->getOne($uuid, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("admin", "super"); - $return = (new FhirDocumentReferenceRestController($request))->getOne($uuid); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Binary/{id}", - * description="Used for downloading binary documents generated either with BULK FHIR Export or with the $docref CCD export operation. Documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API", - * tags={"fhir"}, - * @OA\Parameter( - * name="id", - * in="path", - * description="The id for the Document.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="The documentation for working with BULK FHIR or $docref document exports can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - 'GET /fhir/Binary/:id' => function ($documentId, HttpRestRequest $request) { - $docController = new \OpenEMR\RestControllers\FHIR\FhirDocumentRestController($request); - - if ($request->isPatientRequest()) { - $response = $docController->downloadDocument($documentId, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("admin", "users"); - $response = $docController->downloadDocument($documentId); - } - - return $response; - }, - - /** - * @OA\Get( - * path="/fhir/Encounter", - * description="Returns a list of Encounter resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the Encounter resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="patient", - * in="query", - * description="The uuid for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="date", - * in="query", - * description="The datetime of the Encounter resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/Encounter" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Encounter" => function (HttpRestRequest $request) { - $getParams = $request->getQueryParams(); - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirEncounterRestController())->getAll($getParams, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("encounters", "auth_a"); - $return = (new FhirEncounterRestController())->getAll($getParams); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Encounter/{uuid}", - * description="Returns a single Encounter resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the Encounter resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "946da61d-6b95-4f8e-abe5-534a25913b71", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2021-09-19T06:27:41+00:00" - * }, - * "resourceType": "Encounter", - * "identifier": { - * { - * "system": "urn:ietf:rfc:3986", - * "value": "946da61d-6b95-4f8e-abe5-534a25913b71" - * } - * }, - * "status": "finished", - * "class": { - * "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", - * "code": "AMB", - * "display": "ambulatory" - * }, - * "type": { - * { - * "coding": { - * { - * "system": "http://snomed.info/sct", - * "code": "185349003", - * "display": "Encounter for check up (procedure)" - * } - * } - * } - * }, - * "subject": { - * "reference": "Patient/946da61b-626b-4f88-81e2-adfb88f4f0fe", - * "type": "Patient" - * }, - * "participant": { - * { - * "type": { - * { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/v3-ParticipationType", - * "code": "PPRF", - * "display": "Primary Performer" - * } - * } - * } - * }, - * "period": { - * "start": "2012-08-13T00:00:00+00:00" - * }, - * "individual": { - * "reference": "Practitioner/946da61d-ac5f-4fdc-b3f2-7b58dc49976b", - * "type": "Practitioner" - * } - * } - * }, - * "period": { - * "start": "2012-08-13T00:00:00+00:00" - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Encounter/:uuid" => function ($uuid, HttpRestRequest $request) { - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirEncounterRestController())->getOne($uuid, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("admin", "super"); - $return = (new FhirEncounterRestController())->getOne($uuid); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Goal", - * description="Returns a list of Condition resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the Goal resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="patient", - * in="query", - * description="The uuid for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/Goal" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Goal" => function (HttpRestRequest $request) { - $getParams = $request->getQueryParams(); - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirGoalRestController())->getAll($getParams, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("admin", "super"); - $return = (new FhirGoalRestController())->getAll($getParams); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Goal/{uuid}", - * description="Returns a single Goal resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the Goal resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "946da61d-6b88-4d54-bdd6-4029e2ad9e3f_1", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2021-09-19T06:45:58+00:00" - * }, - * "resourceType": "Goal", - * "lifecycleStatus": "active", - * "description": { - * "text": "Eating more vegetables." - * }, - * "subject": { - * "reference": "Patient/946da619-c631-431a-a282-487cd6fb7802", - * "type": "Patient" - * }, - * "target": { - * { - * "measure": { - * "extension": { - * { - * "valueCode": "unknown", - * "url": "http://hl7.org/fhir/StructureDefinition/data-absent-reason" - * } - * } - * }, - * "detailString": "Eating more vegetables.", - * "dueDate": "2021-09-09" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Goal/:uuid" => function ($uuid, HttpRestRequest $request) { - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirGoalRestController())->getOne($uuid, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("admin", "super"); - $return = (new FhirGoalRestController())->getOne($uuid); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Group", - * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the Group resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="patient", - * in="query", - * description="The uuid for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/Group" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - 'GET /fhir/Group' => function (HttpRestRequest $request) { - RestConfig::authorization_check("admin", "users"); - $getParams = $request->getQueryParams(); - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirGroupRestController())->getAll($getParams, $request->getPatientUUIDString()); - } else { - $return = (new FhirGroupRestController())->getAll($getParams); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Group/{uuid}", - * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the Group resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Group/:uuid" => function ($uuid, HttpRestRequest $request) { - RestConfig::authorization_check("admin", "users"); - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirGroupRestController())->getOne($uuid, $request->getPatientUUIDString()); - } else { - $return = (new FhirGroupRestController())->getOne($uuid); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Group/{id}/$export", - * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API", - * tags={"fhir"}, - * @OA\Parameter( - * name="id", - * in="path", - * description="The id for the Group resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - 'GET /fhir/Group/:id/$export' => function ($groupId, HttpRestRequest $request) { - RestConfig::authorization_check("admin", "users"); - $fhirExportService = new FhirOperationExportRestController($request); - $exportParams = $request->getQueryParams(); - $exportParams['groupId'] = $groupId; - $return = $fhirExportService->processExport( - $exportParams, - 'Group', - $request->getHeader('Accept')[0] ?? '', - $request->getHeader('Prefer')[0] ?? '' - ); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Immunization", - * description="Returns a list of Immunization resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the Immunization resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="patient", - * in="query", - * description="The uuid for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/Immunization" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Immunization" => function (HttpRestRequest $request) { - $getParams = $request->getQueryParams(); - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirImmunizationRestController())->getAll($getParams, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("patients", "med"); - $return = (new FhirImmunizationRestController())->getAll($getParams); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Immunization/{uuid}", - * description="Returns a single Immunization resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the Immunization resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "95e8d8b7-e3e2-4e03-8eb1-31e1d9097d8f", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2022-03-26T05:42:59+00:00" - * }, - * "resourceType": "Immunization", - * "status": "completed", - * "vaccineCode": { - * "coding": { - * { - * "system": "http://hl7.org/fhir/sid/cvx", - * "code": "207", - * "display": "SARS-COV-2 (COVID-19) vaccine, mRNA, spike protein, LNP, preservative free, 100 mcg/0.5mL dose" - * } - * } - * }, - * "patient": { - * "reference": "Patient/95e8d830-3068-48cf-930a-2fefb18c2bcf" - * }, - * "occurrenceDateTime": "2022-03-26T05:35:00+00:00", - * "recorded": "2022-03-26T05:42:26+00:00", - * "primarySource": false - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Immunization/:uuid" => function ($uuid, HttpRestRequest $request) { - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirImmunizationRestController())->getOne($uuid, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("patients", "med"); - $return = (new FhirImmunizationRestController())->getOne($uuid); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Location", - * description="Returns a list of Location resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the Location resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/Location" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Location" => function (HttpRestRequest $request) { - $return = (new FhirLocationRestController())->getAll($request->getQueryParams(), $request->getPatientUUIDString()); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Location/{uuid}", - * description="Returns a single Location resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the Location resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "946da61d-c4f2-4f03-a2a7-b571f6a24b65", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2021-09-19T08:14:58+00:00" - * }, - * "resourceType": "Location", - * "status": "active", - * "name": "Your Clinic Name Here", - * "telecom": { - * { - * "system": "phone", - * "value": "000-000-0000" - * }, - * { - * "system": "fax", - * "value": "000-000-0000" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Location/:uuid" => function ($uuid, HttpRestRequest $request) { - $return = (new FhirLocationRestController())->getOne($uuid, $request->getPatientUUIDString()); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Medication", - * description="Returns a list of Medication resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the Medication resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/Medication" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Medication" => function (HttpRestRequest $request) { - RestConfig::authorization_check("patients", "med"); - $return = (new FhirMedicationRestController())->getAll($request->getQueryParams()); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Medication/{uuid}", - * description="Returns a single Medication resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the Medication resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "961aa334-9348-4145-8252-de665e3c4afa", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2022-04-19T23:42:14+00:00" - * }, - * "resourceType": "Medication", - * "code": { - * "coding": { - * { - * "system": "http://www.nlm.nih.gov/research/umls/rxnorm", - * "code": 153165 - * } - * } - * }, - * "status": "active", - * "batch": { - * "lotNumber": "132", - * "expirationDate": "0000-00-00" - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Medication/:uuid" => function ($uuid, HttpRestRequest $request) { - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirMedicationRestController())->getOne($uuid, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("patients", "med"); - $return = (new FhirMedicationRestController())->getOne($uuid); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/MedicationRequest", - * description="Returns a list of MedicationRequest resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the MedicationRequest resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="patient", - * in="query", - * description="The uuid for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="intent", - * in="query", - * description="The intent of the MedicationRequest resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="status", - * in="query", - * description="The status of the MedicationRequest resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/MedicationRequest" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/MedicationRequest" => function (HttpRestRequest $request) { - $getParams = $request->getQueryParams(); - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirMedicationRequestRestController())->getAll($getParams, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("patients", "med"); - $return = (new FhirMedicationRequestRestController())->getAll($getParams); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/MedicationRequest/{uuid}", - * description="Returns a single MedicationRequest resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the MedicationRequest resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "946da61d-9cff-4416-8d27-805f19f9d7d8", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2021-09-20T04:03:14+00:00" - * }, - * "resourceType": "MedicationRequest", - * "status": "active", - * "intent": "order", - * "category": { - * { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-category", - * "code": "community", - * "display": "Home/Community" - * } - * } - * } - * }, - * "reportedBoolean": false, - * "medicationCodeableConcept": { - * "coding": { - * { - * "system": "http://www.nlm.nih.gov/research/umls/rxnorm", - * "code": "1738139", - * "display": "Acetaminophen 325 MG Oral Tablet" - * } - * } - * }, - * "subject": { - * "reference": "Patient/946da617-1a4a-4b2c-ae66-93b84377cb1e", - * "type": "Patient" - * }, - * "authoredOn": "2021-09-18T00:00:00+00:00", - * "requester": { - * "reference": "Practitioner/946da61d-ac5f-4fdc-b3f2-7b58dc49976b", - * "type": "Practitioner" - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/MedicationRequest/:uuid" => function ($uuid, HttpRestRequest $request) { - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirMedicationRequestRestController())->getOne($uuid, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("patients", "med"); - $return = (new FhirMedicationRequestRestController())->getOne($uuid); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Observation", - * description="Returns a list of Observation resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the Observation resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="patient", - * in="query", - * description="The uuid for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="code", - * in="query", - * description="The code of the Observation resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="category", - * in="query", - * description="The category of the Observation resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="date", - * in="query", - * description="The datetime of the Observation resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/Observation" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Observation" => function (HttpRestRequest $request) { - $getParams = $request->getQueryParams(); - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirObservationRestController())->getAll($getParams, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("patients", "med"); - $return = (new FhirObservationRestController())->getAll($getParams); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Observation/{uuid}", - * description="Returns a single Observation resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the Observation resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "946da61e-0597-485e-9dfd-a87205ea56b3", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2021-09-20T04:12:16+00:00" - * }, - * "resourceType": "Observation", - * "status": "final", - * "category": { - * { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/observation-category", - * "code": "vital-signs" - * } - * } - * } - * }, - * "code": { - * "coding": { - * { - * "system": "http://loinc.org", - * "code": "85354-9", - * "display": "Blood pressure systolic and diastolic" - * } - * } - * }, - * "subject": { - * "reference": "Patient/946da619-c631-431a-a282-487cd6fb7802", - * "type": "Patient" - * }, - * "effectiveDateTime": "2015-08-31T00:00:00+00:00", - * "component": { - * { - * "code": { - * "coding": { - * { - * "system": "http://loinc.org", - * "code": "8480-6", - * "display": "Systolic blood pressure" - * } - * } - * }, - * "valueQuantity": { - * "value": 122, - * "unit": "mm[Hg]", - * "system": "http://unitsofmeasure.org", - * "code": "mm[Hg]" - * } - * }, - * { - * "code": { - * "coding": { - * { - * "system": "http://loinc.org", - * "code": "8462-4", - * "display": "Diastolic blood pressure" - * } - * } - * }, - * "valueQuantity": { - * "value": 77, - * "unit": "mm[Hg]", - * "system": "http://unitsofmeasure.org", - * "code": "mm[Hg]" - * } - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Observation/:uuid" => function ($uuid, HttpRestRequest $request) { - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirObservationRestController())->getOne($uuid, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("patients", "med"); - $return = (new FhirObservationRestController())->getOne($uuid); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Organization", - * description="Returns a list of Organization resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the Organization resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="name", - * in="query", - * description="The name of the Organization resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="email", - * in="query", - * description="The email of the Organization resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="phone", - * in="query", - * description="The phone of the Organization resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="telecom", - * in="query", - * description="The telecom of the Organization resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="address", - * in="query", - * description="The address of the Organization resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="address-city", - * in="query", - * description="The address-city of the Organization resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="address-postalcode", - * in="query", - * description="The address-postalcode of the Organization resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="address-state", - * in="query", - * description="The address-state of the Organization resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/Organization" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Organization" => function (HttpRestRequest $request) { - if (!$request->isPatientRequest()) { - RestConfig::authorization_check("admin", "users"); - } - $return = (new FhirOrganizationRestController())->getAll($request->getQueryParams()); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Organization/{uuid}", - * description="Returns a single Organization resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the Organization resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "95f0e672-be37-4c73-95c9-649c2d200018", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2022-03-30T07:43:23+00:00" - * }, - * "resourceType": "Organization", - * "text": { - * "status": "generated", - * "div": "

Your Clinic Name Here

" - * }, - * "identifier": { - * { - * "system": "http://hl7.org/fhir/sid/us-npi", - * "value": "1234567890" - * } - * }, - * "active": true, - * "type": { - * { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/organization-type", - * "code": "prov", - * "display": "Healthcare Provider" - * } - * } - * } - * }, - * "name": "Your Clinic Name Here", - * "telecom": { - * { - * "system": "phone", - * "value": "000-000-0000", - * "use": "work" - * }, - * { - * "system": "fax", - * "value": "000-000-0000", - * "use": "work" - * } - * }, - * "address": { - * null - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Organization/:uuid" => function ($uuid, HttpRestRequest $request) { - $patientUUID = null; - if (!$request->isPatientRequest()) { - RestConfig::authorization_check("admin", "users"); - } else { - $patientUUID = $request->getPatientUUIDString(); - } - $return = (new FhirOrganizationRestController())->getOne($uuid, $patientUUID); - - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Post( - * path="/fhir/Organization", - * description="Adds a Organization resource.", - * tags={"fhir"}, - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * description="The json object for the Organization resource.", - * type="object" - * ), - * example={ - * "id": "95f0e672-be37-4c73-95c9-649c2d200018", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2022-03-30T07:43:23+00:00" - * }, - * "resourceType": "Organization", - * "text": { - * "status": "generated", - * "div": "

Your Clinic Name Here

" - * }, - * "identifier": { - * { - * "system": "http://hl7.org/fhir/sid/us-npi", - * "value": "1234567890" - * } - * }, - * "active": true, - * "type": { - * { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/organization-type", - * "code": "prov", - * "display": "Healthcare Provider" - * } - * } - * } - * }, - * "name": "Your Clinic Name Here Hey", - * "telecom": { - * { - * "system": "phone", - * "value": "000-000-0000", - * "use": "work" - * }, - * { - * "system": "fax", - * "value": "000-000-0000", - * "use": "work" - * } - * }, - * "address": { - * null - * } - * } - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "95f0e672-be37-4c73-95c9-649c2d200018", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2022-03-30T07:43:23+00:00" - * }, - * "resourceType": "Organization", - * "text": { - * "status": "generated", - * "div": "

Your Clinic Name Here

" - * }, - * "identifier": { - * { - * "system": "http://hl7.org/fhir/sid/us-npi", - * "value": "1234567890" - * } - * }, - * "active": true, - * "type": { - * { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/organization-type", - * "code": "prov", - * "display": "Healthcare Provider" - * } - * } - * } - * }, - * "name": "Your Clinic Name Here Now", - * "telecom": { - * { - * "system": "phone", - * "value": "000-000-0000", - * "use": "work" - * }, - * { - * "system": "fax", - * "value": "000-000-0000", - * "use": "work" - * } - * }, - * "address": { - * null - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "POST /fhir/Organization" => function (HttpRestRequest $request) { - RestConfig::authorization_check("admin", "super"); - $data = (array) (json_decode(file_get_contents("php://input"), true)); - $return = (new FhirOrganizationRestController())->post($data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Put( - * path="/fhir/Organization/{uuid}", - * description="Modifies a Organization resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the organization.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * description="The json object for the Organization resource.", - * type="object" - * ), - * example={ - * "id": "95f0e672-be37-4c73-95c9-649c2d200018", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2022-03-30T07:43:23+00:00" - * }, - * "resourceType": "Organization", - * "text": { - * "status": "generated", - * "div": "

Your Clinic Name Here

" - * }, - * "identifier": { - * { - * "system": "http://hl7.org/fhir/sid/us-npi", - * "value": "1234567890" - * } - * }, - * "active": true, - * "type": { - * { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/organization-type", - * "code": "prov", - * "display": "Healthcare Provider" - * } - * } - * } - * }, - * "name": "Your Clinic Name Here", - * "telecom": { - * { - * "system": "phone", - * "value": "000-000-0000", - * "use": "work" - * }, - * { - * "system": "fax", - * "value": "000-000-0000", - * "use": "work" - * } - * }, - * "address": { - * null - * } - * } - * ) - * ), - * @OA\Response( - * response="201", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * example={ - * "id": 14, - * "uuid": "95f217c1-258c-44ca-bf11-909dce369574" - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "PUT /fhir/Organization/:uuid" => function ($uuid, HttpRestRequest $request) { - RestConfig::authorization_check("admin", "super"); - $data = (array) (json_decode(file_get_contents("php://input"), true)); - $return = (new FhirOrganizationRestController())->patch($uuid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Post( - * path="/fhir/Patient", - * description="Adds a Patient resource.", - * tags={"fhir"}, - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * description="The json object for the Patient resource.", - * type="object" - * ), - * example={ - * "id": "95f22ff4-dd25-4290-8b52-1dd2fedf8e54", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2022-03-31T02:48:28+00:00" - * }, - * "resourceType": "Patient", - * "text": { - * "status": "generated", - * "div": "

Brenda Smith

" - * }, - * "extension": { - * { - * "valueCode": "F", - * "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex" - * }, - * { - * "extension": { - * { - * "valueCoding": { - * "system": "http://terminology.hl7.org/CodeSystem/v3-NullFlavor", - * "code": "UNK", - * "display": "Unknown" - * }, - * "url": "ombCategory" - * }, - * { - * "valueString": "Unknown", - * "url": "text" - * } - * }, - * "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race" - * } - * }, - * "identifier": { - * { - * "use": "official", - * "type": { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/v2-0203", - * "code": "PT" - * } - * } - * }, - * "system": "http://terminology.hl7.org/CodeSystem/v2-0203", - * "value": "1" - * } - * }, - * "active": true, - * "name": { - * { - * "use": "official", - * "family": "Smith", - * "given": { - * "Brenda" - * } - * } - * }, - * "gender": "female", - * "birthDate": "2017-03-10", - * "communication": { - * { - * "language": { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/data-absent-reason", - * "code": "unknown", - * "display": "Unknown" - * } - * } - * } - * } - * } - * } - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "95f22ff4-dd25-4290-8b52-1dd2fedf8e54", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2022-03-31T02:48:28+00:00" - * }, - * "resourceType": "Patient", - * "text": { - * "status": "generated", - * "div": "

Brenda Smith

" - * }, - * "extension": { - * { - * "valueCode": "F", - * "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex" - * }, - * { - * "extension": { - * { - * "valueCoding": { - * "system": "http://terminology.hl7.org/CodeSystem/v3-NullFlavor", - * "code": "UNK", - * "display": "Unknown" - * }, - * "url": "ombCategory" - * }, - * { - * "valueString": "Unknown", - * "url": "text" - * } - * }, - * "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race" - * } - * }, - * "identifier": { - * { - * "use": "official", - * "type": { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/v2-0203", - * "code": "PT" - * } - * } - * }, - * "system": "http://terminology.hl7.org/CodeSystem/v2-0203", - * "value": "1" - * } - * }, - * "active": true, - * "name": { - * { - * "use": "official", - * "family": "Smith", - * "given": { - * "Brenda" - * } - * } - * }, - * "gender": "female", - * "birthDate": "2017-03-10", - * "communication": { - * { - * "language": { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/data-absent-reason", - * "code": "unknown", - * "display": "Unknown" - * } - * } - * } - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "POST /fhir/Patient" => function (HttpRestRequest $request) { - RestConfig::authorization_check("patients", "demo"); - $data = (array) (json_decode(file_get_contents("php://input"), true)); - $return = (new FhirPatientRestController())->post($data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Put( - * path="/fhir/Patient/{uuid}", - * description="Modifies a Patient resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the Patient resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * description="The json object for the Patient resource.", - * type="object" - * ), - * example={ - * "id": "95f22ff4-dd25-4290-8b52-1dd2fedf8e54", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2022-03-31T02:48:28+00:00" - * }, - * "resourceType": "Patient", - * "text": { - * "status": "generated", - * "div": "

Brenda Smith

" - * }, - * "extension": { - * { - * "valueCode": "F", - * "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex" - * }, - * { - * "extension": { - * { - * "valueCoding": { - * "system": "http://terminology.hl7.org/CodeSystem/v3-NullFlavor", - * "code": "UNK", - * "display": "Unknown" - * }, - * "url": "ombCategory" - * }, - * { - * "valueString": "Unknown", - * "url": "text" - * } - * }, - * "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race" - * } - * }, - * "identifier": { - * { - * "use": "official", - * "type": { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/v2-0203", - * "code": "PT" - * } - * } - * }, - * "system": "http://terminology.hl7.org/CodeSystem/v2-0203", - * "value": "1" - * } - * }, - * "active": true, - * "name": { - * { - * "use": "official", - * "family": "Smith", - * "given": { - * "Brenda" - * } - * } - * }, - * "gender": "female", - * "birthDate": "2017-03-10", - * "communication": { - * { - * "language": { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/data-absent-reason", - * "code": "unknown", - * "display": "Unknown" - * } - * } - * } - * } - * } - * } - * ) - * ), - * @OA\Response( - * response="201", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * example={ - * "id": 2, - * "uuid": "95f2ad04-5834-4243-8838-e396a7faadbf" - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "PUT /fhir/Patient/:uuid" => function ($uuid, HttpRestRequest $request) { - RestConfig::authorization_check("patients", "demo"); - $data = (array) (json_decode(file_get_contents("php://input"), true)); - $return = (new FhirPatientRestController())->put($uuid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Patient", - * description="Returns a list of Patient resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the Patient resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="identifier", - * in="query", - * description="The identifier of the Patient resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="name", - * in="query", - * description="The name of the Patient resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="birthdate", - * in="query", - * description="The birthdate of the Patient resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="gender", - * in="query", - * description="The gender of the Patient resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="address", - * in="query", - * description="The address of the Patient resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="address-city", - * in="query", - * description="The address-city of the Patient resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="address-postalcode", - * in="query", - * description="The address-postalcode of the Patient resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="address-state", - * in="query", - * description="The address-state of the Patient resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="email", - * in="query", - * description="The email of the Patient resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="family", - * in="query", - * description="The family name of the Patient resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="given", - * in="query", - * description="The given name of the Patient resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="phone", - * in="query", - * description="The phone number of the Patient resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="telecom", - * in="query", - * description="The fax number of the Patient resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * ref="#/components/parameters/_lastUpdated" - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/Patient" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Patient" => function (HttpRestRequest $request) { - $params = $request->getQueryParams(); - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - // Note in Patient context still have to return a bundle even if it is just one resource. (ie. - // need to use getAll rather than getOne) - $params['_id'] = $request->getPatientUUIDString(); - $return = (new FhirPatientRestController())->getAll($params, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("patients", "demo"); - $return = (new FhirPatientRestController())->getAll($params); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Patient/$export", - * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API", - * tags={"fhir"}, - * @OA\Response( - * response="200", - * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - // we have to have the bulk fhir export operation here otherwise it will match $export to the patient $id - 'GET /fhir/Patient/$export' => function (HttpRestRequest $request) { - RestConfig::authorization_check("admin", "users"); - $fhirExportService = new FhirOperationExportRestController($request); - $return = $fhirExportService->processExport( - $request->getQueryParams(), - 'Patient', - $request->getHeader('Accept')[0] ?? '', - $request->getHeader('Prefer')[0] ?? '' - ); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Patient/{uuid}", - * description="Returns a single Patient resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the Patient resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "946da617-1a4a-4b2c-ae66-93b84377cb1e", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2021-09-21T17:08:03+00:00" - * }, - * "resourceType": "Patient", - * "text": { - * "status": "generated", - * "div": "

Aurore252 Von197

" - * }, - * "extension": { - * { - * "valueCode": "F", - * "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex" - * }, - * { - * "extension": { - * { - * "valueCoding": { - * "system": "urn:oid:2.16.840.1.113883.6.238", - * "code": "1006-6", - * "display": "Abenaki" - * }, - * "url": "ombCategory" - * }, - * { - * "valueString": "Abenaki", - * "url": "text" - * } - * }, - * "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race" - * }, - * { - * "extension": { - * { - * "valueString": "Declined To Specify", - * "url": "text" - * } - * }, - * "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity" - * } - * }, - * "identifier": { - * { - * "use": "official", - * "type": { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/v2-0203", - * "code": "PT" - * } - * } - * }, - * "system": "http://terminology.hl7.org/CodeSystem/v2-0203", - * "value": "1" - * } - * }, - * "active": true, - * "name": { - * { - * "use": "official", - * "family": "Von197", - * "given": { - * "Aurore252" - * } - * } - * }, - * "gender": "female", - * "birthDate": "1970-07-03", - * "address": { - * { - * "line": { - * "245 Crona Wall" - * }, - * "city": "Boston", - * "state": "Massachusetts", - * "postalCode": "02215", - * "period": { - * "start": "2020-09-21T17:08:03.532+00:00" - * } - * } - * }, - * "communication": { - * { - * "language": { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/data-absent-reason", - * "code": "unknown", - * "display": "Unknown" - * } - * } - * } - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Patient/:uuid" => function ($uuid, HttpRestRequest $request) { - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - if (empty($uuid) || ($uuid != $request->getPatientUUIDString())) { - throw new AccessDeniedException("patients", "demo", "patient id invalid"); - } - $uuid = $request->getPatientUUIDString(); - } else { - RestConfig::authorization_check("patients", "demo"); - } - $return = (new FhirPatientRestController())->getOne($uuid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Person", - * description="Returns a list of Person resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the Person resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="name", - * in="query", - * description="The name of the Person resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="active", - * in="query", - * description="The active status of the Person resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="address", - * in="query", - * description="The address of the Person resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="address-city", - * in="query", - * description="The address-city of the Person resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="address-postalcode", - * in="query", - * description="The address-postalcode of the Person resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="address-state", - * in="query", - * description="The address-state of the Person resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="email", - * in="query", - * description="The email of the Person resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="family", - * in="query", - * description="The family name of the Person resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="given", - * in="query", - * description="The given name of the Person resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="phone", - * in="query", - * description="The phone number of the Person resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="telecom", - * in="query", - * description="The fax number of the Person resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/Person" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Person" => function (HttpRestRequest $request) { - RestConfig::authorization_check("admin", "users"); - $return = (new FhirPersonRestController())->getAll($request->getQueryParams()); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Person/{uuid}", - * description="Returns a single Person resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the Person resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "960c7cd6-187a-4119-8cd4-85389d80efb9", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2022-04-13T08:57:32+00:00" - * }, - * "resourceType": "Person", - * "text": { - * "status": "generated", - * "div": "

Administrator Administrator

" - * }, - * "name": { - * { - * "use": "official", - * "family": "Administrator", - * "given": { - * "Administrator", - * "Larry" - * } - * } - * }, - * "telecom": { - * { - * "system": "phone", - * "value": "1234567890", - * "use": "home" - * }, - * { - * "system": "phone", - * "value": "1234567890", - * "use": "work" - * }, - * { - * "system": "phone", - * "value": "1234567890", - * "use": "mobile" - * }, - * { - * "system": "email", - * "value": "hey@hey.com", - * "use": "home" - * } - * }, - * "address": { - * { - * "line": { - * "123 Lane Street" - * }, - * "city": "Bellevue", - * "state": "WA", - * "period": { - * "start": "2021-04-13T08:57:32.146+00:00" - * } - * } - * }, - * "active": true - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Person/:uuid" => function ($uuid, HttpRestRequest $request) { - // if the api user is requesting their own user we need to let it through - // this is because the /Person endpoint needs to be responsive to the fhirUser return value - // for the currently logged in user - if ($request->getRequestUserUUIDString() == $uuid) { - $return = (new FhirPersonRestController())->getOne($uuid); - } elseif (!$request->isPatientRequest()) { - // not a patient ,make sure we have access to the users ACL - RestConfig::authorization_check("admin", "users"); - $return = (new FhirPersonRestController())->getOne($uuid); - } else { - // if we are a patient bound request we need to make sure we are only bound to the patient - $return = (new FhirPersonRestController())->getOne($uuid, $request->getPatientUUIDString()); - } - - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Practitioner", - * description="Returns a list of Practitioner resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the Practitioner resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="name", - * in="query", - * description="The name of the Practitioner resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="active", - * in="query", - * description="The active status of the Practitioner resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="address", - * in="query", - * description="The address of the Practitioner resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="address-city", - * in="query", - * description="The address-city of the Practitioner resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="address-postalcode", - * in="query", - * description="The address-postalcode of the Practitioner resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="address-state", - * in="query", - * description="The address-state of the Practitioner resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="email", - * in="query", - * description="The email of the Practitioner resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="family", - * in="query", - * description="The family name of the Practitioner resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="given", - * in="query", - * description="The given name of the Practitioner resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="phone", - * in="query", - * description="The phone number of the Practitioner resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="telecom", - * in="query", - * description="The fax number of the Practitioner resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/Practitioner" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Practitioner" => function (HttpRestRequest $request) { - - // TODO: @adunsulag talk with brady.miller about patients needing access to any practitioner resource - // that is referenced in connected patient resources -- such as AllergyIntollerance. - // I don't believe patients are assigned to a particular practitioner - // should we allow just open api access to admin information? Should we restrict particular pieces - // of data in the practitioner side (phone number, address information) based on a permission set? - if (!$request->isPatientRequest()) { - RestConfig::authorization_check("admin", "users"); - } - $return = (new FhirPractitionerRestController())->getAll($request->getQueryParams()); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Practitioner/{uuid}", - * description="Returns a single Practitioner resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the Practitioner resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "9473b0cf-e969-4eaa-8044-51037767fa4f", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2021-09-21T17:41:57+00:00" - * }, - * "resourceType": "Practitioner", - * "text": { - * "status": "generated", - * "div": "

Billy Smith

" - * }, - * "identifier": { - * { - * "system": "http://hl7.org/fhir/sid/us-npi", - * "value": "11223344554543" - * } - * }, - * "active": true, - * "name": { - * { - * "use": "official", - * "family": "Smith", - * "given": { - * "Billy" - * } - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Practitioner/:uuid" => function ($uuid, HttpRestRequest $request) { - // TODO: @adunsulag talk with brady.miller about patients needing access to any practitioner resource - // that is referenced in connected patient resources -- such as AllergyIntollerance. - // I don't believe patients are assigned to a particular practitioner - // should we allow just open api access to admin information? Should we restrict particular pieces - // of data in the practitioner side (phone number, address information) based on a permission set? - if (!$request->isPatientRequest()) { - RestConfig::authorization_check("admin", "users"); - } - $return = (new FhirPractitionerRestController())->getOne($uuid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Post( - * path="/fhir/Practitioner", - * description="Adds a Practitioner resources.", - * tags={"fhir"}, - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * description="The json object for the Practitioner resource.", - * type="object" - * ), - * example={ - * "id": "9473b0cf-e969-4eaa-8044-51037767fa4f", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2021-09-21T17:41:57+00:00" - * }, - * "resourceType": "Practitioner", - * "text": { - * "status": "generated", - * "div": "

Billy Smith

" - * }, - * "identifier": { - * { - * "system": "http://hl7.org/fhir/sid/us-npi", - * "value": "11223344554543" - * } - * }, - * "active": true, - * "name": { - * { - * "use": "official", - * "family": "Smith", - * "given": { - * "Danny" - * } - * } - * } - * } - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "9473b0cf-e969-4eaa-8044-51037767fa4f", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2021-09-21T17:41:57+00:00" - * }, - * "resourceType": "Practitioner", - * "text": { - * "status": "generated", - * "div": "

Billy Smith

" - * }, - * "identifier": { - * { - * "system": "http://hl7.org/fhir/sid/us-npi", - * "value": "11223344554543" - * } - * }, - * "active": true, - * "name": { - * { - * "use": "official", - * "family": "Smith", - * "given": { - * "Danny" - * } - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "POST /fhir/Practitioner" => function (HttpRestRequest $request) { - RestConfig::authorization_check("admin", "users"); - $data = (array) (json_decode(file_get_contents("php://input"), true)); - $return = (new FhirPractitionerRestController())->post($data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Put( - * path="/fhir/Practitioner/{uuid}", - * description="Modify a Practitioner resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the Practitioner resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\RequestBody( - * required=true, - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * description="The json object for the Practitioner resource.", - * type="object" - * ), - * example={ - * "id": "9473b0cf-e969-4eaa-8044-51037767fa4f", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2021-09-21T17:41:57+00:00" - * }, - * "resourceType": "Practitioner", - * "text": { - * "status": "generated", - * "div": "

Billy Smith

" - * }, - * "identifier": { - * { - * "system": "http://hl7.org/fhir/sid/us-npi", - * "value": "11223344554543" - * } - * }, - * "active": true, - * "name": { - * { - * "use": "official", - * "family": "Smith", - * "given": { - * "Billy" - * } - * } - * } - * } - * ) - * ), - * @OA\Response( - * response="201", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * example={ - * "id": 5, - * "uuid": "95f294d7-e14c-441d-81a6-309fe369ee21" - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "PUT /fhir/Practitioner/:uuid" => function ($uuid, HttpRestRequest $request) { - RestConfig::authorization_check("admin", "users"); - $data = (array) (json_decode(file_get_contents("php://input"), true)); - $return = (new FhirPractitionerRestController())->patch($uuid, $data); - RestConfig::apiLog($return, $data); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/PractitionerRole", - * description="Returns a list of PractitionerRole resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the PractitionerRole resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="specialty", - * in="query", - * description="The specialty of the PractitionerRole resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="practitioner", - * in="query", - * description="The practitioner of the PractitionerRole resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/PractitionerRole" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/PractitionerRole" => function (HttpRestRequest $request) { - RestConfig::authorization_check("admin", "users"); - $return = (new FhirPractitionerRoleRestController())->getAll($request->getQueryParams()); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/PractitionerRole/{uuid}", - * description="Returns a single PractitionerRole resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the PractitionerRole resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "960c806f-9463-482e-b228-67b5be1fed55", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2022-04-13T06:18:17+00:00" - * }, - * "resourceType": "PractitionerRole", - * "practitioner": { - * "reference": "Practitioner/960c7cd6-187a-4119-8cd4-85389d80efb9", - * "display": "Administrator Administrator" - * }, - * "organization": { - * "reference": "Organization/960c7cc6-b4ae-49bc-877b-1a2913271c43", - * "display": "Your Clinic Name Here" - * }, - * "code": { - * { - * "coding": { - * "102L00000X" - * }, - * "text": "Psychoanalyst" - * }, - * { - * "coding": { - * "101Y00000X" - * }, - * "text": "Counselor" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/PractitionerRole/:uuid" => function ($uuid, HttpRestRequest $request) { - RestConfig::authorization_check("admin", "users"); - $return = (new FhirPractitionerRoleRestController())->getOne($uuid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Procedure", - * description="Returns a list of Procedure resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the Procedure resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="patient", - * in="query", - * description="The uuid for the patient.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="date", - * in="query", - * description="The datetime of the Procedure resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/Procedure" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Procedure" => function (HttpRestRequest $request) { - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirProcedureRestController())->getAll($request->getQueryParams(), $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("patients", "med"); - $return = (new FhirProcedureRestController())->getAll($request->getQueryParams()); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Procedure/{uuid}", - * description="Returns a single Procedure resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the Procedure resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "95e9d3fb-fe7b-448a-aa60-d40b11b486a5", - * "meta": { - * "versionId": "1", - * "lastUpdated": "2022-03-26T17:20:14+00:00" - * }, - * "resourceType": "Procedure", - * "status": "in-progress", - * "subject": { - * "reference": "Patient/95e8d830-3068-48cf-930a-2fefb18c2bcf", - * "type": "Patient" - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Procedure/:uuid" => function ($uuid, HttpRestRequest $request) { - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirProcedureRestController())->getOne($uuid, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("patients", "med"); - $return = (new FhirProcedureRestController())->getOne($uuid); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Provenance/{uuid}", - * description="Returns a single Provenance resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The id for the Provenance resource. Format is \:\ (Example: AllergyIntolerance:95ea43f3-1066-4bc7-b224-6c23b985f145).", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "id": "AllergyIntolerance:95ea43f3-1066-4bc7-b224-6c23b985f145", - * "resourceType": "Provenance", - * "target": { - * { - * "reference": "AllergyIntolerance/95ea43f3-1066-4bc7-b224-6c23b985f145", - * "type": "AllergyIntolerance" - * } - * }, - * "recorded": "2022-03-26T22:43:30+00:00", - * "agent": { - * { - * "type": { - * "coding": { - * { - * "system": "http://terminology.hl7.org/CodeSystem/provenance-participant-type", - * "code": "author", - * "display": "Author" - * } - * } - * }, - * "who": { - * "reference": "Organization/95e8d810-7e55-44aa-bb48-fecd5b0d88c7", - * "type": "Organization" - * }, - * "onBehalfOf": { - * "reference": "Organization/95e8d810-7e55-44aa-bb48-fecd5b0d88c7", - * "type": "Organization" - * } - * }, - * { - * "type": { - * "coding": { - * { - * "system": "http://hl7.org/fhir/us/core/CodeSystem/us-core-provenance-participant-type", - * "code": "transmitter", - * "display": "Transmitter" - * } - * } - * } - * }, - * "who": { - * "reference": "Organization/95e8d810-7e55-44aa-bb48-fecd5b0d88c7", - * "type": "Organization" - * }, - * "onBehalfOf": { - * "reference": "Organization/95e8d810-7e55-44aa-bb48-fecd5b0d88c7", - * "type": "Organization" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Provenance/:uuid" => function ($uuid, HttpRestRequest $request) { - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirProvenanceRestController($request))->getOne($uuid, $request->getPatientUUIDString()); - } else { - RestConfig::authorization_check("admin", "super"); - $return = (new FhirProvenanceRestController($request))->getOne($uuid); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Provenance", - * description="Returns a list of Provenance resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The id for the Provenance resource. Format is \:\ (Example: AllergyIntolerance:95ea43f3-1066-4bc7-b224-6c23b985f145).", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/Provenance" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - // NOTE: this GET request only supports requests with an _id parameter. FHIR inferno test tool requires the 'search' - // property to support which is why this endpoint exists. - "GET /fhir/Provenance" => function (HttpRestRequest $request) { - if ($request->isPatientRequest()) { - // only allow access to data of binded patient - $return = (new FhirProvenanceRestController($request))->getAll($request->getQueryParams(), $request->getPatientUUIDString()); - } else { - // TODO: it seems like regular users should be able to grab authorship / provenance information - RestConfig::authorization_check("admin", "super"); - $return = (new FhirProvenanceRestController($request))->getAll($request->getQueryParams()); - } - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Questionnaire", - * description="Returns a list of Questionnaire resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The id for the Questionnaire resource. ", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/Questionnaire" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/Questionnaire" => function (HttpRestRequest $request) { - $logger = new SystemLogger(); - $fhirQuestionnaireService = new FhirQuestionnaireService(); - $fhirFormService = new FhirQuestionnaireFormService(); - $fhirQuestionnaireService->addMappedService($fhirFormService); - $return = (new FhirQuestionnaireRestController($logger, $fhirQuestionnaireService))->list($request); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/Questionnaire", - * description="Returns a list of QuestionnaireResponse resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The id for the QuestionnaireResponse resource. ", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/QuestionnaireResponse" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/QuestionnaireResponse" => function (HttpRestRequest $request) { - $fhirQuestionnaireService = new FhirQuestionnaireResponseService(); - $fhirQuestionnaireService->addMappedService(new FhirQuestionnaireResponseFormService()); - $return = (new FhirQuestionnaireResponseRestController($fhirQuestionnaireService))->list($request); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/ValueSet", - * description="Returns a list of ValueSet resources.", - * tags={"fhir"}, - * @OA\Parameter( - * name="_id", - * in="query", - * description="The uuid for the ValueSet resource.", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Parameter( - * name="_lastUpdated", - * in="query", - * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", - * required=false, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "meta": { - * "lastUpdated": "2021-09-14T09:13:51" - * }, - * "resourceType": "Bundle", - * "type": "collection", - * "total": 0, - * "link": { - * { - * "relation": "self", - * "url": "https://localhost:9300/apis/default/fhir/ValueSet" - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/ValueSet" => function (HttpRestRequest $request) { - RestConfig::authorization_check("admin", "super"); - $return = (new FhirValueSetRestController())->getAll($request->getQueryParams()); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/ValueSet/{uuid}", - * description="Returns a single ValueSet resource.", - * tags={"fhir"}, - * @OA\Parameter( - * name="uuid", - * in="path", - * description="The uuid for the ValueSet resource.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "resourceType": "ValueSet", - * "id": "appointment-type", - * "compose": { - * "include": { - * { - * "concept": { - * { - * "code": "no_show", - * "display": "No Show" - * }, - * { - * "code": "office_visit", - * "display": "Office Visit" - * }, - * { - * "code": "established_patient", - * "display": "Established Patient" - * }, - * { - * "code": "new_patient", - * "display": "New Patient" - * }, - * { - * "code": "health_and_behavioral_assessment", - * "display": "Health and Behavioral Assessment" - * }, - * { - * "code": "preventive_care_services", - * "display": "Preventive Care Services" - * }, - * { - * "code": "ophthalmological_services", - * "display": "Ophthalmological Services" - * } - * } - * } - * } - * } - * } - * ) - * ) - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * @OA\Response( - * response="404", - * ref="#/components/responses/uuidnotfound" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /fhir/ValueSet/:uuid" => function ($uuid, HttpRestRequest $request) { - RestConfig::authorization_check("admin", "super"); - $return = (new FhirValueSetRestController())->getOne($uuid); - RestConfig::apiLog($return); - return $return; - }, - - // other endpoints - - /** - * @OA\Get( - * path="/fhir/metadata", - * description="Returns metadata (ie. CapabilityStatement resource) of the fhir server.", - * tags={"fhir"}, - * @OA\Response( - * response="200", - * description="Return CapabilityStatement resource of the fhir server" - * ) - * ) - */ - "GET /fhir/metadata" => function () { - $return = (new FhirMetaDataRestController())->getMetaData(); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/.well-known/smart-configuration", - * description="Returns smart configuration of the fhir server.", - * tags={"fhir"}, - * @OA\Response( - * response="200", - * description="Return smart configuration of the fhir server" - * ) - * ) - */ - "GET /fhir/.well-known/smart-configuration" => function () { - $authController = new \OpenEMR\RestControllers\AuthorizationController(); - $return = (new \OpenEMR\RestControllers\SMART\SMARTConfigurationController($authController))->getConfig(); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/OperationDefinition", - * description="Returns a list of the OperationDefinition resources that are specific to this OpenEMR installation", - * tags={"fhir"}, - * @OA\Response( - * response="200", - * description="Return list of OperationDefinition resources" - * ) - * ) - */ - "GET /fhir/OperationDefinition" => function (HttpRestRequest $request) { - // for now we will just hard code the custom resources - $operationDefinitionController = new FhirOperationDefinitionRestController(); - $return = $operationDefinitionController->getAll($request->getQueryParams()); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/fhir/OperationDefinition/{operation}", - * description="Returns a single OperationDefinition resource that is specific to this OpenEMR installation", - * tags={"fhir"}, - * @OA\Parameter( - * name="operation", - * in="path", - * description="The name of the operation to query. For example $bulkdata-status", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * description="Standard Response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="json object", - * description="FHIR Json object.", - * type="object" - * ), - * example={ - * "resourceType": "OperationDefinition", - * "name": "$bulkdata-status", - * "status": "active", - * "kind": "operation", - * "parameter": { - * { - * "name": "job", - * "use": "in", - * "min": 1, - * "max": 1, - * "type": { - * "system": "http://hl7.org/fhir/data-types", - * "code": "string", - * "display": "string" - * }, - * "searchType": { - * "system": "http://hl7.org/fhir/ValueSet/search-param-type", - * "code": "string", - * "display": "string" - * } - * } - * } - * } - * ) - * ) - * ), - * ) - */ - "GET /fhir/OperationDefinition/:operation" => function ($operation, HttpRestRequest $request) { - // for now we will just hard code the custom resources - $operationDefinitionController = new FhirOperationDefinitionRestController(); - $return = $operationDefinitionController->getOne($operation); - RestConfig::apiLog($return); - return $return; - }, - - // FHIR root level operations - - /** - * @OA\Get( - * path="/fhir/$export", - * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API", - * tags={"fhir"}, - * @OA\Response( - * response="200", - * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - 'GET /fhir/$export' => function (HttpRestRequest $request) { - RestConfig::authorization_check("admin", "users"); - $fhirExportService = new FhirOperationExportRestController($request); - $return = $fhirExportService->processExport( - $request->getQueryParams(), - 'System', - $request->getHeader('Accept')[0] ?? '', - $request->getHeader('Prefer')[0] ?? '' - ); - RestConfig::apiLog($return); - return $return; - }, - - // these two operations are adopted based on the documentation used in the IBM FHIR Server - // we'd reference cerner or epic but we couldn't find any documentation about those (Jan 30th 2021) - // @see https://ibm.github.io/FHIR/guides/FHIRBulkOperations/ - - /** - * @OA\Get( - * path="/fhir/$bulkdata-status", - * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API", - * tags={"fhir"}, - * @OA\Response( - * response="200", - * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - 'GET /fhir/$bulkdata-status' => function (HttpRestRequest $request) { - RestConfig::authorization_check("admin", "users"); - $jobUuidString = $request->getQueryParam('job'); - // if we were truly async we would return 202 here to say we are in progress with a JSON response - // since OpenEMR data is so small we just return the JSON from the database - $fhirExportService = new FhirOperationExportRestController($request); - $return = $fhirExportService->processExportStatusRequestForJob($jobUuidString); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Delete( - * path="/fhir/$bulkdata-status", - * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API", - * tags={"fhir"}, - * @OA\Response( - * response="200", - * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - 'DELETE /fhir/$bulkdata-status' => function (HttpRestRequest $request) { - RestConfig::authorization_check("admin", "users"); - $job = $request->getQueryParam('job'); - $fhirExportService = new FhirOperationExportRestController($request); - $return = $fhirExportService->processDeleteExportForJob($job); - RestConfig::apiLog($return); - return $return; - }, -); - -// Note that the portal (api) route is only for patient role -// (there is a mechanism in place to ensure only patient role can access the portal (api) route) -RestConfig::$PORTAL_ROUTE_MAP = array( - /** - * @OA\Get( - * path="/portal/patient", - * description="Returns the patient.", - * tags={"standard-patient"}, - * @OA\Response( - * response="200", - * description="Standard response", - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema(ref="#/components/schemas/api_patient_response") - * ) - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /portal/patient" => function (HttpRestRequest $request) { - $return = (new PatientRestController())->getOne($request->getPatientUUIDString()); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/portal/patient/encounter", - * description="Returns encounters for the patient.", - * tags={"standard-patient"}, - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /portal/patient/encounter" => function (HttpRestRequest $request) { - $return = (new EncounterRestController())->getAll($request->getPatientUUIDString()); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/portal/patient/encounter/{euuid}", - * description="Returns a selected encounter by its uuid.", - * tags={"standard-patient"}, - * @OA\Parameter( - * name="euuid", - * in="path", - * description="The uuid for the encounter.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /portal/patient/encounter/:euuid" => function ($euuid, HttpRestRequest $request) { - $return = (new EncounterRestController())->getOne($request->getPatientUUIDString(), $euuid); - RestConfig::apiLog($return); - return $return; - }, - - /** - * @OA\Get( - * path="/portal/patient/appointment", - * description="Retrieves all appointments for a patient", - * tags={"standard-patient"}, - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /portal/patient/appointment" => function (HttpRestRequest $request) { - $return = (new AppointmentRestController())->getAllForPatientByUuid($request->getPatientUUIDString()); - RestConfig::apiLog($return); - return $return; - }, +RestConfig::$ROUTE_MAP = require_once __DIR__ . "/apis/routes/_rest_routes_standard.inc.php"; +RestConfig::$FHIR_ROUTE_MAP = require_once __DIR__ . "/apis/routes/_rest_routes_fhir_r4_us_core_3_1_0.inc.php"; - /** - * @OA\Get( - * path="/portal/patient/appointment/{auuid}", - * description="Returns a selected appointment by its uuid.", - * tags={"standard-patient"}, - * @OA\Parameter( - * name="auuid", - * in="path", - * description="The uuid for the appointment.", - * required=true, - * @OA\Schema( - * type="string" - * ) - * ), - * @OA\Response( - * response="200", - * ref="#/components/responses/standard" - * ), - * @OA\Response( - * response="400", - * ref="#/components/responses/badrequest" - * ), - * @OA\Response( - * response="401", - * ref="#/components/responses/unauthorized" - * ), - * security={{"openemr_auth":{}}} - * ) - */ - "GET /portal/patient/appointment/:auuid" => function ($auuid, HttpRestRequest $request) { - $return = (new AppointmentRestController())->getOneForPatient($auuid, $request->getPatientUUIDString()); - RestConfig::apiLog($return); - return $return; - } -); +RestConfig::$PORTAL_ROUTE_MAP = require_once __DIR__ . "/apis/routes/_rest_routes_portal.inc.php"; diff --git a/apis/.htaccess b/apis/.htaccess index 012bdf2d8c12..e7d349af24ec 100644 --- a/apis/.htaccess +++ b/apis/.htaccess @@ -5,4 +5,7 @@ SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-l +# It would be best if we didn't use a query param for the rewrite and instead used it as a path segment, +# however that will break a lot of existing openemr installations so we will use a query param for now and +# perhaps issue a deprecation warning in the future. RewriteRule (.*) dispatch.php?_REWRITE_COMMAND=$1 [QSA,L] diff --git a/apis/dispatch.php b/apis/dispatch.php index 9a83d368c9f7..45dd66ee28b0 100644 --- a/apis/dispatch.php +++ b/apis/dispatch.php @@ -15,423 +15,29 @@ */ // below brings in autoloader -require_once("./../_rest_config.php"); +require_once "../vendor/autoload.php"; -use OpenEMR\Common\Auth\UuidUserAccount; -use OpenEMR\Common\Csrf\CsrfUtils; -use OpenEMR\Common\Http\HttpRestRouteHandler; use OpenEMR\Common\Http\HttpRestRequest; -use OpenEMR\Common\Logging\SystemLogger; -use OpenEMR\Common\Session\SessionUtil; -use OpenEMR\Common\Uuid\UuidRegistry; -use OpenEMR\FHIR\SMART\SmartLaunchController; -use OpenEMR\Events\RestApiExtend\RestApiCreateEvent; -use OpenEMR\Telemetry\TelemetryService; -use Psr\Http\Message\ResponseInterface; -use OpenEMR\Tools\Coverage\CoverageHelper; +use OpenEMR\RestControllers\ApiApplication; +use Symfony\Component\HttpFoundation\Response; -if ( - getenv('ENABLE_COVERAGE') - && !empty(getenv('OPENEMR_COVERAGE_DIR')) -) { - // setup our code coverage - ini_set('memory_limit', '1024M'); - $basedir = __DIR__ . '/../' . getenv('OPENEMR_COVERAGE_DIR'); - $coverage = CoverageHelper::createTargetedCodeCoverage($basedir); - $coverageId = CoverageHelper::getCurrentCoverageId(); - $coverage->start($coverageId); -} - -$gbl = RestConfig::GetInstance(); -$restRequest = new HttpRestRequest($gbl, $_SERVER); -$routes = array(); - -// Parse needed information from Redirect or REQUEST_URI -$resource = $gbl::getRequestEndPoint(); -$logger = new SystemLogger(); -$logger->debug("dispatch.php requested", ["resource" => $resource, "method" => $_SERVER['REQUEST_METHOD']]); - -$skipApiAuth = false; -if (!empty($_SERVER['HTTP_APICSRFTOKEN'])) { - // Calling api from within the same session (ie. isLocalApi) since a apicsrftoken header was passed - $isLocalApi = true; - $gbl::setLocalCall(); - $skipApiAuth = false; - $ignoreAuth = false; -} elseif ($gbl::skipApiAuth($resource)) { - // For rest api endpoints that do not require auth, such as the capability statement - // note that the site is validated in the skipApiAuth() function - // refactor resource - $restRequest->setRequestSite($gbl::$SITE); - // set site - $_GET['site'] = $gbl::$SITE; - $isLocalApi = false; - $skipApiAuth = true; - $ignoreAuth = true; -} else { - // Calling api via rest - // ensure token is valid - $tokenRaw = $gbl::verifyAccessToken(); - if ($tokenRaw instanceof ResponseInterface) { - $logger->error("dispatch.php failed token verify for resource", ["resource" => $resource]); - // failed token verify - // not a request object so send the error as response obj - $gbl::emitResponse($tokenRaw); - exit; - } - - // collect token attributes - $attributes = $tokenRaw->getAttributes(); - - // collect site - $site = ''; - $scopes = $attributes['oauth_scopes']; - $logger->debug("Parsed oauth_scopes in AccessToken", ["scopes" => $scopes]); - foreach ($scopes as $attr) { - if (stripos($attr, 'site:') !== false) { - $site = str_replace('site:', '', $attr); - $restRequest->setRequestSite($site); - } - } - // set our scopes and updated resources as needed - $restRequest->setAccessTokenScopes($scopes); - - // ensure 1) sane site 2) site from gbl and access token are the same and 3) ensure the site exists on filesystem - if ( - empty($restRequest->getRequestSite()) || empty($gbl::$SITE) || preg_match('/[^A-Za-z0-9\\-.]/', $gbl::$SITE) - || ($restRequest->getRequestSite() !== $gbl::$SITE) || !file_exists(__DIR__ . '/../sites/' . $gbl::$SITE) - ) { - $logger->error("OpenEMR Error - api site error, so forced exit"); - http_response_code(400); - exit(); - } - // set the site - $_GET['site'] = $site; - - // set the scopes globals for endpoint permission checking - $GLOBALS['oauth_scopes'] = $scopes; - - // collect openemr user uuid - $userId = $attributes['oauth_user_id']; - // collect client id (will be empty for PKCE) - $clientId = $attributes['oauth_client_id'] ?? null; - // collect token id - $tokenId = $attributes['oauth_access_token_id']; - // ensure user uuid and token id are populated - if (empty($userId) || empty($tokenId)) { - $logger->error("OpenEMR Error - userid or tokenid not available, so forced exit", ['attributes' => $attributes]); - http_response_code(400); - exit(); - } - $restRequest->setClientId($clientId); - $restRequest->setAccessTokenId($tokenId); - - // Get a site id from initial login authentication. - $isLocalApi = false; - $skipApiAuth = false; - $ignoreAuth = true; -} - -// set the route as well as the resource information. Note $resource is actually the route and not the resource name. -//$restRequest->setRequestPath($resource); -$resource = $restRequest->getRequestPath(); - -if (!$isLocalApi) { - // Will start the api OpenEMR session/cookie. - SessionUtil::apiSessionStart($gbl::$web_root); -} - -$GLOBALS['is_local_api'] = $isLocalApi; -$restRequest->setIsLocalApi($isLocalApi); - -// Set $sessionAllowWrite to true here for following reasons: -// 1. !$isLocalApi - not applicable since use the SessionUtil::apiSessionStart session, which was set above -// 2. $isLocalApi - in this case, basically setting this to true downstream after some session sets via session_write_close() call -$sessionAllowWrite = true; -require_once("./../interface/globals.php"); - -// we now can check the database to see if the token is revoked -// Note despite League\OAuth2\Server\AuthorizationValidators\BearerTokenValidator.php:L117 already checking for revoked -// access token we have to do this logic here as we use the access token SCOPE parameter to determine our multi-site setting -// and load up the correct database, our earlier access token logic returns false for revoked as we don't have db access -// for that reason we have this double check on validating the access token. -if (!empty($tokenId)) { - $result = $gbl::validateAccessTokenRevoked($tokenId); - if ($result instanceof ResponseInterface) { - $logger->error("dispatch.php access token was revoked", ["resource" => $resource]); - // failed token verify - // not a request object so send the error as response obj - $gbl::emitResponse($result); - exit; - } -} - - -// recollect this so the DEBUG global can be used if set -$logger = new SystemLogger(); - -$gbl::$apisBaseFullUrl = $GLOBALS['site_addr_oath'] . $GLOBALS['webroot'] . "/apis/" . $gbl::$SITE; -$restRequest->setApiBaseFullUrl($gbl::$apisBaseFullUrl); - -if ($isLocalApi) { - // need to check for csrf match when using api locally - $csrfFail = false; - - if (empty($_SERVER['HTTP_APICSRFTOKEN'])) { - $logger->error("OpenEMR Error: internal api failed because csrf token not received"); - $csrfFail = true; - } - - if ((!$csrfFail) && (!CsrfUtils::verifyCsrfToken($_SERVER['HTTP_APICSRFTOKEN'], 'api'))) { - $logger->error("OpenEMR Error: internal api failed because csrf token did not match"); - $csrfFail = true; - } - - if ($csrfFail) { - $logger->error("dispatch.php CSRF failed", ["resource" => $resource]); - http_response_code(401); - exit(); - } -} elseif ($skipApiAuth) { - $logger->debug("dispatch.php skipping api auth"); - // For endpoints that do not require auth, such as the capability statement -} else { - $logger->debug("dispatch.php authenticating user"); - // verify that user tokens haven't been revoked. - // this is done by verifying the user is trusted with active auth session. - $isTrusted = $gbl::isTrustedUser($attributes["oauth_client_id"], $attributes["oauth_user_id"]); - if ($isTrusted instanceof ResponseInterface) { - $logger->debug("dispatch.php oauth2 inactive user api attempt"); - // user is not logged on to server with an active session. - // too me this is easier than revoking tokens or using phantom tokens. - // give a 400(unsure here, could be a 401) so client can redirect to server. - $gbl::destroySession(); - $gbl::emitResponse($isTrusted); - exit; - } - // $isTrusted can be used for further validations using session_cache - // which is a json. json_decode($isTrusted['session_cache']) - - // authenticate the token - if (!$gbl->authenticateUserToken($tokenId, $clientId, $userId)) { - $logger->error("dispatch.php api call with invalid token"); - $gbl::destroySession(); - http_response_code(401); - exit(); - } - - // collect user information and user role - $uuidToUser = new UuidUserAccount($userId); - $user = $uuidToUser->getUserAccount(); - $userRole = $uuidToUser->getUserRole(); - if (empty($user)) { - // unable to identify the users user role - $logger->error("OpenEMR Error - api user account could not be identified, so forced exit", [ - 'userId' => $userId, - 'userRole' => $uuidToUser->getUserRole()]); - $gbl::destroySession(); - http_response_code(400); - exit(); - } - if (empty($userRole)) { - // unable to identify the users user role - $logger->error("OpenEMR Error - api user role for user could not be identified, so forced exit"); - $gbl::destroySession(); - http_response_code(400); - exit(); - } - - $restRequest->setAccessTokenId($tokenId); - $restRequest->setRequestUserRole($userRole); - $restRequest->setRequestUser($userId, $user); - - // verify that the scope covers the route - if ( - // fhir routes are the default and can send openid/fhirUser w/ authorization_code, or no scopes at all - // with Client Credentials, so we only reject requests for standard or portal if the correct scope is not - // sent. - ($gbl::is_api_request($resource) && !in_array('api:oemr', $GLOBALS['oauth_scopes'])) || - ($gbl::is_portal_request($resource) && !in_array('api:port', $GLOBALS['oauth_scopes'])) - ) { - $logger->error("dispatch.php api call with token that does not cover the requested route"); - $gbl::destroySession(); - http_response_code(401); - exit(); - } - // ensure user role has access to the resource - // for now assuming: - // users has access to oemr and fhir - // patient has access to port and fhir - if ($userRole == 'users' && ($gbl::is_api_request($resource) || $gbl::is_fhir_request($resource))) { - $logger->debug("dispatch.php valid role and user has access to api/fhir resource", ['resource' => $resource]); - // good to go - } elseif ($userRole == 'patient' && ($gbl::is_portal_request($resource) || $gbl::is_fhir_request($resource))) { - $logger->debug("dispatch.php valid role and patient has access portal resource", ['resource' => $resource]); - // good to go - } elseif ($userRole === 'system' && ($gbl::is_fhir_request($resource) || $gbl::is_api_request($resource))) { - $logger->debug("dispatch.php valid role and system has access to api/fhir resource", ['resource' => $resource]); - } else { - $logger->error("OpenEMR Error: api failed because user role does not have access to the resource", ['resource' => $resource, 'userRole' => $userRole]); - $gbl::destroySession(); - http_response_code(401); - exit(); - } - // set pertinent session variables - if ($userRole == 'users') { - $_SESSION['authUser'] = $user["username"] ?? null; - $_SESSION['authUserID'] = $user["id"] ?? null; - $_SESSION['authProvider'] = sqlQueryNoLog("SELECT `name` FROM `groups` WHERE `user` = ?", [$_SESSION['authUser']])['name'] ?? null; - if (empty($_SESSION['authUser']) || empty($_SESSION['authUserID']) || empty($_SESSION['authProvider'])) { - // this should never happen - $logger->error("OpenEMR Error: api failed because unable to set critical users session variables"); - $gbl::destroySession(); - http_response_code(401); - exit(); - } - $logger->debug("dispatch.php request setup for user role", ['authUserID' => $user['id'], 'authUser' => $user['username']]); - if ( - $restRequest->requestHasScope(SmartLaunchController::CLIENT_APP_STANDALONE_LAUNCH_SCOPE) - || $restRequest->requestHasScope(SmartLaunchController::CLIENT_APP_REQUIRED_LAUNCH_SCOPE) - ) { - $logger->debug("dispatch.php api is userRole populating token context for request due to smart launch scope"); - $restRequest = $gbl->populateTokenContextForRequest($restRequest); - } - } elseif ($userRole == 'patient') { - $_SESSION['pid'] = $user['pid'] ?? null; - $puuidCheck = $user['uuid'] ?? null; - $puuidStringCheck = UuidRegistry::uuidToString($puuidCheck) ?? null; - if (empty($_SESSION['pid']) || empty($puuidCheck) || empty($puuidStringCheck)) { - // this should never happen - $logger->error("OpenEMR Error: api failed because unable to set critical patient session variables"); - $gbl::destroySession(); - http_response_code(401); - exit(); - } - $restRequest->setPatientRequest(true); - $restRequest->setPatientUuidString($puuidStringCheck); - $logger->debug("dispatch.php request setup for patient role", ['patient' => $puuidStringCheck]); - } elseif ($userRole === 'system') { - $_SESSION['authUser'] = $user["username"] ?? null; - $_SESSION['authUserID'] = $user["id"] ?? null; - if ( - empty($_SESSION['authUser']) - // this should never happen as the system role depends on the system username... but we safety check it anyways - || $_SESSION['authUser'] != \OpenEMR\Services\UserService::SYSTEM_USER_USERNAME - || empty($_SESSION['authUserID']) - ) { - $logger->error("OpenEMR Error: api failed because unable to set critical users session variables"); - $gbl::destroySession(); - http_response_code(401); - exit(); - } - } else { - // this user role is not supported - $logger->error("OpenEMR Error - api user role that was provided is not supported, so forced exit"); - $gbl::destroySession(); - http_response_code(400); - exit(); - } -} - -//Extend API using RestApiCreateEvent -$restApiCreateEvent = new RestApiCreateEvent($gbl::$ROUTE_MAP, $gbl::$FHIR_ROUTE_MAP, $gbl::$PORTAL_ROUTE_MAP, $restRequest); -$restApiCreateEvent = $GLOBALS["kernel"]->getEventDispatcher()->dispatch($restApiCreateEvent, RestApiCreateEvent::EVENT_HANDLE, 10); -$gbl::$ROUTE_MAP = $restApiCreateEvent->getRouteMap(); -$gbl::$FHIR_ROUTE_MAP = $restApiCreateEvent->getFHIRRouteMap(); -$gbl::$PORTAL_ROUTE_MAP = $restApiCreateEvent->getPortalRouteMap(); -$restRequest = $restApiCreateEvent->getRestRequest(); - -// api flag must be four chars -// Pass only routes for current api. -// Also check to ensure route is turned on in globals -if ($gbl::is_fhir_request($resource)) { - if (!$GLOBALS['rest_fhir_api'] && !$isLocalApi) { - // if the external fhir api is turned off and this is not a local api call, then exit - $logger->error("dispatch.php attempted to access resource with FHIR api turned off ", ['resource' => $resource]); - $gbl::destroySession(); - http_response_code(501); - exit(); - } - $_SESSION['api'] = 'fhir'; - $routes = $gbl::$FHIR_ROUTE_MAP; -} elseif ($gbl::is_portal_request($resource)) { - if (!$GLOBALS['rest_portal_api'] && !$isLocalApi) { - $logger->error("dispatch.php attempted to access resource with portal api turned off ", ['resource' => $resource]); - // if the external portal api is turned off and this is not a local api call, then exit - $gbl::destroySession(); - http_response_code(501); - exit(); - } - $_SESSION['api'] = 'port'; - $routes = $gbl::$PORTAL_ROUTE_MAP; -} elseif ($gbl::is_api_request($resource)) { - if (!$GLOBALS['rest_api'] && !$isLocalApi) { - $logger->error( - "dispatch.php attempted to access resource with REST api turned off ", - ['resource' => $resource] - ); - // if the external api is turned off and this is not a local api call, then exit - $gbl::destroySession(); - http_response_code(501); - exit(); - } - $_SESSION['api'] = 'oemr'; - $routes = $gbl::$ROUTE_MAP; -} else { - $logger->error("dispatch.php invalid access to resource", ['resource' => $resource]); - - // somebody is up to no good - if (!$isLocalApi) { - $gbl::destroySession(); - } - http_response_code(501); - exit(); -} - -$restRequest->setApiType($_SESSION['api']); - -if ($isLocalApi) { - // Ensure that a local process does not hold up other processes - // Note can not do this for !$isLocalApi since need to be able to set - // session variables and it won't help performance anyways. - session_write_close(); -} - -// dispatch $routes called by ref (note storing the output in a variable to allow option -// to destroy the session/cookie before sending the output back) -ob_start(); -$dispatchResult = HttpRestRouteHandler::dispatch($routes, $restRequest); -$apiCallOutput = ob_get_clean(); -// Tear down session for security. -if (!$isLocalApi) { - $gbl::destroySession(); -} -// TODO: @adunsulag we should consider rearranging the order of this code. We would rather return the response interface -// then something that was collected in the buffer... There are things internally that just dump to the screen which -// we really don't want to just spit out to the screen such as prepared statement error failures. -// Send the output if not empty -if (!empty($apiCallOutput)) { - echo $apiCallOutput; -} elseif ($dispatchResult instanceof ResponseInterface) { - RestConfig::emitResponse($dispatchResult); -} - -// prevent 200 if route doesn't exist -if ($dispatchResult === false) { - $logger->debug("dispatch.php no route found for resource", ['resource' => $resource]); - http_response_code(404); -} - -// Report to Telemetry -// Be nice to find a centralized place to catch failed requests. +// create the Request object try { - (new TelemetryService())->trackApiRequestEvent([ - 'eventType' => 'API', - 'eventLabel' => strtoupper($_SESSION['api'] ?? 'UNKNOWN'), - 'eventUrl' => $restRequest->getRequestMethod() . ' ' . $resource, - 'eventTarget' => $userRole ?? 'Unknown', - ]); - exit; -} catch (\Exception $e) { - $logger->error("dispatch.php telemetry error", ['exception' => $e]); + $request = HttpRestRequest::createFromGlobals(); + $apiApplication = new ApiApplication(); + $apiApplication->run($request); +} catch (\Throwable $e) { + // should never reach here, but if we do, we can log the error and return a generic error response + // we manually handle it as we don't know if something failed in the symfony component or in our code + error_log($e->getMessage()); + error_log($e->getTraceAsString()); + // should never get here, but if we do, we can return a generic error response + if (!headers_sent()) { + header('Content-Type: application/json'); + http_response_code(Response::HTTP_INTERNAL_SERVER_ERROR); + } + die(json_encode([ + 'error' => 'An error occurred while processing the request.', + 'message' => $e->getMessage(), + ])); } diff --git a/apis/routes/_rest_routes_fhir_r4_us_core_3_1_0.inc.php b/apis/routes/_rest_routes_fhir_r4_us_core_3_1_0.inc.php new file mode 100644 index 000000000000..0bfe10a97e0c --- /dev/null +++ b/apis/routes/_rest_routes_fhir_r4_us_core_3_1_0.inc.php @@ -0,0 +1,6244 @@ + + * @author Jerry Padgett + * @author Brady Miller + * @author Yash Raj Bothra + * @author Stephen Nielson + * @copyright Copyright (c) 2018 Matthew Vita + * @copyright Copyright (c) 2018-2020 Jerry Padgett + * @copyright Copyright (c) 2019-2021 Brady Miller + * @copyright Copyright (c) 2020 Yash Raj Bothra + * @copyright Copyright (c) 2024 Care Management Solutions, Inc. + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ + +use OpenEMR\Common\Http\HttpRestRequest; +use OpenEMR\Core\OEGlobalsBag; +use OpenEMR\RestControllers\Config\RestConfig; +use OpenEMR\RestControllers\FHIR\FhirAllergyIntoleranceRestController; +use OpenEMR\RestControllers\FHIR\FhirAppointmentRestController; +use OpenEMR\RestControllers\FHIR\FhirCarePlanRestController; +use OpenEMR\RestControllers\FHIR\FhirCareTeamRestController; +use OpenEMR\RestControllers\FHIR\FhirConditionRestController; +use OpenEMR\RestControllers\FHIR\FhirCoverageRestController; +use OpenEMR\RestControllers\FHIR\FhirDeviceRestController; +use OpenEMR\RestControllers\FHIR\FhirDiagnosticReportRestController; +use OpenEMR\RestControllers\FHIR\FhirDocumentReferenceRestController; +use OpenEMR\RestControllers\FHIR\FhirEncounterRestController; +use OpenEMR\RestControllers\FHIR\FhirObservationRestController; +use OpenEMR\RestControllers\FHIR\FhirImmunizationRestController; +use OpenEMR\RestControllers\FHIR\FhirGoalRestController; +use OpenEMR\RestControllers\FHIR\FhirGroupRestController; +use OpenEMR\RestControllers\FHIR\FhirLocationRestController; +use OpenEMR\RestControllers\FHIR\FhirMedicationRestController; +use OpenEMR\RestControllers\FHIR\FhirMedicationRequestRestController; +use OpenEMR\RestControllers\FHIR\FhirOrganizationRestController; +use OpenEMR\RestControllers\FHIR\FhirPatientRestController; +use OpenEMR\RestControllers\FHIR\FhirPersonRestController; +use OpenEMR\RestControllers\FHIR\FhirPractitionerRoleRestController; +use OpenEMR\RestControllers\FHIR\FhirPractitionerRestController; +use OpenEMR\RestControllers\FHIR\FhirProcedureRestController; +use OpenEMR\RestControllers\FHIR\FhirProvenanceRestController; +use OpenEMR\RestControllers\FHIR\FhirValueSetRestController; +use OpenEMR\RestControllers\FHIR\FhirMetaDataRestController; +use OpenEMR\RestControllers\FHIR\Operations\FhirOperationExportRestController; +use OpenEMR\RestControllers\FHIR\Operations\FhirOperationDocRefRestController; +use OpenEMR\RestControllers\FHIR\Operations\FhirOperationDefinitionRestController; +use OpenEMR\RestControllers\SMART\SMARTConfigurationController; +use OpenEMR\Common\Acl\AccessDeniedException; +use OpenEMR\Common\Logging\SystemLogger; +use OpenEMR\Services\FHIR\FhirQuestionnaireService; +use OpenEMR\Services\FHIR\Questionnaire\FhirQuestionnaireFormService; +use OpenEMR\RestControllers\FHIR\FhirQuestionnaireRestController; +use OpenEMR\Services\FHIR\FhirQuestionnaireResponseService; +use OpenEMR\Services\FHIR\QuestionnaireResponse\FhirQuestionnaireResponseFormService; +use OpenEMR\RestControllers\FHIR\FhirQuestionnaireResponseRestController; + +// Note that the fhir route includes both user role and patient role +// (there is a mechanism in place to ensure patient role is binded +// to only see the data of the one patient) +return array( + /** + * @OA\Get( + * path="/fhir/AllergyIntolerance", + * description="Returns a list of AllergyIntolerance resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the AllergyIntolerance resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="patient", + * in="query", + * description="The uuid for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/AllergyIntolerance" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/AllergyIntolerance" => function (HttpRestRequest $request) { + $getParams = $request->getQueryParams(); + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirAllergyIntoleranceRestController($request))->getAll($getParams, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new FhirAllergyIntoleranceRestController($request))->getAll($getParams); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/AllergyIntolerance/{uuid}", + * description="Returns a single AllergyIntolerance resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the AllergyIntolerance resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "94682fe5-f383-4885-9505-64b02e34906f", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2021-09-16T00:27:32+00:00" + * }, + * "resourceType": "AllergyIntolerance", + * "text": { + * "status": "additional", + * "div": "
penicillin
" + * }, + * "clinicalStatus": { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical", + * "code": "active", + * "display": "Active" + * } + * } + * }, + * "verificationStatus": { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/allergyintolerance-verification", + * "code": "confirmed", + * "display": "Confirmed" + * } + * } + * }, + * "category": { + * "medication" + * }, + * "criticality": "low", + * "code": { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/data-absent-reason", + * "code": "unknown", + * "display": "Unknown" + * } + * } + * }, + * "patient": { + * "reference": "Patient/94682ef5-b0e3-4289-b19a-11b9592e9c92" + * }, + * "reaction": { + * { + * "manifestation": { + * { + * "coding": { + * { + * "system": "http://snomed.info/sct", + * "code": "422587007", + * "display": "Nausea" + * } + * }, + * "text": "Nausea" + * } + * } + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/AllergyIntolerance/:uuid" => function ($uuid, HttpRestRequest $request) { + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirAllergyIntoleranceRestController($request))->getOne($uuid, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new FhirAllergyIntoleranceRestController($request))->getOne($uuid); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Appointment", + * description="Returns a list of Appointment resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the Appointment resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="patient", + * in="query", + * description="The uuid for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/AllergyIntolerance" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Appointment" => function (HttpRestRequest $request) { + $getParams = $request->getQueryParams(); + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirAppointmentRestController($request))->getAll($getParams, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "patients", "appt"); + $return = (new FhirAppointmentRestController($request))->getAll($getParams); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Appointment/{uuid}", + * description="Returns a single Appointment resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the Appointment resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={} + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Appointment/:uuid" => function ($uuid, HttpRestRequest $request) { + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirAppointmentRestController($request))->getOne($uuid, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "patients", "appt"); + $return = (new FhirAppointmentRestController($request))->getOne($uuid); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/CarePlan", + * description="Returns a list of CarePlan resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the CarePlan resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="patient", + * in="query", + * description="The uuid for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="category", + * in="query", + * description="The category of the CarePlan resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/CarePlan" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/CarePlan" => function (HttpRestRequest $request) { + $getParams = $request->getQueryParams(); + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirCarePlanRestController())->getAll($getParams, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new FhirCarePlanRestController())->getAll($getParams); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/CarePlan/{uuid}", + * description="Returns a single CarePlan resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the CarePlan resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "94682f08-8fbc-451e-b1ec-f922d765c38f_1", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2021-09-16T00:54:18+00:00" + * }, + * "resourceType": "CarePlan", + * "text": { + * "status": "generated", + * "div": "

Treat flu.

" + * }, + * "status": "active", + * "intent": "plan", + * "category": { + * { + * "coding": { + * { + * "system": "http://hl7.org/fhir/us/core/CodeSystem/careplan-category", + * "code": "assess-plan" + * } + * } + * } + * }, + * "description": "Treat flu.", + * "subject": { + * "reference": "Patient/94682ef5-b0e3-4289-b19a-11b9592e9c92", + * "type": "Patient" + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/CarePlan/:uuid" => function ($uuid, HttpRestRequest $request) { + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirCarePlanRestController())->getOne($uuid, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new FhirCarePlanRestController())->getOne($uuid); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/CareTeam", + * description="Returns a list of CareTeam resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the CareTeam resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="patient", + * in="query", + * description="The uuid for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="status", + * in="query", + * description="The status of the CarePlan resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/CareTeam" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/CareTeam" => function (HttpRestRequest $request) { + $getParams = $request->getQueryParams(); + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirCareTeamRestController())->getAll($getParams, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new FhirCareTeamRestController())->getAll($getParams); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/CareTeam/{uuid}", + * description="Returns a single CareTeam resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the CareTeam resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "94682f09-69fe-4ada-8ea6-753a52bd1516", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2021-09-16T01:07:22+00:00" + * }, + * "resourceType": "CareTeam", + * "status": "active", + * "subject": { + * "reference": "Patient/94682ef5-b0e3-4289-b19a-11b9592e9c92", + * "type": "Patient" + * }, + * "participant": { + * { + * "role": { + * { + * "coding": { + * { + * "system": "http://nucc.org/provider-taxonomy", + * "code": "102L00000X", + * "display": "Psychoanalyst" + * } + * } + * } + * }, + * "member": { + * "reference": "Practitioner/94682c68-f712-4c39-9158-ff132a08f26b", + * "type": "Practitioner" + * }, + * "onBehalfOf": { + * "reference": "Organization/94682c62-b801-4498-84a1-13f158bb2a18", + * "type": "Organization" + * } + * }, + * { + * "role": { + * { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/data-absent-reason", + * "code": "unknown", + * "display": "Unknown" + * } + * } + * } + * }, + * "member": { + * "reference": "Organization/94682c62-b801-4498-84a1-13f158bb2a18", + * "type": "Organization" + * } + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/CareTeam/:uuid" => function ($uuid, HttpRestRequest $request) { + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirCareTeamRestController())->getOne($uuid, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new FhirCareTeamRestController())->getOne($uuid); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Condition", + * description="Returns a list of Condition resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the Condition resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="patient", + * in="query", + * description="The uuid for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/Condition" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Condition" => function (HttpRestRequest $request) { + $getParams = $request->getQueryParams(); + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirConditionRestController())->getAll($getParams, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new FhirConditionRestController())->getAll($getParams); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Condition/{uuid}", + * description="Returns a single Condition resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the Condition resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "94682c68-e5bb-4c5c-859a-cebaa5a1e582", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2021-09-16T02:41:53+00:00" + * }, + * "resourceType": "Condition", + * "clinicalStatus": { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/condition-clinical", + * "code": "inactive", + * "display": "Inactive" + * } + * } + * }, + * "verificationStatus": { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/condition-ver-status", + * "code": "unconfirmed", + * "display": "Unconfirmed" + * } + * } + * }, + * "category": { + * { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/condition-category", + * "code": "problem-list-item", + * "display": "Problem List Item" + * } + * } + * } + * }, + * "code": { + * "coding": { + * { + * "system": "http://snomed.info/sct", + * "code": "444814009", + * "display": "" + * } + * } + * }, + * "subject": { + * "reference": "Patient/94682c62-d37e-48b5-8018-c5f6f3566609" + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Condition/:uuid" => function ($uuid, HttpRestRequest $request) { + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirConditionRestController())->getOne($uuid, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new FhirConditionRestController())->getOne($uuid); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Coverage", + * description="Returns a list of Coverage resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the Coverage resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="patient", + * in="query", + * description="The uuid for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="payor", + * in="query", + * description="The payor of the Coverage resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/Coverage" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Coverage" => function (HttpRestRequest $request) { + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirCoverageRestController())->getAll($request->getQueryParams(), $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "admin", "super"); + $return = (new FhirCoverageRestController())->getAll($request->getQueryParams()); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Coverage/{uuid}", + * description="Returns a single Coverage resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the Coverage resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "960d5f10-edc6-4c65-a6d4-39a1e1da87a8", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2022-04-14T07:58:45+00:00" + * }, + * "resourceType": "Coverage", + * "status": "active", + * "beneficiary": { + * "reference": "Patient/960d5f08-9fdf-4bdc-9108-84a149e28bac" + * }, + * "relationship": { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/subscriber-relationship", + * "code": "" + * } + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Coverage/:uuid" => function ($uuid, HttpRestRequest $request) { + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirCoverageRestController())->getOne($uuid, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "admin", "super"); + $return = (new FhirCoverageRestController())->getOne($uuid); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Device", + * description="Returns a list of Device resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the Device resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="patient", + * in="query", + * description="The uuid for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/Device" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Device" => function (HttpRestRequest $request) { + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirDeviceRestController())->getAll($request->getQueryParams(), $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "admin", "super"); + $return = (new FhirDeviceRestController())->getAll($request->getQueryParams()); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Device/{uuid}", + * description="Returns a single Device resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the Device resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "946dce19-c80a-402c-862a-eadf3f2377f0", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2021-09-18T19:28:59+00:00" + * }, + * "resourceType": "Device", + * "udiCarrier": { + * { + * "deviceIdentifier": "08717648200274", + * "carrierHRF": "=/08717648200274=,000025=A99971312345600=>014032=}013032&,1000000000000XYZ123" + * } + * }, + * "distinctIdentifier": "A99971312345600", + * "manufactureDate": "2013-02-01", + * "expirationDate": "2014-02-01", + * "lotNumber": "000000000000XYZ123", + * "serialNumber": "000025", + * "type": { + * "extension": { + * { + * "valueCode": "unknown", + * "url": "http://hl7.org/fhir/StructureDefinition/data-absent-reason" + * } + * } + * }, + * "patient": { + * "reference": "Patient/946da619-c631-431a-a282-487cd6fb7802", + * "type": "Patient" + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Device/:uuid" => function ($uuid, HttpRestRequest $request) { + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirDeviceRestController())->getOne($uuid, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "admin", "super"); + $return = (new FhirDeviceRestController())->getOne($uuid); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/DiagnosticReport", + * description="Returns a list of DiagnosticReport resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the DiagnosticReport resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="patient", + * in="query", + * description="The uuid for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="code", + * in="query", + * description="The code of the DiagnosticReport resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="category", + * in="query", + * description="The category of the DiagnosticReport resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="date", + * in="query", + * description="The datetime of the DiagnosticReport resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/DiagnosticReport" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/DiagnosticReport" => function (HttpRestRequest $request) { + $getParams = $request->getQueryParams(); + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirDiagnosticReportRestController())->getAll($getParams, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "admin", "super"); + $return = (new FhirDiagnosticReportRestController())->getAll($getParams); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/DiagnosticReport/{uuid}", + * description="Returns a single DiagnosticReport resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the DiagnosticReport resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "93fb2d6a-77ac-48ca-a12d-1a17e40007e3", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2021-09-18T20:52:34+00:00" + * }, + * "resourceType": "DiagnosticReport", + * "status": "final", + * "category": { + * { + * "coding": { + * { + * "system": "http://loinc.org", + * "code": "LP7839-6", + * "display": "Pathology" + * } + * } + * } + * }, + * "code": { + * "coding": { + * { + * "system": "http://loinc.org", + * "code": "11502-2", + * "display": "Laboratory report" + * } + * } + * }, + * "subject": { + * "reference": "Patient/9353b8f5-0a87-4e2a-afd4-25341fdb0fbc", + * "type": "Patient" + * }, + * "encounter": { + * "reference": "Encounter/93540818-cb5f-49df-b73b-83901bb793b6", + * "type": "Encounter" + * }, + * "effectiveDateTime": "2015-06-22T00:00:00+00:00", + * "issued": "2015-06-22T00:00:00+00:00", + * "performer": { + * { + * "reference": "Organization/935249b5-0ba6-4b5b-8863-a7a27d4c6350", + * "type": "Organization" + * } + * }, + * "presentedForm": { + * { + * "contentType": "text/plain", + * "data": "TXMgQWxpY2UgTmV3bWFuIHdhcyB0ZXN0ZWQgZm9yIHRoZSBVcmluYW5hbHlzaXMgbWFjcm8gcGFuZWwgYW5kIHRoZSByZXN1bHRzIGhhdmUgYmVlbiBmb3VuZCB0byBiZSANCm5vcm1hbC4=" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/DiagnosticReport/:uuid" => function ($uuid, HttpRestRequest $request) { + $getParams = $request->getQueryParams(); + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirDiagnosticReportRestController())->getOne($uuid, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "admin", "super"); + $return = (new FhirDiagnosticReportRestController())->getOne($uuid); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/DocumentReference", + * description="Returns a list of DocumentReference resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the DocumentReference resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="patient", + * in="query", + * description="The uuid for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="type", + * in="query", + * description="The type of the DocumentReference resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="category", + * in="query", + * description="The category of the DocumentReference resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="date", + * in="query", + * description="The datetime of the DocumentReference resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/DocumentReference" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + 'GET /fhir/DocumentReference' => function (HttpRestRequest $request) { + $getParams = $request->getQueryParams(); + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirDocumentReferenceRestController($request))->getAll($getParams, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "admin", "super"); + $return = (new FhirDocumentReferenceRestController($request))->getAll($getParams); + } + + return $return; + }, + + /** + * @OA\POST( + * path="/fhir/DocumentReference/$docref", + * description="The $docref operation is used to request the server generates a document based on the specified parameters. If no additional parameters are specified then a DocumentReference to the patient's most current Clinical Summary of Care Document (CCD) is returned. The document itself is retrieved using the DocumentReference.content.attachment.url element. See http://hl7.org/fhir/us/core/OperationDefinition-docref.html for more details.", + * tags={"fhir"}, + * @OA\ExternalDocumentation(description="Detailed documentation on this operation", url="https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API"), + * @OA\Parameter( + * name="patient", + * in="query", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="start", + * in="query", + * description="The datetime refers to care dates not record currency dates. All records relating to care provided in a certain date range. If no start date is provided then all documents prior to the end date are in scope. If no start and end date are provided, the most recent or current document is in scope.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="end", + * in="query", + * description="The datetime refers to care dates not record currency dates. All records relating to care provided in a certain date range. If no end date is provided then all documents subsequent to the start date are in scope. If no start and end date are provided, the most recent or current document is in scope.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="type", + * in="query", + * description="The type refers to the document type. This is a LOINC code from the valueset of http://hl7.org/fhir/R4/valueset-c80-doc-typecodes.html. The server currently only supports the LOINC code of 34133-9 (Summary of episode node).", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="A search bundle of DocumentReferences is returned" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + 'POST /fhir/DocumentReference/$docref' => function (HttpRestRequest $request) { + + // NOTE: The order of this route is IMPORTANT as it needs to come before the DocumentReference single request. + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirOperationDocRefRestController($request))->getAll($request->getQueryParams(), $request->getPatientUUIDString()); + } else { + // TODO: it seems like regular users should be able to grab authorship / provenance information + RestConfig::request_authorization_check($request, "patients", "demo"); + $return = (new FhirOperationDocRefRestController($request))->getAll($request->getQueryParams()); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/DocumentReference/{uuid}", + * description="Returns a single DocumentReference resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the DocumentReference resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "946e7553-1aaa-49f8-8f81-ae15ccaa9165", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2021-09-19T03:17:51+00:00" + * }, + * "resourceType": "DocumentReference", + * "identifier": { + * { + * "value": "946e7553-1aaa-49f8-8f81-ae15ccaa9165" + * } + * }, + * "status": "current", + * "type": { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/v3-NullFlavor", + * "code": "UNK", + * "display": "unknown" + * } + * } + * }, + * "category": { + * { + * "coding": { + * { + * "system": "https://localhost:9300/apis/default/fhir/ValueSet/openemr-document-types", + * "code": "openemr-document", + * "display": "OpenEMR Document" + * } + * } + * } + * }, + * "subject": { + * "reference": "Patient/946da619-c631-431a-a282-487cd6fb7802", + * "type": "Patient" + * }, + * "date": "2021-09-19T03:15:56+00:00", + * "author": { + * null + * }, + * "content": { + * { + * "attachment": { + * "contentType": "image/gif", + * "url": "https://localhost:9300/apis/default/fhir/Binary/7" + * }, + * "format": { + * "system": "http://ihe.net/fhir/ValueSet/IHE.FormatCode.codesystem", + * "code": "urn:ihe:iti:xds:2017:mimeTypeSufficient", + * "display": "mimeType Sufficient" + * } + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/DocumentReference/:uuid" => function ($uuid, HttpRestRequest $request) { + $getParams = $request->getQueryParams(); + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirDocumentReferenceRestController($request))->getOne($uuid, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "admin", "super"); + $return = (new FhirDocumentReferenceRestController($request))->getOne($uuid); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Binary/{id}", + * description="Used for downloading binary documents generated either with BULK FHIR Export or with the $docref CCD export operation. Documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API", + * tags={"fhir"}, + * @OA\Parameter( + * name="id", + * in="path", + * description="The id for the Document.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="The documentation for working with BULK FHIR or $docref document exports can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + 'GET /fhir/Binary/:id' => function ($documentId, HttpRestRequest $request) { + $docController = new \OpenEMR\RestControllers\FHIR\FhirDocumentRestController($request); + + if ($request->isPatientRequest()) { + $response = $docController->downloadDocument($documentId, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "admin", "users"); + $response = $docController->downloadDocument($documentId); + } + + return $response; + }, + + /** + * @OA\Get( + * path="/fhir/Encounter", + * description="Returns a list of Encounter resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the Encounter resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="patient", + * in="query", + * description="The uuid for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="date", + * in="query", + * description="The datetime of the Encounter resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/Encounter" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Encounter" => function (HttpRestRequest $request) { + $getParams = $request->getQueryParams(); + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirEncounterRestController())->getAll($getParams, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "encounters", "auth_a"); + $return = (new FhirEncounterRestController())->getAll($getParams); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Encounter/{uuid}", + * description="Returns a single Encounter resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the Encounter resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "946da61d-6b95-4f8e-abe5-534a25913b71", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2021-09-19T06:27:41+00:00" + * }, + * "resourceType": "Encounter", + * "identifier": { + * { + * "system": "urn:ietf:rfc:3986", + * "value": "946da61d-6b95-4f8e-abe5-534a25913b71" + * } + * }, + * "status": "finished", + * "class": { + * "system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", + * "code": "AMB", + * "display": "ambulatory" + * }, + * "type": { + * { + * "coding": { + * { + * "system": "http://snomed.info/sct", + * "code": "185349003", + * "display": "Encounter for check up (procedure)" + * } + * } + * } + * }, + * "subject": { + * "reference": "Patient/946da61b-626b-4f88-81e2-adfb88f4f0fe", + * "type": "Patient" + * }, + * "participant": { + * { + * "type": { + * { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/v3-ParticipationType", + * "code": "PPRF", + * "display": "Primary Performer" + * } + * } + * } + * }, + * "period": { + * "start": "2012-08-13T00:00:00+00:00" + * }, + * "individual": { + * "reference": "Practitioner/946da61d-ac5f-4fdc-b3f2-7b58dc49976b", + * "type": "Practitioner" + * } + * } + * }, + * "period": { + * "start": "2012-08-13T00:00:00+00:00" + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Encounter/:uuid" => function ($uuid, HttpRestRequest $request) { + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirEncounterRestController())->getOne($uuid, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "admin", "super"); + $return = (new FhirEncounterRestController())->getOne($uuid); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Goal", + * description="Returns a list of Condition resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the Goal resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="patient", + * in="query", + * description="The uuid for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/Goal" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Goal" => function (HttpRestRequest $request) { + $getParams = $request->getQueryParams(); + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirGoalRestController())->getAll($getParams, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "admin", "super"); + $return = (new FhirGoalRestController())->getAll($getParams); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Goal/{uuid}", + * description="Returns a single Goal resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the Goal resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "946da61d-6b88-4d54-bdd6-4029e2ad9e3f_1", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2021-09-19T06:45:58+00:00" + * }, + * "resourceType": "Goal", + * "lifecycleStatus": "active", + * "description": { + * "text": "Eating more vegetables." + * }, + * "subject": { + * "reference": "Patient/946da619-c631-431a-a282-487cd6fb7802", + * "type": "Patient" + * }, + * "target": { + * { + * "measure": { + * "extension": { + * { + * "valueCode": "unknown", + * "url": "http://hl7.org/fhir/StructureDefinition/data-absent-reason" + * } + * } + * }, + * "detailString": "Eating more vegetables.", + * "dueDate": "2021-09-09" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Goal/:uuid" => function ($uuid, HttpRestRequest $request) { + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirGoalRestController())->getOne($uuid, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "admin", "super"); + $return = (new FhirGoalRestController())->getOne($uuid); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Group", + * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the Group resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="patient", + * in="query", + * description="The uuid for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/Group" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + 'GET /fhir/Group' => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "admin", "users"); + $getParams = $request->getQueryParams(); + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirGroupRestController())->getAll($getParams, $request->getPatientUUIDString()); + } else { + $return = (new FhirGroupRestController())->getAll($getParams); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Group/{uuid}", + * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the Group resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Group/:uuid" => function ($uuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "admin", "users"); + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirGroupRestController())->getOne($uuid, $request->getPatientUUIDString()); + } else { + $return = (new FhirGroupRestController())->getOne($uuid); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Group/{id}/$export", + * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API", + * tags={"fhir"}, + * @OA\Parameter( + * name="id", + * in="path", + * description="The id for the Group resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + 'GET /fhir/Group/:id/$export' => function ($groupId, HttpRestRequest $request, OEGlobalsBag $globalsBag) { + RestConfig::request_authorization_check($request, "admin", "users"); + $fhirExportService = new FhirOperationExportRestController($request, $globalsBag); + $exportParams = $request->getQueryParams(); + $exportParams['groupId'] = $groupId; + $return = $fhirExportService->processExport( + $exportParams, + 'Group', + $request->getHeader('Accept')[0] ?? '', + $request->getHeader('Prefer')[0] ?? '' + ); + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Immunization", + * description="Returns a list of Immunization resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the Immunization resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="patient", + * in="query", + * description="The uuid for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/Immunization" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Immunization" => function (HttpRestRequest $request) { + $getParams = $request->getQueryParams(); + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirImmunizationRestController())->getAll($getParams, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new FhirImmunizationRestController())->getAll($getParams); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Immunization/{uuid}", + * description="Returns a single Immunization resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the Immunization resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "95e8d8b7-e3e2-4e03-8eb1-31e1d9097d8f", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2022-03-26T05:42:59+00:00" + * }, + * "resourceType": "Immunization", + * "status": "completed", + * "vaccineCode": { + * "coding": { + * { + * "system": "http://hl7.org/fhir/sid/cvx", + * "code": "207", + * "display": "SARS-COV-2 (COVID-19) vaccine, mRNA, spike protein, LNP, preservative free, 100 mcg/0.5mL dose" + * } + * } + * }, + * "patient": { + * "reference": "Patient/95e8d830-3068-48cf-930a-2fefb18c2bcf" + * }, + * "occurrenceDateTime": "2022-03-26T05:35:00+00:00", + * "recorded": "2022-03-26T05:42:26+00:00", + * "primarySource": false + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Immunization/:uuid" => function ($uuid, HttpRestRequest $request) { + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirImmunizationRestController())->getOne($uuid, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new FhirImmunizationRestController())->getOne($uuid); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Location", + * description="Returns a list of Location resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the Location resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/Location" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Location" => function (HttpRestRequest $request) { + $return = (new FhirLocationRestController())->getAll($request->getQueryParams(), $request->getPatientUUIDString()); + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Location/{uuid}", + * description="Returns a single Location resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the Location resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "946da61d-c4f2-4f03-a2a7-b571f6a24b65", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2021-09-19T08:14:58+00:00" + * }, + * "resourceType": "Location", + * "status": "active", + * "name": "Your Clinic Name Here", + * "telecom": { + * { + * "system": "phone", + * "value": "000-000-0000" + * }, + * { + * "system": "fax", + * "value": "000-000-0000" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Location/:uuid" => function ($uuid, HttpRestRequest $request) { + $return = (new FhirLocationRestController())->getOne($uuid, $request->getPatientUUIDString()); + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Medication", + * description="Returns a list of Medication resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the Medication resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/Medication" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Medication" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new FhirMedicationRestController())->getAll($request->getQueryParams()); + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Medication/{uuid}", + * description="Returns a single Medication resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the Medication resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "961aa334-9348-4145-8252-de665e3c4afa", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2022-04-19T23:42:14+00:00" + * }, + * "resourceType": "Medication", + * "code": { + * "coding": { + * { + * "system": "http://www.nlm.nih.gov/research/umls/rxnorm", + * "code": 153165 + * } + * } + * }, + * "status": "active", + * "batch": { + * "lotNumber": "132", + * "expirationDate": "0000-00-00" + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Medication/:uuid" => function ($uuid, HttpRestRequest $request) { + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirMedicationRestController())->getOne($uuid, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new FhirMedicationRestController())->getOne($uuid); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/MedicationRequest", + * description="Returns a list of MedicationRequest resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the MedicationRequest resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="patient", + * in="query", + * description="The uuid for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="intent", + * in="query", + * description="The intent of the MedicationRequest resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="status", + * in="query", + * description="The status of the MedicationRequest resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/MedicationRequest" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/MedicationRequest" => function (HttpRestRequest $request) { + $getParams = $request->getQueryParams(); + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirMedicationRequestRestController())->getAll($getParams, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new FhirMedicationRequestRestController())->getAll($getParams); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/MedicationRequest/{uuid}", + * description="Returns a single MedicationRequest resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the MedicationRequest resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "946da61d-9cff-4416-8d27-805f19f9d7d8", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2021-09-20T04:03:14+00:00" + * }, + * "resourceType": "MedicationRequest", + * "status": "active", + * "intent": "order", + * "category": { + * { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/medicationrequest-category", + * "code": "community", + * "display": "Home/Community" + * } + * } + * } + * }, + * "reportedBoolean": false, + * "medicationCodeableConcept": { + * "coding": { + * { + * "system": "http://www.nlm.nih.gov/research/umls/rxnorm", + * "code": "1738139", + * "display": "Acetaminophen 325 MG Oral Tablet" + * } + * } + * }, + * "subject": { + * "reference": "Patient/946da617-1a4a-4b2c-ae66-93b84377cb1e", + * "type": "Patient" + * }, + * "authoredOn": "2021-09-18T00:00:00+00:00", + * "requester": { + * "reference": "Practitioner/946da61d-ac5f-4fdc-b3f2-7b58dc49976b", + * "type": "Practitioner" + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/MedicationRequest/:uuid" => function ($uuid, HttpRestRequest $request) { + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirMedicationRequestRestController())->getOne($uuid, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new FhirMedicationRequestRestController())->getOne($uuid); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Observation", + * description="Returns a list of Observation resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the Observation resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="patient", + * in="query", + * description="The uuid for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="code", + * in="query", + * description="The code of the Observation resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="category", + * in="query", + * description="The category of the Observation resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="date", + * in="query", + * description="The datetime of the Observation resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/Observation" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Observation" => function (HttpRestRequest $request) { + $getParams = $request->getQueryParams(); + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirObservationRestController())->getAll($getParams, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new FhirObservationRestController())->getAll($getParams); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Observation/{uuid}", + * description="Returns a single Observation resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the Observation resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "946da61e-0597-485e-9dfd-a87205ea56b3", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2021-09-20T04:12:16+00:00" + * }, + * "resourceType": "Observation", + * "status": "final", + * "category": { + * { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/observation-category", + * "code": "vital-signs" + * } + * } + * } + * }, + * "code": { + * "coding": { + * { + * "system": "http://loinc.org", + * "code": "85354-9", + * "display": "Blood pressure systolic and diastolic" + * } + * } + * }, + * "subject": { + * "reference": "Patient/946da619-c631-431a-a282-487cd6fb7802", + * "type": "Patient" + * }, + * "effectiveDateTime": "2015-08-31T00:00:00+00:00", + * "component": { + * { + * "code": { + * "coding": { + * { + * "system": "http://loinc.org", + * "code": "8480-6", + * "display": "Systolic blood pressure" + * } + * } + * }, + * "valueQuantity": { + * "value": 122, + * "unit": "mm[Hg]", + * "system": "http://unitsofmeasure.org", + * "code": "mm[Hg]" + * } + * }, + * { + * "code": { + * "coding": { + * { + * "system": "http://loinc.org", + * "code": "8462-4", + * "display": "Diastolic blood pressure" + * } + * } + * }, + * "valueQuantity": { + * "value": 77, + * "unit": "mm[Hg]", + * "system": "http://unitsofmeasure.org", + * "code": "mm[Hg]" + * } + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Observation/:uuid" => function ($uuid, HttpRestRequest $request) { + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirObservationRestController())->getOne($uuid, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new FhirObservationRestController())->getOne($uuid); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Organization", + * description="Returns a list of Organization resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the Organization resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="name", + * in="query", + * description="The name of the Organization resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="email", + * in="query", + * description="The email of the Organization resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="phone", + * in="query", + * description="The phone of the Organization resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="telecom", + * in="query", + * description="The telecom of the Organization resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="address", + * in="query", + * description="The address of the Organization resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="address-city", + * in="query", + * description="The address-city of the Organization resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="address-postalcode", + * in="query", + * description="The address-postalcode of the Organization resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="address-state", + * in="query", + * description="The address-state of the Organization resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/Organization" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Organization" => function (HttpRestRequest $request) { + if (!$request->isPatientRequest()) { + RestConfig::request_authorization_check($request, "admin", "users"); + } + $return = (new FhirOrganizationRestController())->getAll($request->getQueryParams()); + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Organization/{uuid}", + * description="Returns a single Organization resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the Organization resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "95f0e672-be37-4c73-95c9-649c2d200018", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2022-03-30T07:43:23+00:00" + * }, + * "resourceType": "Organization", + * "text": { + * "status": "generated", + * "div": "

Your Clinic Name Here

" + * }, + * "identifier": { + * { + * "system": "http://hl7.org/fhir/sid/us-npi", + * "value": "1234567890" + * } + * }, + * "active": true, + * "type": { + * { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/organization-type", + * "code": "prov", + * "display": "Healthcare Provider" + * } + * } + * } + * }, + * "name": "Your Clinic Name Here", + * "telecom": { + * { + * "system": "phone", + * "value": "000-000-0000", + * "use": "work" + * }, + * { + * "system": "fax", + * "value": "000-000-0000", + * "use": "work" + * } + * }, + * "address": { + * null + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Organization/:uuid" => function ($uuid, HttpRestRequest $request) { + $patientUUID = null; + if (!$request->isPatientRequest()) { + RestConfig::request_authorization_check($request, "admin", "users"); + } else { + $patientUUID = $request->getPatientUUIDString(); + } + $return = (new FhirOrganizationRestController())->getOne($uuid, $patientUUID); + + + return $return; + }, + + /** + * @OA\Post( + * path="/fhir/Organization", + * description="Adds a Organization resource.", + * tags={"fhir"}, + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * description="The json object for the Organization resource.", + * type="object" + * ), + * example={ + * "id": "95f0e672-be37-4c73-95c9-649c2d200018", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2022-03-30T07:43:23+00:00" + * }, + * "resourceType": "Organization", + * "text": { + * "status": "generated", + * "div": "

Your Clinic Name Here

" + * }, + * "identifier": { + * { + * "system": "http://hl7.org/fhir/sid/us-npi", + * "value": "1234567890" + * } + * }, + * "active": true, + * "type": { + * { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/organization-type", + * "code": "prov", + * "display": "Healthcare Provider" + * } + * } + * } + * }, + * "name": "Your Clinic Name Here Hey", + * "telecom": { + * { + * "system": "phone", + * "value": "000-000-0000", + * "use": "work" + * }, + * { + * "system": "fax", + * "value": "000-000-0000", + * "use": "work" + * } + * }, + * "address": { + * null + * } + * } + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "95f0e672-be37-4c73-95c9-649c2d200018", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2022-03-30T07:43:23+00:00" + * }, + * "resourceType": "Organization", + * "text": { + * "status": "generated", + * "div": "

Your Clinic Name Here

" + * }, + * "identifier": { + * { + * "system": "http://hl7.org/fhir/sid/us-npi", + * "value": "1234567890" + * } + * }, + * "active": true, + * "type": { + * { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/organization-type", + * "code": "prov", + * "display": "Healthcare Provider" + * } + * } + * } + * }, + * "name": "Your Clinic Name Here Now", + * "telecom": { + * { + * "system": "phone", + * "value": "000-000-0000", + * "use": "work" + * }, + * { + * "system": "fax", + * "value": "000-000-0000", + * "use": "work" + * } + * }, + * "address": { + * null + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "POST /fhir/Organization" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "admin", "super"); + $data = (array) (json_decode(file_get_contents("php://input"), true)); + $return = (new FhirOrganizationRestController())->post($data); + + return $return; + }, + + /** + * @OA\Put( + * path="/fhir/Organization/{uuid}", + * description="Modifies a Organization resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the organization.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * description="The json object for the Organization resource.", + * type="object" + * ), + * example={ + * "id": "95f0e672-be37-4c73-95c9-649c2d200018", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2022-03-30T07:43:23+00:00" + * }, + * "resourceType": "Organization", + * "text": { + * "status": "generated", + * "div": "

Your Clinic Name Here

" + * }, + * "identifier": { + * { + * "system": "http://hl7.org/fhir/sid/us-npi", + * "value": "1234567890" + * } + * }, + * "active": true, + * "type": { + * { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/organization-type", + * "code": "prov", + * "display": "Healthcare Provider" + * } + * } + * } + * }, + * "name": "Your Clinic Name Here", + * "telecom": { + * { + * "system": "phone", + * "value": "000-000-0000", + * "use": "work" + * }, + * { + * "system": "fax", + * "value": "000-000-0000", + * "use": "work" + * } + * }, + * "address": { + * null + * } + * } + * ) + * ), + * @OA\Response( + * response="201", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * example={ + * "id": 14, + * "uuid": "95f217c1-258c-44ca-bf11-909dce369574" + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "PUT /fhir/Organization/:uuid" => function ($uuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "admin", "super"); + $data = (array) (json_decode(file_get_contents("php://input"), true)); + $return = (new FhirOrganizationRestController())->patch($uuid, $data); + + return $return; + }, + + /** + * @OA\Post( + * path="/fhir/Patient", + * description="Adds a Patient resource.", + * tags={"fhir"}, + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * description="The json object for the Patient resource.", + * type="object" + * ), + * example={ + * "id": "95f22ff4-dd25-4290-8b52-1dd2fedf8e54", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2022-03-31T02:48:28+00:00" + * }, + * "resourceType": "Patient", + * "text": { + * "status": "generated", + * "div": "

Brenda Smith

" + * }, + * "extension": { + * { + * "valueCode": "F", + * "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex" + * }, + * { + * "extension": { + * { + * "valueCoding": { + * "system": "http://terminology.hl7.org/CodeSystem/v3-NullFlavor", + * "code": "UNK", + * "display": "Unknown" + * }, + * "url": "ombCategory" + * }, + * { + * "valueString": "Unknown", + * "url": "text" + * } + * }, + * "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race" + * } + * }, + * "identifier": { + * { + * "use": "official", + * "type": { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + * "code": "PT" + * } + * } + * }, + * "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + * "value": "1" + * } + * }, + * "active": true, + * "name": { + * { + * "use": "official", + * "family": "Smith", + * "given": { + * "Brenda" + * } + * } + * }, + * "gender": "female", + * "birthDate": "2017-03-10", + * "communication": { + * { + * "language": { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/data-absent-reason", + * "code": "unknown", + * "display": "Unknown" + * } + * } + * } + * } + * } + * } + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "95f22ff4-dd25-4290-8b52-1dd2fedf8e54", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2022-03-31T02:48:28+00:00" + * }, + * "resourceType": "Patient", + * "text": { + * "status": "generated", + * "div": "

Brenda Smith

" + * }, + * "extension": { + * { + * "valueCode": "F", + * "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex" + * }, + * { + * "extension": { + * { + * "valueCoding": { + * "system": "http://terminology.hl7.org/CodeSystem/v3-NullFlavor", + * "code": "UNK", + * "display": "Unknown" + * }, + * "url": "ombCategory" + * }, + * { + * "valueString": "Unknown", + * "url": "text" + * } + * }, + * "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race" + * } + * }, + * "identifier": { + * { + * "use": "official", + * "type": { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + * "code": "PT" + * } + * } + * }, + * "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + * "value": "1" + * } + * }, + * "active": true, + * "name": { + * { + * "use": "official", + * "family": "Smith", + * "given": { + * "Brenda" + * } + * } + * }, + * "gender": "female", + * "birthDate": "2017-03-10", + * "communication": { + * { + * "language": { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/data-absent-reason", + * "code": "unknown", + * "display": "Unknown" + * } + * } + * } + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "POST /fhir/Patient" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "demo"); + $data = (array) (json_decode(file_get_contents("php://input"), true)); + $return = (new FhirPatientRestController())->post($data); + + return $return; + }, + + /** + * @OA\Put( + * path="/fhir/Patient/{uuid}", + * description="Modifies a Patient resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the Patient resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * description="The json object for the Patient resource.", + * type="object" + * ), + * example={ + * "id": "95f22ff4-dd25-4290-8b52-1dd2fedf8e54", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2022-03-31T02:48:28+00:00" + * }, + * "resourceType": "Patient", + * "text": { + * "status": "generated", + * "div": "

Brenda Smith

" + * }, + * "extension": { + * { + * "valueCode": "F", + * "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex" + * }, + * { + * "extension": { + * { + * "valueCoding": { + * "system": "http://terminology.hl7.org/CodeSystem/v3-NullFlavor", + * "code": "UNK", + * "display": "Unknown" + * }, + * "url": "ombCategory" + * }, + * { + * "valueString": "Unknown", + * "url": "text" + * } + * }, + * "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race" + * } + * }, + * "identifier": { + * { + * "use": "official", + * "type": { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + * "code": "PT" + * } + * } + * }, + * "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + * "value": "1" + * } + * }, + * "active": true, + * "name": { + * { + * "use": "official", + * "family": "Smith", + * "given": { + * "Brenda" + * } + * } + * }, + * "gender": "female", + * "birthDate": "2017-03-10", + * "communication": { + * { + * "language": { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/data-absent-reason", + * "code": "unknown", + * "display": "Unknown" + * } + * } + * } + * } + * } + * } + * ) + * ), + * @OA\Response( + * response="201", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * example={ + * "id": 2, + * "uuid": "95f2ad04-5834-4243-8838-e396a7faadbf" + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "PUT /fhir/Patient/:uuid" => function ($uuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "demo"); + $data = (array) (json_decode(file_get_contents("php://input"), true)); + $return = (new FhirPatientRestController())->put($uuid, $data); + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Patient", + * description="Returns a list of Patient resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the Patient resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="identifier", + * in="query", + * description="The identifier of the Patient resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="name", + * in="query", + * description="The name of the Patient resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="birthdate", + * in="query", + * description="The birthdate of the Patient resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="gender", + * in="query", + * description="The gender of the Patient resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="address", + * in="query", + * description="The address of the Patient resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="address-city", + * in="query", + * description="The address-city of the Patient resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="address-postalcode", + * in="query", + * description="The address-postalcode of the Patient resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="address-state", + * in="query", + * description="The address-state of the Patient resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="email", + * in="query", + * description="The email of the Patient resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="family", + * in="query", + * description="The family name of the Patient resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="given", + * in="query", + * description="The given name of the Patient resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="phone", + * in="query", + * description="The phone number of the Patient resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="telecom", + * in="query", + * description="The fax number of the Patient resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * ref="#/components/parameters/_lastUpdated" + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/Patient" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Patient" => function (HttpRestRequest $request) { + $params = $request->getQueryParams(); + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + // Note in Patient context still have to return a bundle even if it is just one resource. (ie. + // need to use getAll rather than getOne) + $params['_id'] = $request->getPatientUUIDString(); + $return = (new FhirPatientRestController())->getAll($params, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "patients", "demo"); + $return = (new FhirPatientRestController())->getAll($params); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Patient/$export", + * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API", + * tags={"fhir"}, + * @OA\Response( + * response="200", + * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + // we have to have the bulk fhir export operation here otherwise it will match $export to the patient $id + 'GET /fhir/Patient/$export' => function (HttpRestRequest $request, OEGlobalsBag $globalsBag) { + RestConfig::request_authorization_check($request, "admin", "users"); + $fhirExportService = new FhirOperationExportRestController($request, $globalsBag); + $return = $fhirExportService->processExport( + $request->getQueryParams(), + 'Patient', + $request->getHeader('Accept')[0] ?? '', + $request->getHeader('Prefer')[0] ?? '' + ); + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Patient/{uuid}", + * description="Returns a single Patient resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the Patient resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "946da617-1a4a-4b2c-ae66-93b84377cb1e", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2021-09-21T17:08:03+00:00" + * }, + * "resourceType": "Patient", + * "text": { + * "status": "generated", + * "div": "

Aurore252 Von197

" + * }, + * "extension": { + * { + * "valueCode": "F", + * "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex" + * }, + * { + * "extension": { + * { + * "valueCoding": { + * "system": "urn:oid:2.16.840.1.113883.6.238", + * "code": "1006-6", + * "display": "Abenaki" + * }, + * "url": "ombCategory" + * }, + * { + * "valueString": "Abenaki", + * "url": "text" + * } + * }, + * "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race" + * }, + * { + * "extension": { + * { + * "valueString": "Declined To Specify", + * "url": "text" + * } + * }, + * "url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity" + * } + * }, + * "identifier": { + * { + * "use": "official", + * "type": { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + * "code": "PT" + * } + * } + * }, + * "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + * "value": "1" + * } + * }, + * "active": true, + * "name": { + * { + * "use": "official", + * "family": "Von197", + * "given": { + * "Aurore252" + * } + * } + * }, + * "gender": "female", + * "birthDate": "1970-07-03", + * "address": { + * { + * "line": { + * "245 Crona Wall" + * }, + * "city": "Boston", + * "state": "Massachusetts", + * "postalCode": "02215", + * "period": { + * "start": "2020-09-21T17:08:03.532+00:00" + * } + * } + * }, + * "communication": { + * { + * "language": { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/data-absent-reason", + * "code": "unknown", + * "display": "Unknown" + * } + * } + * } + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Patient/:uuid" => function ($uuid, HttpRestRequest $request) { + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + if (empty($uuid) || ($uuid != $request->getPatientUUIDString())) { + throw new AccessDeniedException("patients", "demo", "patient id invalid"); + } + $uuid = $request->getPatientUUIDString(); + } else { + RestConfig::request_authorization_check($request, "patients", "demo"); + } + $return = (new FhirPatientRestController())->getOne($uuid); + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Person", + * description="Returns a list of Person resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the Person resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="name", + * in="query", + * description="The name of the Person resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="active", + * in="query", + * description="The active status of the Person resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="address", + * in="query", + * description="The address of the Person resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="address-city", + * in="query", + * description="The address-city of the Person resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="address-postalcode", + * in="query", + * description="The address-postalcode of the Person resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="address-state", + * in="query", + * description="The address-state of the Person resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="email", + * in="query", + * description="The email of the Person resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="family", + * in="query", + * description="The family name of the Person resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="given", + * in="query", + * description="The given name of the Person resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="phone", + * in="query", + * description="The phone number of the Person resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="telecom", + * in="query", + * description="The fax number of the Person resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/Person" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Person" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "admin", "users"); + $return = (new FhirPersonRestController())->getAll($request->getQueryParams()); + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Person/{uuid}", + * description="Returns a single Person resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the Person resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "960c7cd6-187a-4119-8cd4-85389d80efb9", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2022-04-13T08:57:32+00:00" + * }, + * "resourceType": "Person", + * "text": { + * "status": "generated", + * "div": "

Administrator Administrator

" + * }, + * "name": { + * { + * "use": "official", + * "family": "Administrator", + * "given": { + * "Administrator", + * "Larry" + * } + * } + * }, + * "telecom": { + * { + * "system": "phone", + * "value": "1234567890", + * "use": "home" + * }, + * { + * "system": "phone", + * "value": "1234567890", + * "use": "work" + * }, + * { + * "system": "phone", + * "value": "1234567890", + * "use": "mobile" + * }, + * { + * "system": "email", + * "value": "hey@hey.com", + * "use": "home" + * } + * }, + * "address": { + * { + * "line": { + * "123 Lane Street" + * }, + * "city": "Bellevue", + * "state": "WA", + * "period": { + * "start": "2021-04-13T08:57:32.146+00:00" + * } + * } + * }, + * "active": true + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Person/:uuid" => function ($uuid, HttpRestRequest $request) { + // if the api user is requesting their own user we need to let it through + // this is because the /Person endpoint needs to be responsive to the fhirUser return value + // for the currently logged in user + if ($request->getRequestUserUUIDString() == $uuid) { + $return = (new FhirPersonRestController())->getOne($uuid); + } elseif (!$request->isPatientRequest()) { + // not a patient ,make sure we have access to the users ACL + RestConfig::request_authorization_check($request, "admin", "users"); + $return = (new FhirPersonRestController())->getOne($uuid); + } else { + // if we are a patient bound request we need to make sure we are only bound to the patient + $return = (new FhirPersonRestController())->getOne($uuid, $request->getPatientUUIDString()); + } + + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Practitioner", + * description="Returns a list of Practitioner resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the Practitioner resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="name", + * in="query", + * description="The name of the Practitioner resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="active", + * in="query", + * description="The active status of the Practitioner resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="address", + * in="query", + * description="The address of the Practitioner resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="address-city", + * in="query", + * description="The address-city of the Practitioner resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="address-postalcode", + * in="query", + * description="The address-postalcode of the Practitioner resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="address-state", + * in="query", + * description="The address-state of the Practitioner resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="email", + * in="query", + * description="The email of the Practitioner resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="family", + * in="query", + * description="The family name of the Practitioner resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="given", + * in="query", + * description="The given name of the Practitioner resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="phone", + * in="query", + * description="The phone number of the Practitioner resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="telecom", + * in="query", + * description="The fax number of the Practitioner resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/Practitioner" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Practitioner" => function (HttpRestRequest $request) { + + // TODO: @adunsulag talk with brady.miller about patients needing access to any practitioner resource + // that is referenced in connected patient resources -- such as AllergyIntollerance. + // I don't believe patients are assigned to a particular practitioner + // should we allow just open api access to admin information? Should we restrict particular pieces + // of data in the practitioner side (phone number, address information) based on a permission set? + if (!$request->isPatientRequest()) { + RestConfig::request_authorization_check($request, "admin", "users"); + } + $return = (new FhirPractitionerRestController())->getAll($request->getQueryParams()); + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Practitioner/{uuid}", + * description="Returns a single Practitioner resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the Practitioner resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "9473b0cf-e969-4eaa-8044-51037767fa4f", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2021-09-21T17:41:57+00:00" + * }, + * "resourceType": "Practitioner", + * "text": { + * "status": "generated", + * "div": "

Billy Smith

" + * }, + * "identifier": { + * { + * "system": "http://hl7.org/fhir/sid/us-npi", + * "value": "11223344554543" + * } + * }, + * "active": true, + * "name": { + * { + * "use": "official", + * "family": "Smith", + * "given": { + * "Billy" + * } + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Practitioner/:uuid" => function ($uuid, HttpRestRequest $request) { + // TODO: @adunsulag talk with brady.miller about patients needing access to any practitioner resource + // that is referenced in connected patient resources -- such as AllergyIntollerance. + // I don't believe patients are assigned to a particular practitioner + // should we allow just open api access to admin information? Should we restrict particular pieces + // of data in the practitioner side (phone number, address information) based on a permission set? + if (!$request->isPatientRequest()) { + RestConfig::request_authorization_check($request, "admin", "users"); + } + $return = (new FhirPractitionerRestController())->getOne($uuid); + + return $return; + }, + + /** + * @OA\Post( + * path="/fhir/Practitioner", + * description="Adds a Practitioner resources.", + * tags={"fhir"}, + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * description="The json object for the Practitioner resource.", + * type="object" + * ), + * example={ + * "id": "9473b0cf-e969-4eaa-8044-51037767fa4f", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2021-09-21T17:41:57+00:00" + * }, + * "resourceType": "Practitioner", + * "text": { + * "status": "generated", + * "div": "

Billy Smith

" + * }, + * "identifier": { + * { + * "system": "http://hl7.org/fhir/sid/us-npi", + * "value": "11223344554543" + * } + * }, + * "active": true, + * "name": { + * { + * "use": "official", + * "family": "Smith", + * "given": { + * "Danny" + * } + * } + * } + * } + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "9473b0cf-e969-4eaa-8044-51037767fa4f", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2021-09-21T17:41:57+00:00" + * }, + * "resourceType": "Practitioner", + * "text": { + * "status": "generated", + * "div": "

Billy Smith

" + * }, + * "identifier": { + * { + * "system": "http://hl7.org/fhir/sid/us-npi", + * "value": "11223344554543" + * } + * }, + * "active": true, + * "name": { + * { + * "use": "official", + * "family": "Smith", + * "given": { + * "Danny" + * } + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "POST /fhir/Practitioner" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "admin", "users"); + $data = (array) (json_decode(file_get_contents("php://input"), true)); + $return = (new FhirPractitionerRestController())->post($data); + + return $return; + }, + + /** + * @OA\Put( + * path="/fhir/Practitioner/{uuid}", + * description="Modify a Practitioner resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the Practitioner resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * description="The json object for the Practitioner resource.", + * type="object" + * ), + * example={ + * "id": "9473b0cf-e969-4eaa-8044-51037767fa4f", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2021-09-21T17:41:57+00:00" + * }, + * "resourceType": "Practitioner", + * "text": { + * "status": "generated", + * "div": "

Billy Smith

" + * }, + * "identifier": { + * { + * "system": "http://hl7.org/fhir/sid/us-npi", + * "value": "11223344554543" + * } + * }, + * "active": true, + * "name": { + * { + * "use": "official", + * "family": "Smith", + * "given": { + * "Billy" + * } + * } + * } + * } + * ) + * ), + * @OA\Response( + * response="201", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * example={ + * "id": 5, + * "uuid": "95f294d7-e14c-441d-81a6-309fe369ee21" + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "PUT /fhir/Practitioner/:uuid" => function ($uuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "admin", "users"); + $data = (array) (json_decode(file_get_contents("php://input"), true)); + $return = (new FhirPractitionerRestController())->patch($uuid, $data); + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/PractitionerRole", + * description="Returns a list of PractitionerRole resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the PractitionerRole resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="specialty", + * in="query", + * description="The specialty of the PractitionerRole resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="practitioner", + * in="query", + * description="The practitioner of the PractitionerRole resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/PractitionerRole" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/PractitionerRole" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "admin", "users"); + $return = (new FhirPractitionerRoleRestController())->getAll($request->getQueryParams()); + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/PractitionerRole/{uuid}", + * description="Returns a single PractitionerRole resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the PractitionerRole resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "960c806f-9463-482e-b228-67b5be1fed55", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2022-04-13T06:18:17+00:00" + * }, + * "resourceType": "PractitionerRole", + * "practitioner": { + * "reference": "Practitioner/960c7cd6-187a-4119-8cd4-85389d80efb9", + * "display": "Administrator Administrator" + * }, + * "organization": { + * "reference": "Organization/960c7cc6-b4ae-49bc-877b-1a2913271c43", + * "display": "Your Clinic Name Here" + * }, + * "code": { + * { + * "coding": { + * "102L00000X" + * }, + * "text": "Psychoanalyst" + * }, + * { + * "coding": { + * "101Y00000X" + * }, + * "text": "Counselor" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/PractitionerRole/:uuid" => function ($uuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "admin", "users"); + $return = (new FhirPractitionerRoleRestController())->getOne($uuid); + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Procedure", + * description="Returns a list of Procedure resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the Procedure resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="patient", + * in="query", + * description="The uuid for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="date", + * in="query", + * description="The datetime of the Procedure resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/Procedure" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Procedure" => function (HttpRestRequest $request) { + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirProcedureRestController())->getAll($request->getQueryParams(), $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new FhirProcedureRestController())->getAll($request->getQueryParams()); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Procedure/{uuid}", + * description="Returns a single Procedure resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the Procedure resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "95e9d3fb-fe7b-448a-aa60-d40b11b486a5", + * "meta": { + * "versionId": "1", + * "lastUpdated": "2022-03-26T17:20:14+00:00" + * }, + * "resourceType": "Procedure", + * "status": "in-progress", + * "subject": { + * "reference": "Patient/95e8d830-3068-48cf-930a-2fefb18c2bcf", + * "type": "Patient" + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Procedure/:uuid" => function ($uuid, HttpRestRequest $request) { + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirProcedureRestController())->getOne($uuid, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new FhirProcedureRestController())->getOne($uuid); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Provenance/{uuid}", + * description="Returns a single Provenance resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The id for the Provenance resource. Format is \:\ (Example: AllergyIntolerance:95ea43f3-1066-4bc7-b224-6c23b985f145).", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "id": "AllergyIntolerance:95ea43f3-1066-4bc7-b224-6c23b985f145", + * "resourceType": "Provenance", + * "target": { + * { + * "reference": "AllergyIntolerance/95ea43f3-1066-4bc7-b224-6c23b985f145", + * "type": "AllergyIntolerance" + * } + * }, + * "recorded": "2022-03-26T22:43:30+00:00", + * "agent": { + * { + * "type": { + * "coding": { + * { + * "system": "http://terminology.hl7.org/CodeSystem/provenance-participant-type", + * "code": "author", + * "display": "Author" + * } + * } + * }, + * "who": { + * "reference": "Organization/95e8d810-7e55-44aa-bb48-fecd5b0d88c7", + * "type": "Organization" + * }, + * "onBehalfOf": { + * "reference": "Organization/95e8d810-7e55-44aa-bb48-fecd5b0d88c7", + * "type": "Organization" + * } + * }, + * { + * "type": { + * "coding": { + * { + * "system": "http://hl7.org/fhir/us/core/CodeSystem/us-core-provenance-participant-type", + * "code": "transmitter", + * "display": "Transmitter" + * } + * } + * } + * }, + * "who": { + * "reference": "Organization/95e8d810-7e55-44aa-bb48-fecd5b0d88c7", + * "type": "Organization" + * }, + * "onBehalfOf": { + * "reference": "Organization/95e8d810-7e55-44aa-bb48-fecd5b0d88c7", + * "type": "Organization" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Provenance/:uuid" => function ($uuid, HttpRestRequest $request) { + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirProvenanceRestController($request))->getOne($uuid, $request->getPatientUUIDString()); + } else { + RestConfig::request_authorization_check($request, "admin", "super"); + $return = (new FhirProvenanceRestController($request))->getOne($uuid); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Provenance", + * description="Returns a list of Provenance resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The id for the Provenance resource. Format is \:\ (Example: AllergyIntolerance:95ea43f3-1066-4bc7-b224-6c23b985f145).", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/Provenance" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + // NOTE: this GET request only supports requests with an _id parameter. FHIR inferno test tool requires the 'search' + // property to support which is why this endpoint exists. + "GET /fhir/Provenance" => function (HttpRestRequest $request) { + if ($request->isPatientRequest()) { + // only allow access to data of binded patient + $return = (new FhirProvenanceRestController($request))->getAll($request->getQueryParams(), $request->getPatientUUIDString()); + } else { + // TODO: it seems like regular users should be able to grab authorship / provenance information + RestConfig::request_authorization_check($request, "admin", "super"); + $return = (new FhirProvenanceRestController($request))->getAll($request->getQueryParams()); + } + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Questionnaire", + * description="Returns a list of Questionnaire resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The id for the Questionnaire resource. ", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/Questionnaire" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/Questionnaire" => function (HttpRestRequest $request) { + $logger = new SystemLogger(); + $fhirQuestionnaireService = new FhirQuestionnaireService(); + $fhirFormService = new FhirQuestionnaireFormService(); + $fhirQuestionnaireService->addMappedService($fhirFormService); + $return = (new FhirQuestionnaireRestController($logger, $fhirQuestionnaireService))->list($request); + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/Questionnaire", + * description="Returns a list of QuestionnaireResponse resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The id for the QuestionnaireResponse resource. ", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/QuestionnaireResponse" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/QuestionnaireResponse" => function (HttpRestRequest $request) { + $fhirQuestionnaireService = new FhirQuestionnaireResponseService(); + $fhirQuestionnaireService->addMappedService(new FhirQuestionnaireResponseFormService()); + $return = (new FhirQuestionnaireResponseRestController($fhirQuestionnaireService))->list($request); + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/ValueSet", + * description="Returns a list of ValueSet resources.", + * tags={"fhir"}, + * @OA\Parameter( + * name="_id", + * in="query", + * description="The uuid for the ValueSet resource.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_lastUpdated", + * in="query", + * description="Allows filtering resources by the _lastUpdated field. A FHIR Instant value in the format YYYY-MM-DDThh:mm:ss.sss+zz:zz. See FHIR date/time modifiers for filtering options (ge,gt,le, etc)", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "meta": { + * "lastUpdated": "2021-09-14T09:13:51" + * }, + * "resourceType": "Bundle", + * "type": "collection", + * "total": 0, + * "link": { + * { + * "relation": "self", + * "url": "https://localhost:9300/apis/default/fhir/ValueSet" + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/ValueSet" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "admin", "super"); + $return = (new FhirValueSetRestController())->getAll($request->getQueryParams()); + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/ValueSet/{uuid}", + * description="Returns a single ValueSet resource.", + * tags={"fhir"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the ValueSet resource.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "resourceType": "ValueSet", + * "id": "appointment-type", + * "compose": { + * "include": { + * { + * "concept": { + * { + * "code": "no_show", + * "display": "No Show" + * }, + * { + * "code": "office_visit", + * "display": "Office Visit" + * }, + * { + * "code": "established_patient", + * "display": "Established Patient" + * }, + * { + * "code": "new_patient", + * "display": "New Patient" + * }, + * { + * "code": "health_and_behavioral_assessment", + * "display": "Health and Behavioral Assessment" + * }, + * { + * "code": "preventive_care_services", + * "display": "Preventive Care Services" + * }, + * { + * "code": "ophthalmological_services", + * "display": "Ophthalmological Services" + * } + * } + * } + * } + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * @OA\Response( + * response="404", + * ref="#/components/responses/uuidnotfound" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /fhir/ValueSet/:uuid" => function ($uuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "admin", "super"); + $return = (new FhirValueSetRestController())->getOne($uuid); + + return $return; + }, + + // other endpoints + + /** + * @OA\Get( + * path="/fhir/metadata", + * description="Returns metadata (ie. CapabilityStatement resource) of the fhir server.", + * tags={"fhir"}, + * @OA\Response( + * response="200", + * description="Return CapabilityStatement resource of the fhir server" + * ) + * ) + */ + "GET /fhir/metadata" => function (\OpenEMR\Common\Http\HttpRestRequest $request) { + $return = (new FhirMetaDataRestController())->getMetaData(); + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/.well-known/smart-configuration", + * description="Returns smart configuration of the fhir server.", + * tags={"fhir"}, + * @OA\Response( + * response="200", + * description="Return smart configuration of the fhir server" + * ) + * ) + */ + "GET /fhir/.well-known/smart-configuration" => function () { + $return = (new SMARTConfigurationController())->getConfig(); + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/OperationDefinition", + * description="Returns a list of the OperationDefinition resources that are specific to this OpenEMR installation", + * tags={"fhir"}, + * @OA\Response( + * response="200", + * description="Return list of OperationDefinition resources" + * ) + * ) + */ + "GET /fhir/OperationDefinition" => function (HttpRestRequest $request) { + // for now we will just hard code the custom resources + $operationDefinitionController = new FhirOperationDefinitionRestController(); + $return = $operationDefinitionController->getAll($request->getQueryParams()); + + return $return; + }, + + /** + * @OA\Get( + * path="/fhir/OperationDefinition/{operation}", + * description="Returns a single OperationDefinition resource that is specific to this OpenEMR installation", + * tags={"fhir"}, + * @OA\Parameter( + * name="operation", + * in="path", + * description="The name of the operation to query. For example $bulkdata-status", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard Response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="json object", + * description="FHIR Json object.", + * type="object" + * ), + * example={ + * "resourceType": "OperationDefinition", + * "name": "$bulkdata-status", + * "status": "active", + * "kind": "operation", + * "parameter": { + * { + * "name": "job", + * "use": "in", + * "min": 1, + * "max": 1, + * "type": { + * "system": "http://hl7.org/fhir/data-types", + * "code": "string", + * "display": "string" + * }, + * "searchType": { + * "system": "http://hl7.org/fhir/ValueSet/search-param-type", + * "code": "string", + * "display": "string" + * } + * } + * } + * } + * ) + * ) + * ), + * ) + */ + "GET /fhir/OperationDefinition/:operation" => function ($operation, HttpRestRequest $request) { + // for now we will just hard code the custom resources + $operationDefinitionController = new FhirOperationDefinitionRestController(); + $return = $operationDefinitionController->getOne($operation); + + return $return; + }, + + // FHIR root level operations + + /** + * @OA\Get( + * path="/fhir/$export", + * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API", + * tags={"fhir"}, + * @OA\Response( + * response="200", + * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + 'GET /fhir/$export' => function (HttpRestRequest $request, OEGlobalsBag $globalsBag) { + RestConfig::request_authorization_check($request, "admin", "users"); + $fhirExportService = new FhirOperationExportRestController($request, $globalsBag); + $return = $fhirExportService->processExport( + $request->getQueryParams(), + 'System', + $request->getHeader('Accept')[0] ?? '', + $request->getHeader('Prefer')[0] ?? '' + ); + + return $return; + }, + + // these two operations are adopted based on the documentation used in the IBM FHIR Server + // we'd reference cerner or epic but we couldn't find any documentation about those (Jan 30th 2021) + // @see https://ibm.github.io/FHIR/guides/FHIRBulkOperations/ + + /** + * @OA\Get( + * path="/fhir/$bulkdata-status", + * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API", + * tags={"fhir"}, + * @OA\Response( + * response="200", + * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + 'GET /fhir/$bulkdata-status' => function (HttpRestRequest $request, OEGlobalsBag $globalsBag) { + RestConfig::request_authorization_check($request, "admin", "users"); + $jobUuidString = $request->getQueryParam('job'); + // if we were truly async we would return 202 here to say we are in progress with a JSON response + // since OpenEMR data is so small we just return the JSON from the database + $fhirExportService = new FhirOperationExportRestController($request, $globalsBag); + $return = $fhirExportService->processExportStatusRequestForJob($jobUuidString); + + return $return; + }, + + /** + * @OA\Delete( + * path="/fhir/$bulkdata-status", + * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API", + * tags={"fhir"}, + * @OA\Response( + * response="200", + * description="The BULK FHIR Exports documentation can be found at https://www.open-emr.org/wiki/index.php/OpenEMR_Wiki_Home_Page#API" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + 'DELETE /fhir/$bulkdata-status' => function (HttpRestRequest $request, OEGlobalsBag $globalsBag) { + RestConfig::request_authorization_check($request, "admin", "users"); + $job = $request->getQueryParam('job'); + $fhirExportService = new FhirOperationExportRestController($request, $globalsBag); + $return = $fhirExportService->processDeleteExportForJob($job); + + return $return; + }, +); diff --git a/apis/routes/_rest_routes_portal.inc.php b/apis/routes/_rest_routes_portal.inc.php new file mode 100644 index 000000000000..7bb87570c16d --- /dev/null +++ b/apis/routes/_rest_routes_portal.inc.php @@ -0,0 +1,172 @@ + + * @author Jerry Padgett + * @author Brady Miller + * @author Yash Raj Bothra + * @author Stephen Nielson + * @copyright Copyright (c) 2018 Matthew Vita + * @copyright Copyright (c) 2018-2020 Jerry Padgett + * @copyright Copyright (c) 2019-2021 Brady Miller + * @copyright Copyright (c) 2020 Yash Raj Bothra + * @copyright Copyright (c) 2024 Care Management Solutions, Inc. + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ + +use OpenEMR\RestControllers\PatientRestController; +use OpenEMR\RestControllers\EncounterRestController; +use OpenEMR\RestControllers\AppointmentRestController; +use OpenEMR\Common\Http\HttpRestRequest; + +// Note that the portal (api) route is only for patient role +// (there is a mechanism in place to ensure only patient role can access the portal (api) route) +return array( + /** + * @OA\Get( + * path="/portal/patient", + * description="Returns the patient.", + * tags={"standard-patient"}, + * @OA\Response( + * response="200", + * description="Standard response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_patient_response") + * ) + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /portal/patient" => function (HttpRestRequest $request) { + $return = (new PatientRestController())->getOne($request->getPatientUUIDString()); + return $return; + }, + + /** + * @OA\Get( + * path="/portal/patient/encounter", + * description="Returns encounters for the patient.", + * tags={"standard-patient"}, + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /portal/patient/encounter" => function (HttpRestRequest $request) { + $return = (new EncounterRestController($request->getSession()))->getAll($request->getPatientUUIDString()); + return $return; + }, + + /** + * @OA\Get( + * path="/portal/patient/encounter/{euuid}", + * description="Returns a selected encounter by its uuid.", + * tags={"standard-patient"}, + * @OA\Parameter( + * name="euuid", + * in="path", + * description="The uuid for the encounter.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /portal/patient/encounter/:euuid" => function ($euuid, HttpRestRequest $request) { + $return = (new EncounterRestController($request->getSession()))->getOne($request->getPatientUUIDString(), $euuid); + return $return; + }, + + /** + * @OA\Get( + * path="/portal/patient/appointment", + * description="Retrieves all appointments for a patient", + * tags={"standard-patient"}, + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /portal/patient/appointment" => function (HttpRestRequest $request) { + $return = (new AppointmentRestController())->getAllForPatientByUuid($request->getPatientUUIDString()); + return $return; + }, + + + /** + * @OA\Get( + * path="/portal/patient/appointment/{auuid}", + * description="Returns a selected appointment by its uuid.", + * tags={"standard-patient"}, + * @OA\Parameter( + * name="auuid", + * in="path", + * description="The uuid for the appointment.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /portal/patient/appointment/:auuid" => function ($auuid, HttpRestRequest $request) { + $return = (new AppointmentRestController())->getOneForPatient($auuid, $request->getPatientUUIDString()); + return $return; + } +); diff --git a/apis/routes/_rest_routes_standard.inc.php b/apis/routes/_rest_routes_standard.inc.php new file mode 100644 index 000000000000..381893db16b5 --- /dev/null +++ b/apis/routes/_rest_routes_standard.inc.php @@ -0,0 +1,7289 @@ + + * @author Jerry Padgett + * @author Brady Miller + * @author Yash Raj Bothra + * @author Stephen Nielson + * @copyright Copyright (c) 2018 Matthew Vita + * @copyright Copyright (c) 2018-2020 Jerry Padgett + * @copyright Copyright (c) 2019-2021 Brady Miller + * @copyright Copyright (c) 2020 Yash Raj Bothra + * @copyright Copyright (c) 2024 Care Management Solutions, Inc. + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ + +use OpenEMR\Common\Http\HttpRestRequest; +use OpenEMR\Common\Uuid\UuidRegistry; +use OpenEMR\RestControllers\AllergyIntoleranceRestController; +use OpenEMR\RestControllers\AppointmentRestController; +use OpenEMR\RestControllers\ConditionRestController; +use OpenEMR\RestControllers\DocumentRestController; +use OpenEMR\RestControllers\DrugRestController; +use OpenEMR\RestControllers\EmployerRestController; +use OpenEMR\RestControllers\EncounterRestController; +use OpenEMR\RestControllers\FacilityRestController; +use OpenEMR\RestControllers\ImmunizationRestController; +use OpenEMR\RestControllers\InsuranceCompanyRestController; +use OpenEMR\RestControllers\InsuranceRestController; +use OpenEMR\RestControllers\ListRestController; +use OpenEMR\RestControllers\MessageRestController; +use OpenEMR\RestControllers\PatientRestController; +use OpenEMR\RestControllers\PractitionerRestController; +use OpenEMR\RestControllers\PrescriptionRestController; +use OpenEMR\RestControllers\ProcedureRestController; +use OpenEMR\RestControllers\ProductRegistrationRestController; +use OpenEMR\RestControllers\RestControllerHelper; +use OpenEMR\RestControllers\TransactionRestController; +use OpenEMR\RestControllers\UserRestController; +use OpenEMR\RestControllers\VersionRestController; +use OpenEMR\Services\Search\SearchQueryConfig; +// TODO: Remove this import when the OpenEMR\RestControllers\Config\RestConfig is no longer needed +use OpenEMR\RestControllers\Config\RestConfig; + +return array( + /** + * @OA\Get( + * path="/api/facility", + * description="Returns a single facility.", + * tags={"standard"}, + * @OA\Parameter( + * name="name", + * in="query", + * description="The name for the facility.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="facility_npi", + * in="query", + * description="The facility_npi for the facility.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="phone", + * in="query", + * description="The phone for the facility.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="fax", + * in="query", + * description="The fax for the facility.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="street", + * in="query", + * description="The street for the facility.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="city", + * in="query", + * description="The city for the facility.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="state", + * in="query", + * description="The state for the facility.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="postal_code", + * in="query", + * description="The postal_code for the facility.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="country_code", + * in="query", + * description="The country_code for the facility.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="federal_ein", + * in="query", + * description="The federal_ein for the facility.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="website", + * in="query", + * description="The website for the facility.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="email", + * in="query", + * description="The email for the facility.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="domain_identifier", + * in="query", + * description="The domain_identifier for the facility.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="facility_taxonomy", + * in="query", + * description="The facility_taxonomy for the facility.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="facility_code", + * in="query", + * description="The facility_code for the facility.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="billing_location", + * in="query", + * description="The billing_location setting for the facility.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="accepts_assignment", + * in="query", + * description="The accepts_assignment setting for the facility.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="oid", + * in="query", + * description="The oid for the facility.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="service_location", + * in="query", + * description="The service_location setting for the facility.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/facility" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "admin", "users"); + $return = (new FacilityRestController())->getAll($request, $_GET); + return $return; + }, + + /** + * @OA\Get( + * path="/api/facility/{fuuid}", + * description="Returns a single facility.", + * tags={"standard"}, + * @OA\Parameter( + * name="fuuid", + * in="path", + * description="The uuid for the facility.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/facility/:fuuid" => function ($fuuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "admin", "users"); + $return = (new FacilityRestController())->getOne($fuuid, $request); + + return $return; + }, + + /** + * @OA\Post( + * path="/api/facility", + * description="Creates a facility in the system", + * tags={"standard"}, + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="name", + * description="The name for the facility.", + * type="string" + * ), + * @OA\Property( + * property="facility_npi", + * description="The facility_npi for the facility.", + * type="string" + * ), + * @OA\Property( + * property="phone", + * description="The phone for the facility.", + * type="string" + * ), + * @OA\Property( + * property="fax", + * description="The fax for the facility.", + * type="string" + * ), + * @OA\Property( + * property="street", + * description="The street for the facility.", + * type="string" + * ), + * @OA\Property( + * property="city", + * description="The city for the facility.", + * type="string" + * ), + * @OA\Property( + * property="state", + * description="The state for the facility.", + * type="string" + * ), + * @OA\Property( + * property="postal_code", + * description="The postal_code for the facility.", + * type="string" + * ), + * @OA\Property( + * property="country_code", + * description="The country_code for the facility.", + * type="string" + * ), + * @OA\Property( + * property="federal_ein", + * description="The federal_ein for the facility.", + * type="string" + * ), + * @OA\Property( + * property="website", + * description="The website for the facility.", + * type="string" + * ), + * @OA\Property( + * property="email", + * description="The email for the facility.", + * type="string" + * ), + * @OA\Property( + * property="domain_identifier", + * description="The domain_identifier for the facility.", + * type="string" + * ), + * @OA\Property( + * property="facility_taxonomy", + * description="The facility_taxonomy for the facility.", + * type="string" + * ), + * @OA\Property( + * property="facility_code", + * description="The facility_code for the facility.", + * type="string" + * ), + * @OA\Property( + * property="billing_location", + * description="The billing_location setting for the facility.", + * type="string" + * ), + * @OA\Property( + * property="accepts_assignment", + * description="The accepts_assignment setting for the facility.", + * type="string" + * ), + * @OA\Property( + * property="oid", + * description="The oid for the facility.", + * type="string" + * ), + * @OA\Property( + * property="service_location", + * description="The service_location setting for the facility.", + * type="string" + * ), + * required={"name", "facility_npi"}, + * example={ + * "name": "Aquaria", + * "facility_npi": "123456789123", + * "phone": "808-606-3030", + * "fax": "808-606-3031", + * "street": "1337 Bit Shifter Ln", + * "city": "San Lorenzo", + * "state": "ZZ", + * "postal_code": "54321", + * "country_code": "US", + * "federal_ein": "4343434", + * "website": "https://example.com", + * "email": "foo@bar.com", + * "domain_identifier": "", + * "facility_taxonomy": "", + * "facility_code": "", + * "billing_location": "1", + * "accepts_assignment": "1", + * "oid": "", + * "service_location": "1" + * } + * ) + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "POST /api/facility" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "admin", "super"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new FacilityRestController())->post($data, $request); + + return $return; + }, + + /** + * @OA\Put( + * path="/api/facility/{fuuid}", + * description="Updates a facility in the system", + * tags={"standard"}, + * @OA\Parameter( + * name="fuuid", + * in="path", + * description="The uuid for the facility.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="name", + * description="The name for the facility.", + * type="string" + * ), + * @OA\Property( + * property="facility_npi", + * description="The facility_npi for the facility.", + * type="string" + * ), + * @OA\Property( + * property="phone", + * description="The phone for the facility.", + * type="string" + * ), + * @OA\Property( + * property="fax", + * description="The fax for the facility.", + * type="string" + * ), + * @OA\Property( + * property="street", + * description="The street for the facility.", + * type="string" + * ), + * @OA\Property( + * property="city", + * description="The city for the facility.", + * type="string" + * ), + * @OA\Property( + * property="state", + * description="The state for the facility.", + * type="string" + * ), + * @OA\Property( + * property="postal_code", + * description="The postal_code for the facility.", + * type="string" + * ), + * @OA\Property( + * property="country_code", + * description="The country_code for the facility.", + * type="string" + * ), + * @OA\Property( + * property="federal_ein", + * description="The federal_ein for the facility.", + * type="string" + * ), + * @OA\Property( + * property="website", + * description="The website for the facility.", + * type="string" + * ), + * @OA\Property( + * property="email", + * description="The email for the facility.", + * type="string" + * ), + * @OA\Property( + * property="domain_identifier", + * description="The domain_identifier for the facility.", + * type="string" + * ), + * @OA\Property( + * property="facility_taxonomy", + * description="The facility_taxonomy for the facility.", + * type="string" + * ), + * @OA\Property( + * property="facility_code", + * description="The facility_code for the facility.", + * type="string" + * ), + * @OA\Property( + * property="billing_location", + * description="The billing_location setting for the facility.", + * type="string" + * ), + * @OA\Property( + * property="accepts_assignment", + * description="The accepts_assignment setting for the facility.", + * type="string" + * ), + * @OA\Property( + * property="oid", + * description="The oid for the facility.", + * type="string" + * ), + * @OA\Property( + * property="service_location", + * description="The service_location setting for the facility.", + * type="string" + * ), + * example={ + * "name": "Aquaria", + * "facility_npi": "123456789123", + * "phone": "808-606-3030", + * "fax": "808-606-3031", + * "street": "1337 Bit Shifter Ln", + * "city": "San Lorenzo", + * "state": "ZZ", + * "postal_code": "54321", + * "country_code": "US", + * "federal_ein": "4343434", + * "website": "https://example.com", + * "email": "foo@bar.com", + * "domain_identifier": "", + * "facility_taxonomy": "", + * "facility_code": "", + * "billing_location": "1", + * "accepts_assignment": "1", + * "oid": "", + * "service_location": "1" + * } + * ) + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "PUT /api/facility/:fuuid" => function ($fuuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "admin", "super"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new FacilityRestController())->patch($fuuid, $data, $request); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient", + * description="Retrieves a list of patients", + * tags={"standard"}, + * @OA\Parameter( + * ref="#/components/parameters/_sort" + * ), + * @OA\Parameter( + * name="fname", + * in="query", + * description="The first name for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="lname", + * in="query", + * description="The last name for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="ss", + * in="query", + * description="The social security number for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="street", + * in="query", + * description="The street for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="postal_code", + * in="query", + * description="The postal code for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="city", + * in="query", + * description="The city for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="state", + * in="query", + * description="The state for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="phone_home", + * in="query", + * description="The home phone for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="phone_biz", + * in="query", + * description="The business phone for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="phone_cell", + * in="query", + * description="The cell phone for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="postal_contact", + * in="query", + * description="The postal_contact for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="sex", + * in="query", + * description="The gender for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="country_code", + * in="query", + * description="The country code for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="email", + * in="query", + * description="The email for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="DOB", + * in="query", + * description="The DOB for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="date", + * in="query", + * description="The date this patient resource was last modified.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="_offset", + * in="query", + * description="The number of records to offset from this index in the search result.", + * required=false, + * @OA\Schema( + * type="integer" + * ) + * ), + * @OA\Parameter( + * name="_limit", + * in="query", + * description="The maximum number of resources to return in the result set. 0 means unlimited.", + * required=false, + * @OA\Schema( + * type="integer" + * ,minimum=0 + * ,maximum=200 + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "demo"); + $config = SearchQueryConfig::createConfigFromQueryParams($request->query->all()); + $return = (new PatientRestController())->getAll($request, $request->query->all(), $config); + + return $return; + }, + + /** + * Schema for the patient request + * + * @OA\Schema( + * schema="api_patient_request", + * @OA\Property( + * property="title", + * description="The title of patient.", + * type="string" + * ), + * @OA\Property( + * property="fname", + * description="The fname of patient.", + * type="string" + * ), + * @OA\Property( + * property="mname", + * description="The mname of patient.", + * type="string" + * ), + * @OA\Property( + * property="lname", + * description="The lname of patient.", + * type="string" + * ), + * @OA\Property( + * property="street", + * description="The street address of patient.", + * type="string" + * ), + * @OA\Property( + * property="postal_code", + * description="The postal code of patient.", + * type="string" + * ), + * @OA\Property( + * property="city", + * description="The city of patient.", + * type="string" + * ), + * @OA\Property( + * property="state", + * description="The state of patient.", + * type="string" + * ), + * @OA\Property( + * property="country_code", + * description="The country code of patient.", + * type="string" + * ), + * @OA\Property( + * property="phone_contact", + * description="The phone contact of patient.", + * type="string" + * ), + * @OA\Property( + * property="DOB", + * description="The DOB of patient.", + * type="string" + * ), + * @OA\Property( + * property="sex", + * description="The lname of patient.", + * type="string" + * ), + * @OA\Property( + * property="race", + * description="The race of patient.", + * type="string" + * ), + * @OA\Property( + * property="ethnicity", + * description="The ethnicity of patient.", + * type="string" + * ), + * required={"fname", "lname", "DOB", "sex"}, + * example={ + * "title": "Mr", + * "fname": "Foo", + * "mname": "", + * "lname": "Bar", + * "street": "456 Tree Lane", + * "postal_code": "08642", + * "city": "FooTown", + * "state": "FL", + * "country_code": "US", + * "phone_contact": "123-456-7890", + * "DOB": "1992-02-02", + * "sex": "Male", + * "race": "", + * "ethnicity": "" + * } + * ) + */ + /** + * @OA\Post( + * path="/api/patient", + * description="Creates a new patient", + * tags={"standard"}, + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_patient_request") + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="validationErrors", + * description="Validation errors.", + * type="array", + * @OA\Items( + * type="object", + * ), + * ), + * @OA\Property( + * property="internalErrors", + * description="Internal errors.", + * type="array", + * @OA\Items( + * type="object", + * ), + * ), + * @OA\Property( + * property="data", + * description="Returned data.", + * type="array", + * @OA\Items( + * @OA\Property( + * property="pid", + * description="patient pid", + * type="integer", + * ) + * ), + * ), + * example={ + * "validationErrors": {}, + * "error_description": {}, + * "data": { + * "pid": 1 + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "POST /api/patient" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "demo"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new PatientRestController())->post($data, $request); + + return $return; + }, + + /** + * Schema for the patient response + * + * @OA\Schema( + * schema="api_patient_response", + * @OA\Property( + * property="validationErrors", + * description="Validation errors.", + * type="array", + * @OA\Items( + * type="object", + * ), + * ), + * @OA\Property( + * property="internalErrors", + * description="Internal errors.", + * type="array", + * @OA\Items( + * type="object", + * ), + * ), + * @OA\Property( + * property="data", + * description="Returned data.", + * type="array", + * @OA\Items( + * @OA\Property( + * property="id", + * description="patient id", + * type="string", + * ), + * @OA\Property( + * property="pid", + * description="patient pid", + * type="string", + * ), + * @OA\Property( + * property="pubpid", + * description="patient public id", + * type="string", + * ), + * @OA\Property( + * property="title", + * description="patient title", + * type="string", + * ), + * @OA\Property( + * property="fname", + * description="patient first name", + * type="string", + * ), + * @OA\Property( + * property="mname", + * description="patient middle name", + * type="string", + * ), + * @OA\Property( + * property="lname", + * description="patient last name", + * type="string", + * ), + * @OA\Property( + * property="ss", + * description="patient social security number", + * type="string", + * ), + * @OA\Property( + * property="street", + * description="patient street address", + * type="string", + * ), + * @OA\Property( + * property="postal_code", + * description="patient postal code", + * type="string", + * ), + * @OA\Property( + * property="city", + * description="patient city", + * type="string", + * ), + * @OA\Property( + * property="state", + * description="patient state", + * type="string", + * ), + * @OA\Property( + * property="county", + * description="patient county", + * type="string", + * ), + * @OA\Property( + * property="country_code", + * description="patient country code", + * type="string", + * ), + * @OA\Property( + * property="drivers_license", + * description="patient drivers license id", + * type="string", + * ), + * @OA\Property( + * property="contact_relationship", + * description="patient contact relationship", + * type="string", + * ), + * @OA\Property( + * property="phone_contact", + * description="patient phone contact", + * type="string", + * ), + * @OA\Property( + * property="phone_home", + * description="patient home phone", + * type="string", + * ), + * @OA\Property( + * property="phone_biz", + * description="patient work phone", + * type="string", + * ), + * @OA\Property( + * property="phone_cell", + * description="patient mobile phone", + * type="string", + * ), + * @OA\Property( + * property="email", + * description="patient email", + * type="string", + * ), + * @OA\Property( + * property="DOB", + * description="patient DOB", + * type="string", + * ), + * @OA\Property( + * property="sex", + * description="patient sex (gender)", + * type="string", + * ), + * @OA\Property( + * property="race", + * description="patient race", + * type="string", + * ), + * @OA\Property( + * property="ethnicity", + * description="patient ethnicity", + * type="string", + * ), + * @OA\Property( + * property="status", + * description="patient status", + * type="string", + * ), + * ), + * ), + * example={ + * "validationErrors": {}, + * "error_description": {}, + * "data": { + * "id": "193", + * "pid": "1", + * "pubpid": "", + * "title": "Mr", + * "fname": "Baz", + * "mname": "", + * "lname": "Bop", + * "ss": "", + * "street": "456 Tree Lane", + * "postal_code": "08642", + * "city": "FooTown", + * "state": "FL", + * "county": "", + * "country_code": "US", + * "drivers_license": "", + * "contact_relationship": "", + * "phone_contact": "123-456-7890", + * "phone_home": "", + * "phone_biz": "", + * "phone_cell": "", + * "email": "", + * "DOB": "1992-02-03", + * "sex": "Male", + * "race": "", + * "ethnicity": "", + * "status": "" + * } + * } + * ) + */ + /** + * @OA\Put( + * path="/api/patient/{puuid}", + * description="Updates a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="puuid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_patient_request") + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_patient_response") + * ) + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "PUT /api/patient/:puuid" => function ($puuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "demo"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new PatientRestController())->put($puuid, $data, $request); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{puuid}", + * description="Retrieves a single patient by their uuid", + * tags={"standard"}, + * @OA\Parameter( + * name="puuid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_patient_response") + * ) + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:puuid" => function ($puuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "demo"); + $return = (new PatientRestController())->getOne($puuid, $request); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{puuid}/encounter", + * description="Retrieves a list of encounters for a single patient", + * tags={"standard"}, + * @OA\Parameter( + * name="puuid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:puuid/encounter" => function ($puuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "encounters", "auth_a"); + $return = (new EncounterRestController($request->getSession()))->getAll($puuid); + + return $return; + }, + + /** + * Schema for the encounter request + * + * @OA\Schema( + * schema="api_encounter_request", + * @OA\Property( + * property="date", + * description="The date of encounter.", + * type="string" + * ), + * @OA\Property( + * property="onset_date", + * description="The onset date of encounter.", + * type="string" + * ), + * @OA\Property( + * property="reason", + * description="The reason of encounter.", + * type="string" + * ), + * @OA\Property( + * property="facility", + * description="The facility of encounter.", + * type="string" + * ), + * @OA\Property( + * property="pc_catid", + * description="The pc_catid of encounter.", + * type="string" + * ), + * @OA\Property( + * property="facility_id", + * description="The facility id of encounter.", + * type="string" + * ), + * @OA\Property( + * property="billing_facility", + * description="The billing facility id of encounter.", + * type="string" + * ), + * @OA\Property( + * property="sensitivity", + * description="The sensitivity of encounter.", + * type="string" + * ), + * @OA\Property( + * property="referral_source", + * description="The referral source of encounter.", + * type="string" + * ), + * @OA\Property( + * property="pos_code", + * description="The pos_code of encounter.", + * type="string" + * ), + * @OA\Property( + * property="external_id", + * description="The external id of encounter.", + * type="string" + * ), + * @OA\Property( + * property="provider_id", + * description="The provider id of encounter.", + * type="string" + * ), + * @OA\Property( + * property="class_code", + * description="The class_code of encounter.", + * type="string" + * ), + * required={"pc_catid", "class_code"}, + * example={ + * "date":"2020-11-10", + * "onset_date": "", + * "reason": "Pregnancy Test", + * "facility": "Owerri General Hospital", + * "pc_catid": "5", + * "facility_id": "3", + * "billing_facility": "3", + * "sensitivity": "normal", + * "referral_source": "", + * "pos_code": "0", + * "external_id": "", + * "provider_id": "1", + * "class_code" : "AMB" + * } + * ) + */ + /** + * @OA\Post( + * path="/api/patient/{puuid}/encounter", + * description="Creates a new encounter", + * tags={"standard"}, + * @OA\Parameter( + * name="puuid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_encounter_request") + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="validationErrors", + * description="Validation errors.", + * type="array", + * @OA\Items( + * type="object", + * ), + * ), + * @OA\Property( + * property="internalErrors", + * description="Internal errors.", + * type="array", + * @OA\Items( + * type="object", + * ), + * ), + * @OA\Property( + * property="data", + * description="Returned data.", + * type="array", + * @OA\Items( + * @OA\Property( + * property="encounter", + * description="encounter id", + * type="integer", + * ), + * @OA\Property( + * property="uuid", + * description="encounter uuid", + * type="string", + * ) + * ), + * ), + * example={ + * "validationErrors": {}, + * "error_description": {}, + * "data": { + * "encounter": 1, + * "uuid": "90c196f2-51cc-4655-8858-3a80aebff3ef" + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "POST /api/patient/:puuid/encounter" => function ($puuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "encounters", "auth_a"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new EncounterRestController($request->getSession()))->post($puuid, $data, $request); + + return $return; + }, + + /** + * Schema for the encounter response + * + * @OA\Schema( + * schema="api_encounter_response", + * @OA\Property( + * property="validationErrors", + * description="Validation errors.", + * type="array", + * @OA\Items( + * type="object", + * ), + * ), + * @OA\Property( + * property="internalErrors", + * description="Internal errors.", + * type="array", + * @OA\Items( + * type="object", + * ), + * ), + * @OA\Property( + * property="data", + * description="Returned data.", + * type="array", + * @OA\Items( + * @OA\Property( + * property="id", + * description="encounter id", + * type="string", + * ), + * @OA\Property( + * property="uuid", + * description="encounter uuid", + * type="string", + * ), + * @OA\Property( + * property="date", + * description="encounter date", + * type="string", + * ), + * @OA\Property( + * property="reason", + * description="encounter reason", + * type="string", + * ), + * @OA\Property( + * property="facility", + * description="encounter facility name", + * type="string", + * ), + * @OA\Property( + * property="facility_id", + * description="encounter facility id name", + * type="string", + * ), + * @OA\Property( + * property="pid", + * description="encounter for patient pid", + * type="string", + * ), + * @OA\Property( + * property="onset_date", + * description="encounter onset date", + * type="string", + * ), + * @OA\Property( + * property="sensitivity", + * description="encounter sensitivity", + * type="string", + * ), + * @OA\Property( + * property="billing_note", + * description="encounter billing note", + * type="string", + * ), + * @OA\Property( + * property="pc_catid", + * description="encounter pc_catid", + * type="string", + * ), + * @OA\Property( + * property="last_level_billed", + * description="encounter last_level_billed", + * type="string", + * ), + * @OA\Property( + * property="last_level_closed", + * description="encounter last_level_closed", + * type="string", + * ), + * @OA\Property( + * property="last_stmt_date", + * description="encounter last_stmt_date", + * type="string", + * ), + * @OA\Property( + * property="stmt_count", + * description="encounter stmt_count", + * type="string", + * ), + * @OA\Property( + * property="provider_id", + * description="provider id", + * type="string", + * ), + * @OA\Property( + * property="supervisor_id", + * description="encounter supervisor id", + * type="string", + * ), + * @OA\Property( + * property="invoice_refno", + * description="encounter invoice_refno", + * type="string", + * ), + * @OA\Property( + * property="referral_source", + * description="encounter referral source", + * type="string", + * ), + * @OA\Property( + * property="billing_facility", + * description="encounter billing facility id", + * type="string", + * ), + * @OA\Property( + * property="external_id", + * description="encounter external id", + * type="string", + * ), + * @OA\Property( + * property="pos_code", + * description="encounter pos_code", + * type="string", + * ), + * @OA\Property( + * property="class_code", + * description="encounter class_code", + * type="string", + * ), + * @OA\Property( + * property="class_title", + * description="encounter class_title", + * type="string", + * ), + * @OA\Property( + * property="pc_catname", + * description="encounter pc_catname", + * type="string", + * ), + * @OA\Property( + * property="billing_facility_name", + * description="encounter billing facility name", + * type="string", + * ), + * ), + * ), + * example={ + * "validationErrors": {}, + * "error_description": {}, + * "data": { + * "id": "1", + * "uuid": "90c196f2-51cc-4655-8858-3a80aebff3ef", + * "date": "2019-09-14 00:00:00", + * "reason": "Pregnancy Test", + * "facility": "Owerri General Hospital", + * "facility_id": "3", + * "pid": "1", + * "onset_date": "2019-04-20 00:00:00", + * "sensitivity": "normal", + * "billing_note": null, + * "pc_catid": "5", + * "last_level_billed": "0", + * "last_level_closed": "0", + * "last_stmt_date": null, + * "stmt_count": "0", + * "provider_id": "1", + * "supervisor_id": "0", + * "invoice_refno": "", + * "referral_source": "", + * "billing_facility": "3", + * "external_id": "", + * "pos_code": "0", + * "class_code": "AMB", + * "class_title": "ambulatory", + * "pc_catname": "Office Visit", + * "billing_facility_name": "Owerri General Hospital" + * } + * } + * ) + */ + /** + * @OA\Put( + * path="/api/patient/{puuid}/encounter/{euuid}", + * description="Modify a encounter", + * tags={"standard"}, + * @OA\Parameter( + * name="puuid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="euuid", + * in="path", + * description="The uuid for the encounter.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_encounter_request") + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_encounter_response") + * ) + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "PUT /api/patient/:puuid/encounter/:euuid" => function ($puuid, $euuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "encounters", "auth_a"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new EncounterRestController($request->getSession()))->put($puuid, $euuid, $data); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{puuid}/encounter/{euuid}", + * description="Retrieves a single encounter for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="puuid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="euuid", + * in="path", + * description="The uuid for the encounter.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_encounter_response") + * ) + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:puuid/encounter/:euuid" => function ($puuid, $euuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "encounters", "auth_a"); + $return = (new EncounterRestController($request->getSession()))->getOne($puuid, $euuid); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{pid}/encounter/{eid}/soap_note", + * description="Retrieves soap notes from an encounter for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The pid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="eid", + * in="path", + * description="The id for the encounter.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:pid/encounter/:eid/soap_note" => function ($pid, $eid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "encounters", "notes"); + $return = (new EncounterRestController($request->getSession()))->getSoapNotes($pid, $eid); + + return $return; + }, + + /** + * Schema for the vital request + * + * @OA\Schema( + * schema="api_vital_request", + * @OA\Property( + * property="bps", + * description="The bps of vitals.", + * type="string" + * ), + * @OA\Property( + * property="bpd", + * description="The bpd of vitals.", + * type="string" + * ), + * @OA\Property( + * property="weight", + * description="The weight of vitals. (unit is lb)", + * type="string" + * ), + * @OA\Property( + * property="height", + * description="The height of vitals. (unit is inches)", + * type="string" + * ), + * @OA\Property( + * property="temperature", + * description="The temperature of temperature. (unit is F)", + * type="string" + * ), + * @OA\Property( + * property="temp_method", + * description="The temp_method of vitals.", + * type="string" + * ), + * @OA\Property( + * property="pulse", + * description="The pulse of vitals.", + * type="string" + * ), + * @OA\Property( + * property="respiration", + * description="The respiration of vitals.", + * type="string" + * ), + * @OA\Property( + * property="note", + * description="The note (ie. comments) of vitals.", + * type="string" + * ), + * @OA\Property( + * property="waist_circ", + * description="The waist circumference of vitals. (unit is inches)", + * type="string" + * ), + * @OA\Property( + * property="head_circ", + * description="The head circumference of vitals. (unit is inches)", + * type="string" + * ), + * @OA\Property( + * property="oxygen_saturation", + * description="The oxygen_saturation of vitals.", + * type="string" + * ), + * example={ + * "bps": "130", + * "bpd": "80", + * "weight": "220", + * "height": "70", + * "temperature": "98", + * "temp_method": "Oral", + * "pulse": "60", + * "respiration": "20", + * "note": "Patient with difficulty standing, which made weight measurement difficult.", + * "waist_circ": "37", + * "head_circ": "22.2", + * "oxygen_saturation": "96" + * } + * ) + */ + /** + * @OA\Post( + * path="/api/patient/{pid}/encounter/{eid}/vital", + * description="Submits a new vitals form", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The id for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="eid", + * in="path", + * description="The id for the encounter.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_vital_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "POST /api/patient/:pid/encounter/:eid/vital" => function ($pid, $eid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "encounters", "notes"); + $data = json_decode(file_get_contents("php://input"), true) ?? []; + $return = (new EncounterRestController($request->getSession()))->postVital($pid, $eid, $data); + + return $return; + }, + + /** + * @OA\Put( + * path="/api/patient/{pid}/encounter/{eid}/vital/{vid}", + * description="Edit a vitals form", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The id for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="eid", + * in="path", + * description="The id for the encounter.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="vid", + * in="path", + * description="The id for the vitalss form.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_vital_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "PUT /api/patient/:pid/encounter/:eid/vital/:vid" => function ($pid, $eid, $vid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "encounters", "notes"); + $data = json_decode(file_get_contents("php://input"), true) ?? []; + $return = (new EncounterRestController($request->getSession()))->putVital($pid, $eid, $vid, $data); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{pid}/encounter/{eid}/vital", + * description="Retrieves all vitals from an encounter for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The pid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="eid", + * in="path", + * description="The id for the encounter.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:pid/encounter/:eid/vital" => function ($pid, $eid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "encounters", "notes"); + $return = (new EncounterRestController($request->getSession()))->getVitals($pid, $eid); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{pid}/encounter/{eid}/vital/{vid}", + * description="Retrieves a vitals form from an encounter for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The pid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="eid", + * in="path", + * description="The id for the encounter.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="vid", + * in="path", + * description="The id for the vitals form.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:pid/encounter/:eid/vital/:vid" => function ($pid, $eid, $vid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "encounters", "notes"); + $return = (new EncounterRestController($request->getSession()))->getVital($pid, $eid, $vid); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{pid}/encounter/{eid}/soap_note/{sid}", + * description="Retrieves a soap note from an encounter for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The pid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="eid", + * in="path", + * description="The id for the encounter.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="sid", + * in="path", + * description="The id for the soap note.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:pid/encounter/:eid/soap_note/:sid" => function ($pid, $eid, $sid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "encounters", "notes"); + $return = (new EncounterRestController($request->getSession()))->getSoapNote($pid, $eid, $sid); + + return $return; + }, + + /** + * Schema for the soap_note request + * + * @OA\Schema( + * schema="api_soap_note_request", + * @OA\Property( + * property="subjective", + * description="The subjective of soap note.", + * type="string" + * ), + * @OA\Property( + * property="objective", + * description="The objective of soap note.", + * type="string" + * ), + * @OA\Property( + * property="assessment", + * description="The assessment of soap note.", + * type="string" + * ), + * @OA\Property( + * property="plan", + * description="The plan of soap note.", + * type="string" + * ), + * example={ + * "subjective": "The patient with mechanical fall and cut finger.", + * "objective": "The patient with finger laceration on exam.", + * "assessment": "The patient with finger laceration requiring sutures.", + * "plan": "Sutured finger laceration." + * } + * ) + */ + /** + * @OA\Post( + * path="/api/patient/{pid}/encounter/{eid}/soap_note", + * description="Submits a new soap note", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The id for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="eid", + * in="path", + * description="The id for the encounter.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_soap_note_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "POST /api/patient/:pid/encounter/:eid/soap_note" => function ($pid, $eid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "encounters", "notes"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new EncounterRestController($request->getSession()))->postSoapNote($pid, $eid, $data); + + return $return; + }, + + /** + * @OA\Put( + * path="/api/patient/{pid}/encounter/{eid}/soap_note/{sid}", + * description="Edit a soap note", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The id for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="eid", + * in="path", + * description="The id for the encounter.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="sid", + * in="path", + * description="The id for the soap noted.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_soap_note_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "PUT /api/patient/:pid/encounter/:eid/soap_note/:sid" => function ($pid, $eid, $sid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "encounters", "notes"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new EncounterRestController($request->getSession()))->putSoapNote($pid, $eid, $sid, $data); + + return $return; + }, + + + /** + * @OA\Get( + * path="/api/practitioner", + * description="Retrieves a list of practitioners", + * tags={"standard"}, + * @OA\Parameter( + * name="title", + * in="query", + * description="The title for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="fname", + * in="query", + * description="The first name for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="lname", + * in="query", + * description="The last name for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="mname", + * in="query", + * description="The middle name for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="federaltaxid", + * in="query", + * description="The federal tax id for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="federaldrugid", + * in="query", + * description="The federal drug id for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="upin", + * in="query", + * description="The upin for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="facility_id", + * in="query", + * description="The facility id for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="facility", + * in="query", + * description="The facility for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="npi", + * in="query", + * description="The npi for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="email", + * in="query", + * description="The email for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="specialty", + * in="query", + * description="The specialty for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="billname", + * in="query", + * description="The billname for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="url", + * in="query", + * description="The url for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="assistant", + * in="query", + * description="The assistant for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="organization", + * in="query", + * description="The organization for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="valedictory", + * in="query", + * description="The valedictory for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="street", + * in="query", + * description="The street for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="streetb", + * in="query", + * description="The street (line 2) for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="city", + * in="query", + * description="The city for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="state", + * in="query", + * description="The state for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="zip", + * in="query", + * description="The zip for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="phone", + * in="query", + * description="The phone for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="fax", + * in="query", + * description="The fax for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="phonew1", + * in="query", + * description="The phonew1 for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="phonecell", + * in="query", + * description="The phonecell for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="notes", + * in="query", + * description="The notes for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="state_license_number2", + * in="query", + * description="The state license number for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="username", + * in="query", + * description="The username for the practitioner.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/practitioner" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "admin", "users"); + $return = (new PractitionerRestController())->getAll($request, $request->query->all()); + return $return; + }, + + /** + * @OA\Get( + * path="/api/practitioner/{pruuid}", + * description="Retrieves a single practitioner by their uuid", + * tags={"standard"}, + * @OA\Parameter( + * name="pruuid", + * in="path", + * description="The uuid for the practitioner.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/practitioner/:pruuid" => function ($pruuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "admin", "users"); + $return = (new PractitionerRestController())->getOne($pruuid, $request); + return $return; + }, + + /** + * @OA\Post( + * path="/api/practitioner", + * description="Submits a new practitioner", + * tags={"standard"}, + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="title", + * description="The title for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="fname", + * description="The first name for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="mname", + * description="The middle name for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="lname", + * description="The last name for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="federaltaxid", + * description="The federal tax id for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="federaldrugid", + * description="The federal drug id for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="upin", + * description="The upin for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="facility_id", + * description="The facility_id for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="facility", + * description="The facility name for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="npi", + * description="The npi for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="email", + * description="The email for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="specialty", + * description="The specialty for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="billname", + * description="The billname for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="url", + * description="The url for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="assistant", + * description="The assistant for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="valedictory", + * description="The valedictory for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="street", + * description="The street address for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="streetb", + * description="The streetb address for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="city", + * description="The city for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="state", + * description="The state for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="zip", + * description="The zip for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="phone", + * description="The phone for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="fax", + * description="The fax for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="phonew1", + * description="The phonew1 for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="phonecell", + * description="The phonecell for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="notes", + * description="The notes for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="state_license_number", + * description="The state license number for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="username", + * description="The username for the practitioner.", + * type="string" + * ), + * required={"fname", "lname", "npi"}, + * example={ + * "title": "Mrs.", + * "fname": "Eduardo", + * "mname": "Kathy", + * "lname": "Perez", + * "federaltaxid": "", + * "federaldrugid": "", + * "upin": "", + * "facility_id": "3", + * "facility": "Your Clinic Name Here", + * "npi": "12345678901", + * "email": "info@pennfirm.com", + * "specialty": "", + * "billname": null, + * "url": null, + * "assistant": null, + * "organization": null, + * "valedictory": null, + * "street": "789 Third Avenue", + * "streetb": "123 Cannaut Street", + * "city": "San Diego", + * "state": "CA", + * "zip": "90210", + * "phone": "(619) 555-9827", + * "fax": null, + * "phonew1": "(619) 555-7822", + * "phonecell": "(619) 555-7821", + * "notes": null, + * "state_license_number": "123456", + * "username": "eduardoperez" + * } + * ) + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="validationErrors", + * description="Validation errors.", + * type="array", + * @OA\Items( + * type="object", + * ), + * ), + * @OA\Property( + * property="internalErrors", + * description="Internal errors.", + * type="array", + * @OA\Items( + * type="object", + * ), + * ), + * @OA\Property( + * property="data", + * description="Returned data.", + * type="array", + * @OA\Items( + * @OA\Property( + * property="id", + * description="practitioner id", + * type="integer", + * ), + * @OA\Property( + * property="uuid", + * description="practitioner uuid", + * type="string", + * ), + * ), + * ), + * example={ + * "validationErrors": {}, + * "error_description": {}, + * "data": { + * "id": 7, + * "uuid": "90d453fb-0248-4c0d-9575-d99d02b169f5" + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "POST /api/practitioner" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "admin", "users"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new PractitionerRestController())->post($data, $request); + return $return; + }, + + /** + * @OA\Put( + * path="/api/practitioner/{pruuid}", + * description="Edit a practitioner", + * tags={"standard"}, + * @OA\Parameter( + * name="pruuid", + * in="path", + * description="The uuid for the practitioner.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="title", + * description="The title for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="fname", + * description="The first name for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="mname", + * description="The middle name for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="lname", + * description="The last name for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="federaltaxid", + * description="The federal tax id for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="federaldrugid", + * description="The federal drug id for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="upin", + * description="The upin for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="facility_id", + * description="The facility_id for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="facility", + * description="The facility name for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="npi", + * description="The npi for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="email", + * description="The email for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="specialty", + * description="The specialty for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="billname", + * description="The billname for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="url", + * description="The url for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="assistant", + * description="The assistant for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="valedictory", + * description="The valedictory for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="street", + * description="The street address for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="streetb", + * description="The streetb address for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="city", + * description="The city for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="state", + * description="The state for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="zip", + * description="The zip for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="phone", + * description="The phone for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="fax", + * description="The fax for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="phonew1", + * description="The phonew1 for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="phonecell", + * description="The phonecell for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="notes", + * description="The notes for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="state_license_number", + * description="The state license number for the practitioner.", + * type="string" + * ), + * @OA\Property( + * property="username", + * description="The username for the practitioner.", + * type="string" + * ), + * example={ + * "title": "Mr", + * "fname": "Baz", + * "mname": "", + * "lname": "Bop", + * "street": "456 Tree Lane", + * "zip": "08642", + * "city": "FooTown", + * "state": "FL", + * "phone": "123-456-7890" + * } + * ) + * ) + * ), + * @OA\Response( + * response="200", + * description="Standard response", + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="validationErrors", + * description="Validation errors.", + * type="array", + * @OA\Items( + * type="object", + * ), + * ), + * @OA\Property( + * property="internalErrors", + * description="Internal errors.", + * type="array", + * @OA\Items( + * type="object", + * ), + * ), + * @OA\Property( + * property="data", + * description="Returned data.", + * type="array", + * @OA\Items( + * @OA\Property( + * property="id", + * description="practitioner id", + * type="string", + * ), + * @OA\Property( + * property="uuid", + * description="practitioner uuid", + * type="string", + * ), + * @OA\Property( + * property="title", + * description="practitioner title", + * type="string", + * ), + * @OA\Property( + * property="fname", + * description="practitioner fname", + * type="string", + * ), + * @OA\Property( + * property="lname", + * description="practitioner lname", + * type="string", + * ), + * @OA\Property( + * property="mname", + * description="practitioner mname", + * type="string", + * ), + * @OA\Property( + * property="federaltaxid", + * description="practitioner federaltaxid", + * type="string", + * ), + * @OA\Property( + * property="federaldrugid", + * description="practitioner federaldrugid", + * type="string", + * ), + * @OA\Property( + * property="upin", + * description="practitioner upin", + * type="string", + * ), + * @OA\Property( + * property="facility_id", + * description="practitioner facility_id", + * type="string", + * ), + * @OA\Property( + * property="facility", + * description="practitioner facility", + * type="string", + * ), + * @OA\Property( + * property="npi", + * description="practitioner npi", + * type="string", + * ), + * @OA\Property( + * property="email", + * description="practitioner email", + * type="string", + * ), + * @OA\Property( + * property="active", + * description="practitioner active setting", + * type="string", + * ), + * @OA\Property( + * property="specialty", + * description="practitioner specialty", + * type="string", + * ), + * @OA\Property( + * property="billname", + * description="practitioner billname", + * type="string", + * ), + * @OA\Property( + * property="url", + * description="practitioner url", + * type="string", + * ), + * @OA\Property( + * property="assistant", + * description="practitioner assistant", + * type="string", + * ), + * @OA\Property( + * property="organization", + * description="practitioner organization", + * type="string", + * ), + * @OA\Property( + * property="valedictory", + * description="practitioner valedictory", + * type="string", + * ), + * @OA\Property( + * property="street", + * description="practitioner street", + * type="string", + * ), + * @OA\Property( + * property="streetb", + * description="practitioner streetb", + * type="string", + * ), + * @OA\Property( + * property="city", + * description="practitioner city", + * type="string", + * ), + * @OA\Property( + * property="state", + * description="practitioner state", + * type="string", + * ), + * @OA\Property( + * property="zip", + * description="practitioner zip", + * type="string", + * ), + * @OA\Property( + * property="phone", + * description="practitioner phone", + * type="string", + * ), + * @OA\Property( + * property="fax", + * description="fax", + * type="string", + * ), + * @OA\Property( + * property="phonew1", + * description="practitioner phonew1", + * type="string", + * ), + * @OA\Property( + * property="phonecell", + * description="practitioner phonecell", + * type="string", + * ), + * @OA\Property( + * property="notes", + * description="practitioner notes", + * type="string", + * ), + * @OA\Property( + * property="state_license_number", + * description="practitioner state license number", + * type="string", + * ), + * @OA\Property( + * property="abook_title", + * description="practitioner abook title", + * type="string", + * ), + * @OA\Property( + * property="physician_title", + * description="practitioner physician title", + * type="string", + * ), + * @OA\Property( + * property="physician_code", + * description="practitioner physician code", + * type="string", + * ) + * ), + * ), + * example={ + * "validationErrors": {}, + * "error_description": {}, + * "data": { + * "id": 7, + * "uuid": "90d453fb-0248-4c0d-9575-d99d02b169f5", + * "title": "Mr", + * "fname": "Baz", + * "lname": "Bop", + * "mname": "", + * "federaltaxid": "", + * "federaldrugid": "", + * "upin": "", + * "facility_id": "3", + * "facility": "Your Clinic Name Here", + * "npi": "0123456789", + * "email": "info@pennfirm.com", + * "active": "1", + * "specialty": "", + * "billname": "", + * "url": "", + * "assistant": "", + * "organization": "", + * "valedictory": "", + * "street": "456 Tree Lane", + * "streetb": "123 Cannaut Street", + * "city": "FooTown", + * "state": "FL", + * "zip": "08642", + * "phone": "123-456-7890", + * "fax": "", + * "phonew1": "(619) 555-7822", + * "phonecell": "(619) 555-7821", + * "notes": "", + * "state_license_number": "123456", + * "abook_title": null, + * "physician_title": null, + * "physician_code": null + * } + * } + * ) + * ) + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "PUT /api/practitioner/:pruuid" => function ($pruuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "admin", "users"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new PractitionerRestController())->patch($pruuid, $data, $request); + return $return; + }, + + /** + * @OA\Get( + * path="/api/medical_problem", + * description="Retrieves a list of medical problems", + * tags={"standard"}, + * @OA\Parameter( + * name="puuid", + * in="query", + * description="The uuid for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="condition_uuid", + * in="query", + * description="The uuid for the medical problem.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="title", + * in="query", + * description="The title for the medical problem.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="begdate", + * in="query", + * description="The start date for the medical problem.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="enddate", + * in="query", + * description="The end date for the medical problem.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="diagnosis", + * in="query", + * description="The diagnosis for the medical problem.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/medical_problem" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "encounters", "notes"); + $return = (new ConditionRestController())->getAll(); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/medical_problem/{muuid}", + * description="Retrieves a single medical problem by their uuid", + * tags={"standard"}, + * @OA\Parameter( + * name="muuid", + * in="path", + * description="The uuid for the medical problem.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/medical_problem/:muuid" => function ($muuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "encounters", "notes"); + $return = (new ConditionRestController())->getOne($muuid); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{puuid}/medical_problem", + * description="Retrieves all medical problems for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="puuid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:puuid/medical_problem" => function ($puuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "encounters", "notes"); + $return = (new ConditionRestController())->getAll(['puuid' => $puuid]); + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{puuid}/medical_problem/{muuid}", + * description="Retrieves a medical problem for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="puuid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="muuid", + * in="path", + * description="The uuid for the medical problem.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:puuid/medical_problem/:muuid" => function ($puuid, $muuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new ConditionRestController())->getAll(['puuid' => $puuid, 'condition_uuid' => $muuid]); + + return $return; + }, + + /** + * Schema for the medical_problem request + * + * @OA\Schema( + * schema="api_medical_problem_request", + * @OA\Property( + * property="title", + * description="The title of medical problem.", + * type="string" + * ), + * @OA\Property( + * property="begdate", + * description="The beginning date of medical problem.", + * type="string" + * ), + * @OA\Property( + * property="enddate", + * description="The end date of medical problem.", + * type="string" + * ), + * @OA\Property( + * property="diagnosis", + * description="The diagnosis of medical problem. In format `:`", + * type="string" + * ), + * required={"title", "begdate"}, + * example={ + * "title": "Dermatochalasis", + * "begdate": "2010-10-13", + * "enddate": null, + * "diagnosis": "ICD10:H02.839" + * } + * ) + */ + /** + * @OA\Post( + * path="/api/patient/{puuid}/medical_problem", + * description="Submits a new medical problem", + * tags={"standard"}, + * @OA\Parameter( + * name="puuid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_medical_problem_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "POST /api/patient/:puuid/medical_problem" => function ($puuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new ConditionRestController())->post($puuid, $data); + + return $return; + }, + + /** + * @OA\Put( + * path="/api/patient/{puuid}/medical_problem/{muuid}", + * description="Edit a medical problem", + * tags={"standard"}, + * @OA\Parameter( + * name="puuid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="muuid", + * in="path", + * description="The uuid for the medical problem.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_medical_problem_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "PUT /api/patient/:puuid/medical_problem/:muuid" => function ($puuid, $muuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new ConditionRestController())->put($puuid, $muuid, $data); + + return $return; + }, + + /** + * @OA\Delete( + * path="/api/patient/{puuid}/medical_problem/{muuid}", + * description="Delete a medical problem", + * tags={"standard"}, + * @OA\Parameter( + * name="puuid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="muuid", + * in="path", + * description="The uuid for the medical problem.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "DELETE /api/patient/:puuid/medical_problem/:muuid" => function ($puuid, $muuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new ConditionRestController())->delete($puuid, $muuid); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/allergy", + * description="Retrieves a list of allergies", + * tags={"standard"}, + * @OA\Parameter( + * name="lists.pid", + * in="query", + * description="The uuid for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="lists.id", + * in="query", + * description="The uuid for the allergy.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="title", + * in="query", + * description="The title for the allergy.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="begdate", + * in="query", + * description="The start date for the allergy.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="enddate", + * in="query", + * description="The end date for the allergy.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="diagnosis", + * in="query", + * description="The diagnosis for the allergy.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/allergy" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new AllergyIntoleranceRestController())->getAll(); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/allergy/{auuid}", + * description="Retrieves a single allergy by their uuid", + * tags={"standard"}, + * @OA\Parameter( + * name="auuid", + * in="path", + * description="The uuid for the allergy.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/allergy/:auuid" => function ($auuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new AllergyIntoleranceRestController())->getOne($auuid); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{puuid}/allergy", + * description="Retrieves all allergies for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="puuid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:puuid/allergy" => function ($puuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new AllergyIntoleranceRestController())->getAll(['lists.pid' => $puuid]); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{puuid}/allergy/{auuid}", + * description="Retrieves a allergy for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="puuid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="auuid", + * in="path", + * description="The uuid for the allergy.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:puuid/allergy/:auuid" => function ($puuid, $auuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new AllergyIntoleranceRestController())->getAll(['lists.pid' => $puuid, 'lists.id' => $auuid]); + + return $return; + }, + + /** + * Schema for the allergy request + * + * @OA\Schema( + * schema="api_allergy_request", + * @OA\Property( + * property="title", + * description="The title of allergy.", + * type="string" + * ), + * @OA\Property( + * property="begdate", + * description="The beginning date of allergy.", + * type="string" + * ), + * @OA\Property( + * property="enddate", + * description="The end date of allergy.", + * type="string" + * ), + * @OA\Property( + * property="diagnosis", + * description="The diagnosis of allergy. In format `:`", + * type="string" + * ), + * required={"title", "begdate"}, + * example={ + * "title": "Iodine", + * "begdate": "2010-10-13", + * "enddate": null + * } + * ) + */ + /** + * @OA\Post( + * path="/api/patient/{puuid}/allergy", + * description="Submits a new allergy", + * tags={"standard"}, + * @OA\Parameter( + * name="puuid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_allergy_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "POST /api/patient/:puuid/allergy" => function ($puuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new AllergyIntoleranceRestController())->post($puuid, $data); + + return $return; + }, + + /** + * @OA\Put( + * path="/api/patient/{puuid}/allergy/{auuid}", + * description="Edit a allergy", + * tags={"standard"}, + * @OA\Parameter( + * name="puuid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="auuid", + * in="path", + * description="The uuid for the allergy.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_allergy_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "PUT /api/patient/:puuid/allergy/:auuid" => function ($puuid, $auuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new AllergyIntoleranceRestController())->put($puuid, $auuid, $data); + + return $return; + }, + + /** + * @OA\Delete( + * path="/api/patient/{puuid}/allergy/{auuid}", + * description="Delete a medical problem", + * tags={"standard"}, + * @OA\Parameter( + * name="puuid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="auuid", + * in="path", + * description="The uuid for the allergy.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "DELETE /api/patient/:puuid/allergy/:auuid" => function ($puuid, $auuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new AllergyIntoleranceRestController())->delete($puuid, $auuid); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{pid}/medication", + * description="Retrieves all medications for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The pid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:pid/medication" => function ($pid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new ListRestController())->getAll($pid, "medication"); + + return $return; + }, + + /** + * Schema for the medication request + * + * @OA\Schema( + * schema="api_medication_request", + * @OA\Property( + * property="title", + * description="The title of medication.", + * type="string" + * ), + * @OA\Property( + * property="begdate", + * description="The beginning date of medication.", + * type="string" + * ), + * @OA\Property( + * property="enddate", + * description="The end date of medication.", + * type="string" + * ), + * @OA\Property( + * property="diagnosis", + * description="The diagnosis of medication. In format `:`", + * type="string" + * ), + * required={"title", "begdate"}, + * example={ + * "title": "Norvasc", + * "begdate": "2013-04-13", + * "enddate": null + * } + * ) + */ + /** + * @OA\Post( + * path="/api/patient/{pid}/medication", + * description="Submits a new medication", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The pid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_medication_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "POST /api/patient/:pid/medication" => function ($pid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new ListRestController())->post($pid, "medication", $data); + + return $return; + }, + + /** + * @OA\Put( + * path="/api/patient/{pid}/medication/{mid}", + * description="Edit a medication", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The pid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="mid", + * in="path", + * description="The id for the medication.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_medication_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "PUT /api/patient/:pid/medication/:mid" => function ($pid, $mid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new ListRestController())->put($pid, $mid, "medication", $data); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{pid}/medication/{mid}", + * description="Retrieves a medication for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The id for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="mid", + * in="path", + * description="The id for the medication.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:pid/medication/:mid" => function ($pid, $mid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new ListRestController())->getOne($pid, "medication", $mid); + + return $return; + }, + + /** + * @OA\Delete( + * path="/api/patient/{pid}/medication/{mid}", + * description="Delete a medication", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The id for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="mid", + * in="path", + * description="The id for the medication.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "DELETE /api/patient/:pid/medication/:mid" => function ($pid, $mid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new ListRestController())->delete($pid, $mid, "medication"); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{pid}/surgery", + * description="Retrieves all surgeries for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The pid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:pid/surgery" => function ($pid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new ListRestController())->getAll($pid, "surgery"); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{pid}/surgery/{sid}", + * description="Retrieves a surgery for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The id for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="sid", + * in="path", + * description="The id for the surgery.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:pid/surgery/:sid" => function ($pid, $sid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new ListRestController())->getOne($pid, "surgery", $sid); + + return $return; + }, + + /** + * @OA\Delete( + * path="/api/patient/{pid}/surgery/{sid}", + * description="Delete a surgery", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The id for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="sid", + * in="path", + * description="The id for the surgery.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "DELETE /api/patient/:pid/surgery/:sid" => function ($pid, $sid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new ListRestController())->delete($pid, $sid, "surgery"); + + return $return; + }, + + /** + * Schema for the surgery request + * + * @OA\Schema( + * schema="api_surgery_request", + * @OA\Property( + * property="title", + * description="The title of surgery.", + * type="string" + * ), + * @OA\Property( + * property="begdate", + * description="The beginning date of surgery.", + * type="string" + * ), + * @OA\Property( + * property="enddate", + * description="The end date of surgery.", + * type="string" + * ), + * @OA\Property( + * property="diagnosis", + * description="The diagnosis of surgery. In format `:`", + * type="string" + * ), + * required={"title", "begdate"}, + * example={ + * "title": "Blepharoplasty", + * "begdate": "2013-10-14", + * "enddate": null, + * "diagnosis": "CPT4:15823-50" + * } + * ) + */ + /** + * @OA\Post( + * path="/api/patient/{pid}/surgery", + * description="Submits a new surgery", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The pid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_surgery_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "POST /api/patient/:pid/surgery" => function ($pid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new ListRestController())->post($pid, "surgery", $data); + + return $return; + }, + + /** + * @OA\Put( + * path="/api/patient/{pid}/surgery/{sid}", + * description="Edit a surgery", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The pid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="sid", + * in="path", + * description="The id for the surgery.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_surgery_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "PUT /api/patient/:pid/surgery/:sid" => function ($pid, $sid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new ListRestController())->put($pid, $sid, "surgery", $data); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{pid}/dental_issue", + * description="Retrieves all dental issues for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The pid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:pid/dental_issue" => function ($pid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new ListRestController())->getAll($pid, "dental"); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{pid}/dental_issue/{did}", + * description="Retrieves a dental issue for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The id for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="did", + * in="path", + * description="The id for the dental issue.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:pid/dental_issue/:did" => function ($pid, $did, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new ListRestController())->getOne($pid, "dental", $did); + + return $return; + }, + + /** + * @OA\Delete( + * path="/api/patient/{pid}/dental_issue/{did}", + * description="Delete a dental issue", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The id for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="did", + * in="path", + * description="The id for the dental issue.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "DELETE /api/patient/:pid/dental_issue/:did" => function ($pid, $did, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new ListRestController())->delete($pid, $did, "dental"); + + return $return; + }, + + /** + * Schema for the dental_issue request + * + * @OA\Schema( + * schema="api_dental_issue_request", + * @OA\Property( + * property="title", + * description="The title of dental issue.", + * type="string" + * ), + * @OA\Property( + * property="begdate", + * description="The beginning date of dental issue.", + * type="string" + * ), + * @OA\Property( + * property="enddate", + * description="The end date of dental issue.", + * type="string" + * ), + * @OA\Property( + * property="diagnosis", + * description="The diagnosis of dental issue. In format `:`", + * type="string" + * ), + * required={"title", "begdate"}, + * example={ + * "title": "Halitosis", + * "begdate": "2015-03-17", + * "enddate": null, + * } + * ) + */ + /** + * @OA\Post( + * path="/api/patient/{pid}/dental_issue", + * description="Submits a new dental issue", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The pid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_dental_issue_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "POST /api/patient/:pid/dental_issue" => function ($pid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new ListRestController())->post($pid, "dental", $data); + + return $return; + }, + + /** + * @OA\Put( + * path="/api/patient/{pid}/dental_issue/{did}", + * description="Edit a dental issue", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The pid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="did", + * in="path", + * description="The id for the dental issue.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_dental_issue_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "PUT /api/patient/:pid/dental_issue/:did" => function ($pid, $did, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new ListRestController())->put($pid, $did, "dental", $data); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{pid}/appointment", + * description="Retrieves all appointments for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The pid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:pid/appointment" => function ($pid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "appt"); + $return = (new AppointmentRestController())->getAllForPatient($pid); + + return $return; + }, + + /** + * @OA\Post( + * path="/api/patient/{pid}/appointment", + * description="Submits a new appointment", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The id for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * @OA\Property( + * property="pc_catid", + * description="The category of the appointment.", + * type="string" + * ), + * @OA\Property( + * property="pc_title", + * description="The title of the appointment.", + * type="string" + * ), + * @OA\Property( + * property="pc_duration", + * description="The duration of the appointment.", + * type="string" + * ), + * @OA\Property( + * property="pc_hometext", + * description="Comments for the appointment.", + * type="string" + * ), + * @OA\Property( + * property="pc_apptstatus", + * description="use an option from resource=/api/list/apptstat", + * type="string" + * ), + * @OA\Property( + * property="pc_eventDate", + * description="The date of the appointment.", + * type="string" + * ), + * @OA\Property( + * property="pc_startTime", + * description="The time of the appointment.", + * type="string" + * ), + * @OA\Property( + * property="pc_facility", + * description="The facility id of the appointment.", + * type="string" + * ), + * @OA\Property( + * property="pc_billing_location", + * description="The billinag location id of the appointment.", + * type="string" + * ), + * @OA\Property( + * property="pc_aid", + * description="The provider id for the appointment.", + * type="string" + * ), + * required={"pc_catid", "pc_title", "pc_duration", "pc_hometext", "pc_apptstatus", "pc_eventDate", "pc_startTime", "pc_facility", "pc_billing_location"}, + * example={ + * "pc_catid": "5", + * "pc_title": "Office Visit", + * "pc_duration": "900", + * "pc_hometext": "Test", + * "pc_apptstatus": "-", + * "pc_eventDate": "2018-10-19", + * "pc_startTime": "09:00", + * "pc_facility": "9", + * "pc_billing_location": "10", + * "pc_aid": "1" + * } + * ) + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "POST /api/patient/:pid/appointment" => function ($pid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "appt"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new AppointmentRestController())->post($pid, $data); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/appointment", + * description="Retrieves all appointments", + * tags={"standard"}, + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/appointment" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "appt"); + $return = (new AppointmentRestController())->getAll(); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/appointment/{eid}", + * description="Retrieves an appointment", + * tags={"standard"}, + * @OA\Parameter( + * name="eid", + * in="path", + * description="The eid for the appointment.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/appointment/:eid" => function ($eid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "appt"); + $return = (new AppointmentRestController())->getOne($eid); + + return $return; + }, + + /** + * @OA\Delete( + * path="/api/patient/{pid}/appointment/{eid}", + * description="Delete a appointment", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The id for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="eid", + * in="path", + * description="The eid for the appointment.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "DELETE /api/patient/:pid/appointment/:eid" => function ($pid, $eid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "appt"); + $return = (new AppointmentRestController())->delete($eid); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{pid}/appointment/{eid}", + * description="Retrieves a appointment for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The id for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="eid", + * in="path", + * description="The eid for the appointment.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:pid/appointment/:eid" => function ($pid, $eid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "appt"); + $return = (new AppointmentRestController())->getOne($eid); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/list/{list_name}", + * description="Retrieves a list", + * tags={"standard"}, + * @OA\Parameter( + * name="list_name", + * in="path", + * description="The list_id of the list.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/list/:list_name" => function ($list_name, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "lists", "default"); + $return = (new ListRestController())->getOptions($list_name); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/user", + * description="Retrieves a list of users", + * tags={"standard"}, + * @OA\Parameter( + * name="id", + * in="query", + * description="The id for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="title", + * in="query", + * description="The title for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="fname", + * in="query", + * description="The first name for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="lname", + * in="query", + * description="The last name for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="mname", + * in="query", + * description="The middle name for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="federaltaxid", + * in="query", + * description="The federal tax id for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="federaldrugid", + * in="query", + * description="The federal drug id for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="upin", + * in="query", + * description="The upin for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="facility_id", + * in="query", + * description="The facility id for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="facility", + * in="query", + * description="The facility for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="npi", + * in="query", + * description="The npi for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="email", + * in="query", + * description="The email for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="specialty", + * in="query", + * description="The specialty for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="billname", + * in="query", + * description="The billname for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="url", + * in="query", + * description="The url for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="assistant", + * in="query", + * description="The assistant for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="organization", + * in="query", + * description="The organization for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="valedictory", + * in="query", + * description="The valedictory for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="street", + * in="query", + * description="The street for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="streetb", + * in="query", + * description="The street (line 2) for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="city", + * in="query", + * description="The city for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="state", + * in="query", + * description="The state for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="zip", + * in="query", + * description="The zip for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="phone", + * in="query", + * description="The phone for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="fax", + * in="query", + * description="The fax for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="phonew1", + * in="query", + * description="The phonew1 for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="phonecell", + * in="query", + * description="The phonecell for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="notes", + * in="query", + * description="The notes for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="state_license_number2", + * in="query", + * description="The state license number for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="username", + * in="query", + * description="The username for the user.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/user" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "admin", "users"); + $return = (new UserRestController())->getAll($_GET); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/user/{uuid}", + * description="Retrieves a single user by their uuid", + * tags={"standard"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the user.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/user/:uuid" => function ($uuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "admin", "users"); + $return = (new UserRestController())->getOne($uuid); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/version", + * description="Retrieves the OpenEMR version information", + * tags={"standard"}, + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/version" => function (HttpRestRequest $request) { + $return = (new VersionRestController())->getOne(); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/product", + * description="Retrieves the OpenEMR product registration information", + * tags={"standard"}, + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/product" => function (HttpRestRequest $request) { + $return = (new ProductRegistrationRestController())->getOne(); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/insurance_company", + * description="Retrieves all insurance companies", + * tags={"standard"}, + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/insurance_company" => function (HttpRestRequest $request) { + $return = (new InsuranceCompanyRestController())->getAll(); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/insurance_company/{iid}", + * description="Retrieves insurance company", + * tags={"standard"}, + * @OA\Parameter( + * name="iid", + * in="path", + * description="The id of the insurance company.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/insurance_company/:iid" => function ($iid, HttpRestRequest $request) { + $return = (new InsuranceCompanyRestController())->getOne($iid); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/insurance_type", + * description="Retrieves all insurance types", + * tags={"standard"}, + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/insurance_type" => function (HttpRestRequest $request) { + $return = (new InsuranceCompanyRestController())->getInsuranceTypes(); + + return $return; + }, + + /** + * Schema for the insurance_company request + * + * @OA\Schema( + * schema="api_insurance_company_request", + * @OA\Property( + * property="name", + * description="The name of insurance company.", + * type="string" + * ), + * @OA\Property( + * property="attn", + * description="The attn of insurance company.", + * type="string" + * ), + * @OA\Property( + * property="cms_id", + * description="The cms id of insurance company.", + * type="string" + * ), + * @OA\Property( + * property="ins_type_code", + * description="The insurance type code of insurance company. The insurance type code can be found by inspecting the route at (/api/insurance_type).", + * type="string" + * ), + * @OA\Property( + * property="x12_receiver_id", + * description="The x12 receiver id of insurance company.", + * type="string" + * ), + * @OA\Property( + * property="x12_default_partner_id", + * description="The x12 default partner id of insurance company.", + * type="string" + * ), + * @OA\Property( + * property="alt_cms_id", + * description="The alternate cms id of insurance company.", + * type="string" + * ), + * @OA\Property( + * property="line1", + * description="The line1 address of insurance company.", + * type="string" + * ), + * @OA\Property( + * property="line2", + * description="The line2 address of insurance company.", + * type="string" + * ), + * @OA\Property( + * property="city", + * description="The city of insurance company.", + * type="string" + * ), + * @OA\Property( + * property="state", + * description="The state of insurance company.", + * type="string" + * ), + * @OA\Property( + * property="zip", + * description="The zip of insurance company.", + * type="string" + * ), + * @OA\Property( + * property="country", + * description="The country of insurance company.", + * type="string" + * ), + * required={"name"}, + * example={ + * "name": "Cool Insurance Company", + * "attn": null, + * "cms_id": null, + * "ins_type_code": "2", + * "x12_receiver_id": null, + * "x12_default_partner_id": null, + * "alt_cms_id": "", + * "line1": "123 Cool Lane", + * "line2": "Suite 123", + * "city": "Cooltown", + * "state": "CA", + * "zip": "12245", + * "country": "USA" + * } + * ) + */ + /** + * @OA\Post( + * path="/api/insurance_company", + * description="Submits a new insurance company", + * tags={"standard"}, + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_insurance_company_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "POST /api/insurance_company" => function (HttpRestRequest $request) { + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new InsuranceCompanyRestController())->post($data); + + return $return; + }, + + /** + * @OA\Put( + * path="/api/insurance_company/{iid}", + * description="Edit a insurance company", + * tags={"standard"}, + * @OA\Parameter( + * name="iid", + * in="path", + * description="The id for the insurance company.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_insurance_company_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "PUT /api/insurance_company/:iid" => function ($iid, HttpRestRequest $request) { + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new InsuranceCompanyRestController())->put($iid, $data); + + return $return; + }, + + /** + * @OA\Post( + * path="/api/patient/{pid}/document", + * description="Submits a new patient document", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The pid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="path", + * in="query", + * description="The category of the document.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="multipart/form-data", + * @OA\Schema( + * @OA\Property( + * property="document", + * description="document", + * type="string", + * format="binary" + * ), + * ), + * ), + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "POST /api/patient/:pid/document" => function ($pid, HttpRestRequest $request) { + $return = (new DocumentRestController())->postWithPath($pid, $_GET['path'], $_FILES['document']); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{pid}/document", + * description="Retrieves all file information of documents from a category for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The pid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="path", + * in="query", + * description="The category of the documents.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:pid/document" => function ($pid, HttpRestRequest $request) { + $return = (new DocumentRestController())->getAllAtPath($pid, $_GET['path']); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{pid}/document/{did}", + * description="Retrieves a document for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The pid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="did", + * in="path", + * description="The id for the patient document.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:pid/document/:did" => function ($pid, $did, HttpRestRequest $request) { + $return = (new DocumentRestController())->downloadFile($pid, $did); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{puuid}/employer", + * description="Retrieves all the employer data for a patient. Returns an array of the employer data for the patient.", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{"user/employer.read", "patient/employer.read"}}} + * ) + */ + "GET /api/patient/:puuid/employer" => function ($puuid, HttpRestRequest $request) { + if (!UuidRegistry::isValidStringUUID($puuid)) { + $errorReturn = [ + 'validationErrors' => [ 'uuid' => ['Invalid UUID format']] + ]; + return RestControllerHelper::responseHandler($errorReturn, null, 400); + } + + $searchParams = $request->getQueryParams(); + if ($request->isPatientRequest()) { + // For patient portal users, force the UUID to match the authenticated patient. + $searchParams['puuid'] = $request->getPatientUUIDString(); + } else { + // For staff users, verify they have permission to view demographic data. + RestConfig::request_authorization_check($request, "patients", "demo"); + $searchParams['puuid'] = $puuid; + } + + // Try to get the data. The service layer will handle non-existent UUIDs. + $return = (new EmployerRestController())->getAll($searchParams); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{puuid}/insurance", + * description="Retrieves all insurances for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:puuid/insurance" => function ($puuid, HttpRestRequest $request) { + $searchParams = $request->getQueryParams(); + $searchParams['puuid'] = $puuid; + if ($request->isPatientRequest()) { + $searchParams['puuid'] = $request->getPatientUUIDString(); + } + $return = (new InsuranceRestController())->getAll($searchParams); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{puuid}/insurance/$swap-insurance", + * description="Updates the insurance for the passed in uuid to be a policy of type `type` and updates (if one exists) the current or most recent insurance for the passed in `type` for a patient to be the `type` of the insurance for the given `uuid`. Validations on the swap operation are performed to make sure the effective `date` of the src and target policies being swapped can be received in each given policy `type` as a policy `type` and `date` must together be unique per patient.", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="type", + * in="query", + * description="The type or category of OpenEMR insurance policy, 'primary', 'secondary', or 'tertiary'.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="uuid", + * in="query", + * description="The insurance uuid that will be swapped into the list of insurances for the type query parameter", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + 'GET /api/patient/:puuid/insurance/$swap-insurance' => function ($puuid, HttpRestRequest $request) { + if ($request->isPatientRequest()) { + $puuid = $request->getPatientUUIDString(); + } + $type = $request->getQueryParam('type'); + $insuranceUuid = $request->getQueryParam('uuid'); + + $return = (new InsuranceRestController())->operationSwapInsurance($puuid, $type, $insuranceUuid); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{puuid}/insurance/{uuid}", + * description="Retrieves all insurances for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/patient/:puuid/insurance/:uuid" => function ($puuid, $uuid, HttpRestRequest $request) { + if ($request->isPatientRequest()) { + $puuid = $request->getPatientUUIDString(); + } + $return = (new InsuranceRestController())->getOne($uuid, $puuid); + + return $return; + }, + + /** + * Schema for the insurance request. Note the following additional validation checks on the request. + * If the subscriber_relationship value is of type 'self' then the subscriber_fname and subscriber_lname fields + * must match the patient's first and last name or a patient's previous first and last name. + * + * If the subscriber_relationship value is of type 'self' then the subscriber_ss field must match the patient's + * social security number. + * + * If the subscriber_relationship value is not of type 'self' then the subscriber_ss field MUST not be the current patient's social security number. + * + * If the system's global configuration permits only a single insurance type option then any insurance rquest where the type is NOT 'primary' will fail. + * + * An insurance is considered the current policy for the policy type if the policy date_end field is null. Only one of these records per policy type can exist for a patient. + * @OA\Schema( + * schema="api_insurance_request", + * @OA\Property( + * property="provider", + * description="The insurance company id.", + * type="string" + * ), + * @OA\Property( + * property="plan_name", + * description="The plan name of insurance. (2-255 characters)", + * type="string" + * ), + * @OA\Property( + * property="policy_number", + * description="The policy number of insurance. (2-255 characters)", + * type="string" + * ), + * @OA\Property( + * property="group_number", + * description="The group number of insurance.(2-255 characters)", + * type="string" + * ), + * @OA\Property( + * property="subscriber_lname", + * description="The subscriber last name of insurance.(2-255 characters).", + * type="string" + * ), + * @OA\Property( + * property="subscriber_mname", + * description="The subscriber middle name of insurance.", + * type="string" + * ), + * @OA\Property( + * property="subscriber_fname", + * description="The subscriber first name of insurance.", + * type="string" + * ), + * @OA\Property( + * property="subscriber_relationship", + * description="The subscriber relationship of insurance. `subscriber_relationship` can be found by querying `resource=/api/list/subscriber_relationship`", + * type="string" + * ), + * @OA\Property( + * property="subscriber_ss", + * description="The subscriber ss number of insurance.", + * type="string" + * ), + * @OA\Property( + * property="subscriber_DOB", + * description="The subscriber DOB of insurance.", + * type="string" + * ), + * @OA\Property( + * property="subscriber_street", + * description="The subscriber street address of insurance.", + * type="string" + * ), + * @OA\Property( + * property="subscriber_postal_code", + * description="The subscriber postal code of insurance.", + * type="string" + * ), + * @OA\Property( + * property="subscriber_city", + * description="The subscriber city of insurance.", + * type="string" + * ), + * @OA\Property( + * property="subscriber_state", + * description="The subscriber state of insurance. `state` can be found by querying `resource=/api/list/state`", + * type="string" + * ), + * @OA\Property( + * property="subscriber_country", + * description="The subscriber country of insurance. `country` can be found by querying `resource=/api/list/country`", + * type="string" + * ), + * @OA\Property( + * property="subscriber_phone", + * description="The subscriber phone of insurance.", + * type="string" + * ), + * @OA\Property( + * property="subscriber_employer", + * description="The subscriber employer of insurance.", + * type="string" + * ), + * @OA\Property( + * property="subscriber_employer_street", + * description="The subscriber employer street of insurance.", + * type="string" + * ), + * @OA\Property( + * property="subscriber_employer_postal_code", + * description="The subscriber employer postal code of insurance.", + * type="string" + * ), + * @OA\Property( + * property="subscriber_employer_state", + * description="The subscriber employer state of insurance.", + * type="string" + * ), + * @OA\Property( + * property="subscriber_employer_country", + * description="The subscriber employer country of insurance.", + * type="string" + * ), + * @OA\Property( + * property="subscriber_employer_city", + * description="The subscriber employer city of insurance.", + * type="string" + * ), + * @OA\Property( + * property="copay", + * description="The copay of insurance.", + * type="string" + * ), + * @OA\Property( + * property="date", + * description="The effective date of insurance in YYYY-MM-DD format. This value cannot be after the date_end property and cannot be the same date as any other insurance policy for the same insurance type ('primary, 'secondary', etc).", + * type="string" + * ), + * @OA\Property( + * property="date_end", + * description="The effective end date of insurance in YYYY-MM-DD format. This value cannot be before the date property. If it is null then this policy is the current policy for this policy type for the patient. There can only be one current policy per type and the request will fail if there is already a current policy for this type.", + * type="string" + * ), + * @OA\Property( + * property="subscriber_sex", + * description="The subscriber sex of insurance.", + * type="string" + * ), + * @OA\Property( + * property="accept_assignment", + * description="The accept_assignment of insurance.", + * type="string" + * ), + * @OA\Property( + * property="policy_type", + * description="The 837p list of policy types for an insurance. See src/Billing/InsurancePolicyType.php for the list of valid values.", + * type="string" + * ), + * @OA\Property( + * property="type", + * description="The type or category of OpenEMR insurance policy, 'primary', 'secondary', or 'tertiary'. If this field is missing it will default to 'primary'.", + * type="string" + * ), + * required={"provider", "policy_number", "subscriber_fname", "subscriber_lname", "subscriber_relationship", "subscriber_ss", "subscriber_DOB", "subscriber_street", "subscriber_postal_code", "subscriber_city", "subscriber_state", "subscriber_sex", "accept_assignment"}, + * example={ + * "provider": "33", + * "plan_name": "Some Plan", + * "policy_number": "12345", + * "group_number": "252412", + * "subscriber_lname": "Tester", + * "subscriber_mname": "Xi", + * "subscriber_fname": "Foo", + * "subscriber_relationship": "other", + * "subscriber_ss": "234231234", + * "subscriber_DOB": "2018-10-03", + * "subscriber_street": "183 Cool St", + * "subscriber_postal_code": "23418", + * "subscriber_city": "Cooltown", + * "subscriber_state": "AZ", + * "subscriber_country": "USA", + * "subscriber_phone": "234-598-2123", + * "subscriber_employer": "Some Employer", + * "subscriber_employer_street": "123 Heather Lane", + * "subscriber_employer_postal_code": "23415", + * "subscriber_employer_state": "AZ", + * "subscriber_employer_country": "USA", + * "subscriber_employer_city": "Cooltown", + * "copay": "35", + * "date": "2018-10-15", + * "subscriber_sex": "Female", + * "accept_assignment": "TRUE", + * "policy_type": "a", + * "type": "primary" + * } + * ) + */ + + /** + * @OA\Put( + * path="/api/patient/{puuid}/insurance/{insuranceUuid}", + * description="Edit a specific patient insurance policy. Requires the patients/demo/write ACL to call. This method is the preferred method for updating a patient insurance policy. The {insuranceId} can be found by querying /api/patient/{pid}/insurance", + * tags={"standard"}, + * @OA\Parameter( + * name="puuid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="insuranceUuid", + * in="path", + * description="The insurance policy uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_insurance_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "PUT /api/patient/:puuid/insurance/:insuranceUuid" => function ($puuid, $insuranceUuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "demo", 'write'); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new InsuranceRestController())->put($puuid, $insuranceUuid, $data); + + return $return; + }, + + /** + * @OA\Post( + * path="/api/patient/{puuid}/insurance", + * description="Submits a new patient insurance.", + * tags={"standard"}, + * @OA\Parameter( + * name="puuid", + * in="path", + * description="The uuid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_insurance_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "POST /api/patient/:puuid/insurance" => function ($puuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "demo", ['write','addonly']); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new InsuranceRestController())->post($puuid, $data); + + return $return; + }, + /** + * Schema for the message request + * + * @OA\Schema( + * schema="api_message_request", + * @OA\Property( + * property="body", + * description="The body of message.", + * type="string" + * ), + * @OA\Property( + * property="groupname", + * description="The group name (usually is 'Default').", + * type="string" + * ), + * @OA\Property( + * property="from", + * description="The sender of the message.", + * type="string" + * ), + * @OA\Property( + * property="to", + * description="The recipient of the message.", + * type="string" + * ), + * @OA\Property( + * property="title", + * description="use an option from resource=/api/list/note_type", + * type="string" + * ), + * @OA\Property( + * property="message_status", + * description="use an option from resource=/api/list/message_status", + * type="string" + * ), + * required={"body", "groupname", "from", "to", "title", "message_status"}, + * example={ + * "body": "Test 456", + * "groupname": "Default", + * "from": "Matthew", + * "to": "admin", + * "title": "Other", + * "message_status": "New" + * } + * ) + */ + /** + * @OA\Post( + * path="/api/patient/{pid}/message", + * description="Submits a pnote message", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The id for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_message_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "POST /api/patient/:pid/message" => function ($pid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "notes"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new MessageRestController())->post($pid, $data); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/patient/{pid}/transaction", + * description="Get Transactions for a patient", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The pid for the patient", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + + "GET /api/patient/:pid/transaction" => function ($pid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "trans"); + $cont = new TransactionRestController(); + $return = (new TransactionRestController())->GetPatientTransactions($pid); + + return $return; + }, + + /** + * Schema for the transaction request + * + * @OA\Schema( + * schema="api_transaction_request", + * @OA\Property( + * property="message", + * description="The message of the transaction.", + * type="string" + * ), + * @OA\Property( + * property="type", + * description="The type of transaction. Use an option from resource=/api/transaction_type", + * type="string" + * ), + * @OA\Property( + * property="groupname", + * description="The group name (usually is 'Default').", + * type="string" + * ), + * @OA\Property( + * property="referByNpi", + * description="NPI of the person creating the referral.", + * type="string" + * ), + * @OA\Property( + * property="referToNpi", + * description="NPI of the person getting the referral.", + * type="string" + * ), + * @OA\Property( + * property="referDiagnosis", + * description="The referral diagnosis.", + * type="string" + * ), + * @OA\Property( + * property="riskLevel", + * description="The risk level. (Low, Medium, High)", + * type="string" + * ), + * @OA\Property( + * property="includeVitals", + * description="Are vitals included (0,1)", + * type="string" + * ), + * @OA\Property( + * property="referralDate", + * description="The date of the referral", + * type="string" + * ), + * @OA\Property( + * property="authorization", + * description="The authorization for the referral", + * type="string" + * ), + * @OA\Property( + * property="visits", + * description="The number of vists for the referral", + * type="string" + * ), + * @OA\Property( + * property="validFrom", + * description="The date the referral is valid from", + * type="string" + * ), + * @OA\Property( + * property="validThrough", + * description="The date the referral is valid through", + * type="string" + * ), + * required={"message", "groupname", "title"}, + * example={ + * "message": "Message", + * "type": "LBTref", + * "groupname": "Default", + * "referByNpi":"9999999999", + * "referToNpi":"9999999999", + * "referDiagnosis":"Diag 1", + * "riskLevel":"Low", + * "includeVitals":"1", + * "referralDate":"2022-01-01", + * "authorization":"Auth_123", + * "visits": "1", + * "validFrom": "2022-01-02", + * "validThrough": "2022-01-03", + * "body": "Reason 1" + * } + * ) + */ + /** + * @OA\Post( + * path="/api/patient/{pid}/transaction", + * description="Submits a transaction", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The pid for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_transaction_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "POST /api/patient/:pid/transaction" => function ($pid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "trans"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new TransactionRestController())->CreateTransaction($pid, $data); + + return $return; + }, + + /** + * @OA\PUT( + * path="/api/transaction/{tid}", + * description="Updates a transaction", + * tags={"standard"}, + * @OA\Parameter( + * name="tid", + * in="path", + * description="The id for the transaction.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_transaction_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "PUT /api/transaction/:tid" => function ($tid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "trans"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new TransactionRestController())->UpdateTransaction($tid, $data); + + return $return; + }, + + /** + * @OA\Put( + * path="/api/patient/{pid}/message/{mid}", + * description="Edit a pnote message", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The id for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="mid", + * in="path", + * description="The id for the pnote message.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema(ref="#/components/schemas/api_message_request") + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "PUT /api/patient/:pid/message/:mid" => function ($pid, $mid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "notes"); + $data = (array) (json_decode(file_get_contents("php://input"))); + $return = (new MessageRestController())->put($pid, $mid, $data); + + return $return; + }, + + /** + * @OA\Delete( + * path="/api/patient/{pid}/message/{mid}", + * description="Delete a pnote message", + * tags={"standard"}, + * @OA\Parameter( + * name="pid", + * in="path", + * description="The id for the patient.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="mid", + * in="path", + * description="The id for the pnote message.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "DELETE /api/patient/:pid/message/:mid" => function ($pid, $mid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "notes"); + $return = (new MessageRestController())->delete($pid, $mid); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/immunization", + * description="Retrieves a list of immunizations", + * tags={"standard"}, + * @OA\Parameter( + * name="patient_id", + * in="query", + * description="The pid for the patient.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="id", + * in="query", + * description="The id for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="uuid", + * in="query", + * description="The uuid for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="administered_date", + * in="query", + * description="The administered date for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="immunization_id", + * in="query", + * description="The immunization list_id for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="cvx_code", + * in="query", + * description="The cvx code for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="manufacturer", + * in="query", + * description="The manufacturer for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="lot_number", + * in="query", + * description="The lot number for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="administered_by_id", + * in="query", + * description="The administered by id for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="administered_by", + * in="query", + * description="The administered by for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="education_date", + * in="query", + * description="The education date for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="vis_date", + * in="query", + * description="The vis date for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="note", + * in="query", + * description="The note for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="create_date", + * in="query", + * description="The create date for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="update_date", + * in="query", + * description="The update date for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="created_by", + * in="query", + * description="The created_by for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="updated_by", + * in="query", + * description="The updated_by for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="amount_administered", + * in="query", + * description="The amount administered for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="amount_administered_unit", + * in="query", + * description="The amount administered unit for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="expiration_date", + * in="query", + * description="The expiration date for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="route", + * in="query", + * description="The route for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="administration_site", + * in="query", + * description="The administration site for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="added_erroneously", + * in="query", + * description="The added_erroneously for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="external_id", + * in="query", + * description="The external_id for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="completion_status", + * in="query", + * description="The completion status for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="information_source", + * in="query", + * description="The information source for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="refusal_reason", + * in="query", + * description="The refusal reason for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Parameter( + * name="ordering_provider", + * in="query", + * description="The ordering provider for the immunization.", + * required=false, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/immunization" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new ImmunizationRestController())->getAll($_GET); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/immunization/{uuid}", + * description="Retrieves a immunization", + * tags={"standard"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the immunization.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/immunization/:uuid" => function ($uuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new ImmunizationRestController())->getOne($uuid); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/procedure", + * description="Retrieves a list of all procedures", + * tags={"standard"}, + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/procedure" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new ProcedureRestController())->getAll(); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/procedure/{uuid}", + * description="Retrieves a procedure", + * tags={"standard"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the procedure.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/procedure/:uuid" => function ($uuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new ProcedureRestController())->getOne($uuid); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/drug", + * description="Retrieves a list of all drugs", + * tags={"standard"}, + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/drug" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new DrugRestController())->getAll(); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/drug/{uuid}", + * description="Retrieves a drug", + * tags={"standard"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the drug.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/drug/:uuid" => function ($uuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new DrugRestController())->getOne($uuid); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/prescription", + * description="Retrieves a list of all prescriptions", + * tags={"standard"}, + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/prescription" => function (HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new PrescriptionRestController())->getAll(); + + return $return; + }, + + /** + * @OA\Get( + * path="/api/prescription/{uuid}", + * description="Retrieves a prescription", + * tags={"standard"}, + * @OA\Parameter( + * name="uuid", + * in="path", + * description="The uuid for the prescription.", + * required=true, + * @OA\Schema( + * type="string" + * ) + * ), + * @OA\Response( + * response="200", + * ref="#/components/responses/standard" + * ), + * @OA\Response( + * response="400", + * ref="#/components/responses/badrequest" + * ), + * @OA\Response( + * response="401", + * ref="#/components/responses/unauthorized" + * ), + * security={{"openemr_auth":{}}} + * ) + */ + "GET /api/prescription/:uuid" => function ($uuid, HttpRestRequest $request) { + RestConfig::request_authorization_check($request, "patients", "med"); + $return = (new PrescriptionRestController())->getOne($uuid); + + return $return; + } +); diff --git a/composer.json b/composer.json index c7cb9c1a4c62..48d4bf889e61 100644 --- a/composer.json +++ b/composer.json @@ -106,7 +106,8 @@ "vlucas/phpdotenv": "5.6.2", "waryway/php-traits-library": "1.0.4", "yubico/u2flib-server": "1.0.2", - "twilio/sdk": "8.7.0" + "twilio/sdk": "8.7.0", + "symfony/psr-http-message-bridge": "6.4.13" }, "config": { "platform": { @@ -149,11 +150,11 @@ "phpstan/extension-installer": "^1.4", "phpstan/phpstan": "^2.1", "phpstan/phpstan-phpunit": "^2.0", - "phpunit/php-code-coverage": "^11.0", + "phpunit/php-code-coverage": "^11.0", "phpunit/phpunit": "11.*", "rector/rector": "^2.1", - "squizlabs/php_codesniffer": "^3.13", "symfony/panther": "2.*", + "squizlabs/php_codesniffer": "^3.13", "zircote/swagger-php": "3.*" }, "repositories": [ diff --git a/composer.lock b/composer.lock index af137d542d87..8972118ddd77 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "041bf82ce337ca70f9dbf793c29abfa4", + "content-hash": "545955a24ef5ca53abc0ad4fd7593316", "packages": [ { "name": "academe/authorizenet-objects", @@ -555,16 +555,16 @@ }, { "name": "dasprid/enum", - "version": "1.0.6", + "version": "1.0.7", "source": { "type": "git", "url": "https://github.com/DASPRiD/Enum.git", - "reference": "8dfd07c6d2cf31c8da90c53b83c026c7696dda90" + "reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/8dfd07c6d2cf31c8da90c53b83c026c7696dda90", - "reference": "8dfd07c6d2cf31c8da90c53b83c026c7696dda90", + "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/b5874fa9ed0043116c72162ec7f4fb50e02e7cce", + "reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce", "shasum": "" }, "require": { @@ -599,9 +599,9 @@ ], "support": { "issues": "https://github.com/DASPRiD/Enum/issues", - "source": "https://github.com/DASPRiD/Enum/tree/1.0.6" + "source": "https://github.com/DASPRiD/Enum/tree/1.0.7" }, - "time": "2024-08-09T14:30:48+00:00" + "time": "2025-09-16T12:23:56+00:00" }, { "name": "defuse/php-encryption", @@ -1121,20 +1121,20 @@ }, { "name": "google/apiclient-services", - "version": "v0.405.0", + "version": "v0.412.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client-services.git", - "reference": "8366037e450b62ffc1c5489459f207640acca2b4" + "reference": "212b51a11caa98e71c97f08041cc58e3425b2e15" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/8366037e450b62ffc1c5489459f207640acca2b4", - "reference": "8366037e450b62ffc1c5489459f207640acca2b4", + "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/212b51a11caa98e71c97f08041cc58e3425b2e15", + "reference": "212b51a11caa98e71c97f08041cc58e3425b2e15", "shasum": "" }, "require": { - "php": "^8.0" + "php": "^8.1" }, "require-dev": { "phpunit/phpunit": "^9.6" @@ -1159,29 +1159,29 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client-services/issues", - "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.405.0" + "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.412.0" }, - "time": "2025-06-04T17:28:44+00:00" + "time": "2025-09-15T00:56:22+00:00" }, { "name": "google/auth", - "version": "v1.47.1", + "version": "v1.48.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-auth-library-php.git", - "reference": "d7a0a215ec42ca0c8cb40e9ae0c5960aa9a024b7" + "reference": "3053a5bfe284538419d4fee8c9df148488db6d30" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/d7a0a215ec42ca0c8cb40e9ae0c5960aa9a024b7", - "reference": "d7a0a215ec42ca0c8cb40e9ae0c5960aa9a024b7", + "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/3053a5bfe284538419d4fee8c9df148488db6d30", + "reference": "3053a5bfe284538419d4fee8c9df148488db6d30", "shasum": "" }, "require": { "firebase/php-jwt": "^6.0", "guzzlehttp/guzzle": "^7.4.5", "guzzlehttp/psr7": "^2.4.5", - "php": "^8.0", + "php": "^8.1", "psr/cache": "^2.0||^3.0", "psr/http-message": "^1.1||^2.0", "psr/log": "^3.0" @@ -1193,7 +1193,7 @@ "phpspec/prophecy-phpunit": "^2.1", "phpunit/phpunit": "^9.6", "sebastian/comparator": ">=1.2.3", - "squizlabs/php_codesniffer": "^3.5", + "squizlabs/php_codesniffer": "^4.0", "symfony/process": "^6.0||^7.0", "webmozart/assert": "^1.11" }, @@ -1220,9 +1220,9 @@ "support": { "docs": "https://cloud.google.com/php/docs/reference/auth/latest", "issues": "https://github.com/googleapis/google-auth-library-php/issues", - "source": "https://github.com/googleapis/google-auth-library-php/tree/v1.47.1" + "source": "https://github.com/googleapis/google-auth-library-php/tree/v1.48.0" }, - "time": "2025-07-09T15:26:02+00:00" + "time": "2025-09-16T22:09:18+00:00" }, { "name": "graham-campbell/result-type", @@ -1414,16 +1414,16 @@ }, { "name": "guzzlehttp/promises", - "version": "2.2.0", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c" + "reference": "481557b130ef3790cf82b713667b43030dc9c957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c", - "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c", + "url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957", + "reference": "481557b130ef3790cf82b713667b43030dc9c957", "shasum": "" }, "require": { @@ -1431,7 +1431,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.39 || ^9.6.20" + "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "type": "library", "extra": { @@ -1477,7 +1477,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.2.0" + "source": "https://github.com/guzzle/promises/tree/2.3.0" }, "funding": [ { @@ -1493,20 +1493,20 @@ "type": "tidelift" } ], - "time": "2025-03-27T13:27:01+00:00" + "time": "2025-08-22T14:34:08+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.7.1", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16" + "reference": "21dc724a0583619cd1652f673303492272778051" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16", - "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", + "reference": "21dc724a0583619cd1652f673303492272778051", "shasum": "" }, "require": { @@ -1522,7 +1522,7 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "http-interop/http-factory-tests": "0.9.0", - "phpunit/phpunit": "^8.5.39 || ^9.6.20" + "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -1593,7 +1593,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.7.1" + "source": "https://github.com/guzzle/psr7/tree/2.8.0" }, "funding": [ { @@ -1609,7 +1609,7 @@ "type": "tidelift" } ], - "time": "2025-03-27T12:30:47+00:00" + "time": "2025-08-23T21:21:41+00:00" }, { "name": "html2text/html2text", @@ -3606,16 +3606,16 @@ }, { "name": "laminas/laminas-view", - "version": "2.40.0", + "version": "2.41.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-view.git", - "reference": "ab63fd76444941e92c5ef1ed0ac59366b4fe9330" + "reference": "77bb5814062fb485dc67baa22ea4b83cc93f7e1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-view/zipball/ab63fd76444941e92c5ef1ed0ac59366b4fe9330", - "reference": "ab63fd76444941e92c5ef1ed0ac59366b4fe9330", + "url": "https://api.github.com/repos/laminas/laminas-view/zipball/77bb5814062fb485dc67baa22ea4b83cc93f7e1d", + "reference": "77bb5814062fb485dc67baa22ea4b83cc93f7e1d", "shasum": "" }, "require": { @@ -3704,7 +3704,7 @@ "type": "community_bridge" } ], - "time": "2025-07-29T10:45:12+00:00" + "time": "2025-08-07T08:55:27+00:00" }, { "name": "laminas/laminas-xml", @@ -5120,16 +5120,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.13.3", + "version": "1.13.4", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "faed855a7b5f4d4637717c2b3863e277116beb36" + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/faed855a7b5f4d4637717c2b3863e277116beb36", - "reference": "faed855a7b5f4d4637717c2b3863e277116beb36", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", "shasum": "" }, "require": { @@ -5168,7 +5168,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.3" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" }, "funding": [ { @@ -5176,7 +5176,7 @@ "type": "tidelift" } ], - "time": "2025-07-05T12:25:42+00:00" + "time": "2025-08-01T08:46:24+00:00" }, { "name": "nikic/php-parser", @@ -6608,16 +6608,16 @@ }, { "name": "phpoption/phpoption", - "version": "1.9.3", + "version": "1.9.4", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-option.git", - "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54" + "reference": "638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54", - "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d", + "reference": "638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d", "shasum": "" }, "require": { @@ -6625,7 +6625,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" + "phpunit/phpunit": "^8.5.44 || ^9.6.25 || ^10.5.53 || ^11.5.34" }, "type": "library", "extra": { @@ -6667,7 +6667,7 @@ ], "support": { "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.9.3" + "source": "https://github.com/schmittjoh/php-option/tree/1.9.4" }, "funding": [ { @@ -6679,7 +6679,7 @@ "type": "tidelift" } ], - "time": "2024-07-20T21:41:07+00:00" + "time": "2025-08-21T11:53:16+00:00" }, { "name": "phpseclib/phpseclib", @@ -7900,23 +7900,23 @@ }, { "name": "react/promise", - "version": "v3.2.0", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/reactphp/promise.git", - "reference": "8a164643313c71354582dc850b42b33fa12a4b63" + "reference": "23444f53a813a3296c1368bb104793ce8d88f04a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/8a164643313c71354582dc850b42b33fa12a4b63", - "reference": "8a164643313c71354582dc850b42b33fa12a4b63", + "url": "https://api.github.com/repos/reactphp/promise/zipball/23444f53a813a3296c1368bb104793ce8d88f04a", + "reference": "23444f53a813a3296c1368bb104793ce8d88f04a", "shasum": "" }, "require": { "php": ">=7.1.0" }, "require-dev": { - "phpstan/phpstan": "1.10.39 || 1.4.10", + "phpstan/phpstan": "1.12.28 || 1.4.10", "phpunit/phpunit": "^9.6 || ^7.5" }, "type": "library", @@ -7961,7 +7961,7 @@ ], "support": { "issues": "https://github.com/reactphp/promise/issues", - "source": "https://github.com/reactphp/promise/tree/v3.2.0" + "source": "https://github.com/reactphp/promise/tree/v3.3.0" }, "funding": [ { @@ -7969,7 +7969,7 @@ "type": "open_collective" } ], - "time": "2024-05-24T10:39:05+00:00" + "time": "2025-08-19T18:57:03+00:00" }, { "name": "react/socket", @@ -10157,16 +10157,16 @@ }, { "name": "symfony/polyfill-php83", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" + "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", - "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5", + "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5", "shasum": "" }, "require": { @@ -10213,7 +10213,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0" }, "funding": [ { @@ -10224,25 +10224,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2025-07-08T02:45:35+00:00" }, { "name": "symfony/process", - "version": "v7.3.0", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af" + "reference": "32241012d521e2e8a9d713adb0812bb773b907f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", - "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", + "url": "https://api.github.com/repos/symfony/process/zipball/32241012d521e2e8a9d713adb0812bb773b907f1", + "reference": "32241012d521e2e8a9d713adb0812bb773b907f1", "shasum": "" }, "require": { @@ -10274,7 +10278,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.3.0" + "source": "https://github.com/symfony/process/tree/v7.3.3" }, "funding": [ { @@ -10285,12 +10289,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-04-17T09:11:12+00:00" + "time": "2025-08-18T09:42:54+00:00" }, { "name": "symfony/property-access", @@ -10372,6 +10380,89 @@ ], "time": "2022-06-27T13:16:42+00:00" }, + { + "name": "symfony/psr-http-message-bridge", + "version": "v6.4.13", + "source": { + "type": "git", + "url": "https://github.com/symfony/psr-http-message-bridge.git", + "reference": "c9cf83326a1074f83a738fc5320945abf7fb7fec" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/c9cf83326a1074f83a738fc5320945abf7fb7fec", + "reference": "c9cf83326a1074f83a738fc5320945abf7fb7fec", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/http-message": "^1.0|^2.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0" + }, + "conflict": { + "php-http/discovery": "<1.15", + "symfony/http-kernel": "<6.2" + }, + "require-dev": { + "nyholm/psr7": "^1.1", + "php-http/discovery": "^1.15", + "psr/log": "^1.1.4|^2|^3", + "symfony/browser-kit": "^5.4|^6.0|^7.0", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/framework-bundle": "^6.2|^7.0", + "symfony/http-kernel": "^6.2|^7.0" + }, + "type": "symfony-bridge", + "autoload": { + "psr-4": { + "Symfony\\Bridge\\PsrHttpMessage\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "PSR HTTP message bridge", + "homepage": "https://symfony.com", + "keywords": [ + "http", + "http-message", + "psr-17", + "psr-7" + ], + "support": { + "source": "https://github.com/symfony/psr-http-message-bridge/tree/v6.4.13" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:18:03+00:00" + }, { "name": "symfony/service-contracts", "version": "v3.6.0", @@ -10457,16 +10548,16 @@ }, { "name": "symfony/string", - "version": "v7.3.2", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "42f505aff654e62ac7ac2ce21033818297ca89ca" + "reference": "17a426cce5fd1f0901fefa9b2a490d0038fd3c9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/42f505aff654e62ac7ac2ce21033818297ca89ca", - "reference": "42f505aff654e62ac7ac2ce21033818297ca89ca", + "url": "https://api.github.com/repos/symfony/string/zipball/17a426cce5fd1f0901fefa9b2a490d0038fd3c9c", + "reference": "17a426cce5fd1f0901fefa9b2a490d0038fd3c9c", "shasum": "" }, "require": { @@ -10524,7 +10615,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.3.2" + "source": "https://github.com/symfony/string/tree/v7.3.3" }, "funding": [ { @@ -10544,20 +10635,20 @@ "type": "tidelift" } ], - "time": "2025-07-10T08:47:49+00:00" + "time": "2025-08-25T06:35:40+00:00" }, { "name": "symfony/var-exporter", - "version": "v7.3.0", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "c9a1168891b5aaadfd6332ef44393330b3498c4c" + "reference": "d4dfcd2a822cbedd7612eb6fbd260e46f87b7137" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/c9a1168891b5aaadfd6332ef44393330b3498c4c", - "reference": "c9a1168891b5aaadfd6332ef44393330b3498c4c", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/d4dfcd2a822cbedd7612eb6fbd260e46f87b7137", + "reference": "d4dfcd2a822cbedd7612eb6fbd260e46f87b7137", "shasum": "" }, "require": { @@ -10605,7 +10696,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v7.3.0" + "source": "https://github.com/symfony/var-exporter/tree/v7.3.3" }, "funding": [ { @@ -10616,12 +10707,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-05-15T09:04:05+00:00" + "time": "2025-08-18T13:10:53+00:00" }, { "name": "symfony/yaml", @@ -11545,16 +11640,16 @@ }, { "name": "phpstan/phpstan", - "version": "2.1.21", + "version": "2.1.27", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "1ccf445757458c06a04eb3f803603cb118fe5fa6" + "reference": "25da374959afa391992792691093550b3098ef1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/1ccf445757458c06a04eb3f803603cb118fe5fa6", - "reference": "1ccf445757458c06a04eb3f803603cb118fe5fa6", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/25da374959afa391992792691093550b3098ef1e", + "reference": "25da374959afa391992792691093550b3098ef1e", "shasum": "" }, "require": { @@ -11599,7 +11694,7 @@ "type": "github" } ], - "time": "2025-07-28T19:35:08+00:00" + "time": "2025-09-17T09:55:13+00:00" }, { "name": "phpstan/phpstan-phpunit", @@ -11656,16 +11751,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "11.0.10", + "version": "11.0.11", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "1a800a7446add2d79cc6b3c01c45381810367d76" + "reference": "4f7722aa9a7b76aa775e2d9d4e95d1ea16eeeef4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/1a800a7446add2d79cc6b3c01c45381810367d76", - "reference": "1a800a7446add2d79cc6b3c01c45381810367d76", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/4f7722aa9a7b76aa775e2d9d4e95d1ea16eeeef4", + "reference": "4f7722aa9a7b76aa775e2d9d4e95d1ea16eeeef4", "shasum": "" }, "require": { @@ -11722,7 +11817,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/show" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.11" }, "funding": [ { @@ -11742,7 +11837,7 @@ "type": "tidelift" } ], - "time": "2025-06-18T08:56:18+00:00" + "time": "2025-08-27T14:37:49+00:00" }, { "name": "phpunit/php-file-iterator", @@ -11991,16 +12086,16 @@ }, { "name": "phpunit/phpunit", - "version": "11.5.27", + "version": "11.5.39", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "446d43867314781df7e9adf79c3ec7464956fd8f" + "reference": "ad5597f79d8489d2870073ac0bc0dd0ad1fa9931" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/446d43867314781df7e9adf79c3ec7464956fd8f", - "reference": "446d43867314781df7e9adf79c3ec7464956fd8f", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ad5597f79d8489d2870073ac0bc0dd0ad1fa9931", + "reference": "ad5597f79d8489d2870073ac0bc0dd0ad1fa9931", "shasum": "" }, "require": { @@ -12010,24 +12105,24 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.13.3", + "myclabs/deep-copy": "^1.13.4", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.2", - "phpunit/php-code-coverage": "^11.0.10", + "phpunit/php-code-coverage": "^11.0.11", "phpunit/php-file-iterator": "^5.1.0", "phpunit/php-invoker": "^5.0.1", "phpunit/php-text-template": "^4.0.1", "phpunit/php-timer": "^7.0.1", "sebastian/cli-parser": "^3.0.2", "sebastian/code-unit": "^3.0.3", - "sebastian/comparator": "^6.3.1", + "sebastian/comparator": "^6.3.2", "sebastian/diff": "^6.0.2", "sebastian/environment": "^7.2.1", "sebastian/exporter": "^6.3.0", "sebastian/global-state": "^7.0.2", "sebastian/object-enumerator": "^6.0.1", - "sebastian/type": "^5.1.2", + "sebastian/type": "^5.1.3", "sebastian/version": "^5.0.2", "staabm/side-effects-detector": "^1.0.5" }, @@ -12072,7 +12167,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.27" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.39" }, "funding": [ { @@ -12096,20 +12191,20 @@ "type": "tidelift" } ], - "time": "2025-07-11T04:10:06+00:00" + "time": "2025-09-14T06:20:41+00:00" }, { "name": "rector/rector", - "version": "2.1.2", + "version": "2.1.7", "source": { "type": "git", "url": "https://github.com/rectorphp/rector.git", - "reference": "40a71441dd73fa150a66102f5ca1364c44fc8fff" + "reference": "c34cc07c4698f007a20dc5c99ff820089ae413ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/40a71441dd73fa150a66102f5ca1364c44fc8fff", - "reference": "40a71441dd73fa150a66102f5ca1364c44fc8fff", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/c34cc07c4698f007a20dc5c99ff820089ae413ce", + "reference": "c34cc07c4698f007a20dc5c99ff820089ae413ce", "shasum": "" }, "require": { @@ -12148,7 +12243,7 @@ ], "support": { "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/2.1.2" + "source": "https://github.com/rectorphp/rector/tree/2.1.7" }, "funding": [ { @@ -12156,7 +12251,7 @@ "type": "github" } ], - "time": "2025-07-17T19:30:06+00:00" + "time": "2025-09-10T11:13:58+00:00" }, { "name": "sebastian/cli-parser", @@ -12330,16 +12425,16 @@ }, { "name": "sebastian/comparator", - "version": "6.3.1", + "version": "6.3.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959" + "reference": "85c77556683e6eee4323e4c5468641ca0237e2e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/24b8fbc2c8e201bb1308e7b05148d6ab393b6959", - "reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/85c77556683e6eee4323e4c5468641ca0237e2e8", + "reference": "85c77556683e6eee4323e4c5468641ca0237e2e8", "shasum": "" }, "require": { @@ -12398,15 +12493,27 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.1" + "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "type": "tidelift" } ], - "time": "2025-03-07T06:57:01+00:00" + "time": "2025-08-10T08:07:46+00:00" }, { "name": "sebastian/complexity", @@ -12923,23 +13030,23 @@ }, { "name": "sebastian/recursion-context", - "version": "6.0.2", + "version": "6.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" + "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", - "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/f6458abbf32a6c8174f8f26261475dc133b3d9dc", + "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { @@ -12975,28 +13082,40 @@ "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.3" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", + "type": "tidelift" } ], - "time": "2024-07-03T05:10:34+00:00" + "time": "2025-08-13T04:42:22+00:00" }, { "name": "sebastian/type", - "version": "5.1.2", + "version": "5.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e" + "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/a8a7e30534b0eb0c77cd9d07e82de1a114389f5e", - "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/f77d2d4e78738c98d9a68d2596fe5e8fa380f449", + "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449", "shasum": "" }, "require": { @@ -13032,15 +13151,27 @@ "support": { "issues": "https://github.com/sebastianbergmann/type/issues", "security": "https://github.com/sebastianbergmann/type/security/policy", - "source": "https://github.com/sebastianbergmann/type/tree/5.1.2" + "source": "https://github.com/sebastianbergmann/type/tree/5.1.3" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/type", + "type": "tidelift" } ], - "time": "2025-03-18T13:35:50+00:00" + "time": "2025-08-09T06:55:48+00:00" }, { "name": "sebastian/version", @@ -13098,16 +13229,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.13.2", + "version": "3.13.4", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "5b5e3821314f947dd040c70f7992a64eac89025c" + "reference": "ad545ea9c1b7d270ce0fc9cbfb884161cd706119" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/5b5e3821314f947dd040c70f7992a64eac89025c", - "reference": "5b5e3821314f947dd040c70f7992a64eac89025c", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/ad545ea9c1b7d270ce0fc9cbfb884161cd706119", + "reference": "ad545ea9c1b7d270ce0fc9cbfb884161cd706119", "shasum": "" }, "require": { @@ -13178,7 +13309,7 @@ "type": "thanks_dev" } ], - "time": "2025-06-17T22:17:01+00:00" + "time": "2025-09-05T05:47:09+00:00" }, { "name": "staabm/side-effects-detector", @@ -13234,16 +13365,16 @@ }, { "name": "symfony/browser-kit", - "version": "v7.3.0", + "version": "v7.3.2", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "5384291845e74fd7d54f3d925c4a86ce12336593" + "reference": "f0b889b73a845cddef1d25fe207b37fd04cb5419" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/5384291845e74fd7d54f3d925c4a86ce12336593", - "reference": "5384291845e74fd7d54f3d925c4a86ce12336593", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/f0b889b73a845cddef1d25fe207b37fd04cb5419", + "reference": "f0b889b73a845cddef1d25fe207b37fd04cb5419", "shasum": "" }, "require": { @@ -13282,7 +13413,7 @@ "description": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/browser-kit/tree/v7.3.0" + "source": "https://github.com/symfony/browser-kit/tree/v7.3.2" }, "funding": [ { @@ -13293,25 +13424,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-03-05T10:15:41+00:00" + "time": "2025-07-10T08:47:49+00:00" }, { "name": "symfony/dom-crawler", - "version": "v7.3.1", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "8b2ee2e06ab99fa5f067b6699296d4e35c156bb9" + "reference": "efa076ea0eeff504383ff0dcf827ea5ce15690ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/8b2ee2e06ab99fa5f067b6699296d4e35c156bb9", - "reference": "8b2ee2e06ab99fa5f067b6699296d4e35c156bb9", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/efa076ea0eeff504383ff0dcf827ea5ce15690ba", + "reference": "efa076ea0eeff504383ff0dcf827ea5ce15690ba", "shasum": "" }, "require": { @@ -13349,7 +13484,7 @@ "description": "Eases DOM navigation for HTML and XML documents", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v7.3.1" + "source": "https://github.com/symfony/dom-crawler/tree/v7.3.3" }, "funding": [ { @@ -13360,25 +13495,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-06-15T10:07:06+00:00" + "time": "2025-08-06T20:13:54+00:00" }, { "name": "symfony/error-handler", - "version": "v7.3.1", + "version": "v7.3.2", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "35b55b166f6752d6aaf21aa042fc5ed280fce235" + "reference": "0b31a944fcd8759ae294da4d2808cbc53aebd0c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/35b55b166f6752d6aaf21aa042fc5ed280fce235", - "reference": "35b55b166f6752d6aaf21aa042fc5ed280fce235", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/0b31a944fcd8759ae294da4d2808cbc53aebd0c3", + "reference": "0b31a944fcd8759ae294da4d2808cbc53aebd0c3", "shasum": "" }, "require": { @@ -13426,7 +13565,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.3.1" + "source": "https://github.com/symfony/error-handler/tree/v7.3.2" }, "funding": [ { @@ -13437,25 +13576,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-06-13T07:48:40+00:00" + "time": "2025-07-07T08:17:57+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.2.8", + "version": "v7.2.9", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "3f461ff845e4529e0fa14f9639a7b6898367aa34" + "reference": "d0cc0295c9c2fd5e053fee2b2a143001f2d0c33c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/3f461ff845e4529e0fa14f9639a7b6898367aa34", - "reference": "3f461ff845e4529e0fa14f9639a7b6898367aa34", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/d0cc0295c9c2fd5e053fee2b2a143001f2d0c33c", + "reference": "d0cc0295c9c2fd5e053fee2b2a143001f2d0c33c", "shasum": "" }, "require": { @@ -13540,7 +13683,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.2.8" + "source": "https://github.com/symfony/http-kernel/tree/v7.2.9" }, "funding": [ { @@ -13551,12 +13694,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-06-28T08:20:39+00:00" + "time": "2025-07-31T09:36:38+00:00" }, { "name": "symfony/panther", @@ -13649,16 +13796,16 @@ }, { "name": "symfony/var-dumper", - "version": "v7.3.1", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "6e209fbe5f5a7b6043baba46fe5735a4b85d0d42" + "reference": "34d8d4c4b9597347306d1ec8eb4e1319b1e6986f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/6e209fbe5f5a7b6043baba46fe5735a4b85d0d42", - "reference": "6e209fbe5f5a7b6043baba46fe5735a4b85d0d42", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/34d8d4c4b9597347306d1ec8eb4e1319b1e6986f", + "reference": "34d8d4c4b9597347306d1ec8eb4e1319b1e6986f", "shasum": "" }, "require": { @@ -13670,7 +13817,6 @@ "symfony/console": "<6.4" }, "require-dev": { - "ext-iconv": "*", "symfony/console": "^6.4|^7.0", "symfony/http-kernel": "^6.4|^7.0", "symfony/process": "^6.4|^7.0", @@ -13713,7 +13859,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.3.1" + "source": "https://github.com/symfony/var-dumper/tree/v7.3.3" }, "funding": [ { @@ -13724,12 +13870,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-06-27T19:55:54+00:00" + "time": "2025-08-13T11:49:31+00:00" }, { "name": "theseer/tokenizer", diff --git a/custom/export_labworks.php b/custom/export_labworks.php index a775968ffbc3..5ac092d2f6bf 100644 --- a/custom/export_labworks.php +++ b/custom/export_labworks.php @@ -34,7 +34,7 @@ $out = ""; // Add a string to output with some basic sanitizing. -function Add($field) +function custom_labworks_Add($field) { return "^" . trim(str_replace(array("\r", "\n", "\t"), " ", $field)); } @@ -147,84 +147,84 @@ function mydie($msg): void // Patient Section. // $out .= $pid; // patient id - $out .= Add($row['pubpid']); // chart number - $out .= Add($row['lname']); // last name - $out .= Add($row['fname']); // first name - $out .= Add(substr($row['mname'], 0, 1)); // middle initial - $out .= Add(""); // alias - $out .= Add(Digits($row['ss'])); // ssn - $out .= Add(LWDate($row['DOB'])); // dob - $out .= Add(Sex($row['sex'])); // gender - $out .= Add(""); // notes - $out .= Add($row['street']); // address 1 - $out .= Add(""); // address2 - $out .= Add($row['city']); // city - $out .= Add($row['state']); // state - $out .= Add($row['postal_code']); // zip - $out .= Add(Digits($row['phone_home'])); // home phone + $out .= custom_labworks_Add($row['pubpid']); // chart number + $out .= custom_labworks_Add($row['lname']); // last name + $out .= custom_labworks_Add($row['fname']); // first name + $out .= custom_labworks_Add(substr($row['mname'], 0, 1)); // middle initial + $out .= custom_labworks_Add(""); // alias + $out .= custom_labworks_Add(Digits($row['ss'])); // ssn + $out .= custom_labworks_Add(LWDate($row['DOB'])); // dob + $out .= custom_labworks_Add(Sex($row['sex'])); // gender + $out .= custom_labworks_Add(""); // notes + $out .= custom_labworks_Add($row['street']); // address 1 + $out .= custom_labworks_Add(""); // address2 + $out .= custom_labworks_Add($row['city']); // city + $out .= custom_labworks_Add($row['state']); // state + $out .= custom_labworks_Add($row['postal_code']); // zip + $out .= custom_labworks_Add(Digits($row['phone_home'])); // home phone // Guarantor Section. OpenEMR does not have guarantors so we use the primary // insurance subscriber if there is one, otherwise the patient. // if (trim($row['lname1'])) { - $out .= Add($row['lname1']); - $out .= Add($row['fname1']); - $out .= Add(substr($row['mname1'], 0, 1)); - $out .= Add($row['sstreet1']); - $out .= Add(""); - $out .= Add($row['scity1']); - $out .= Add($row['sstate1']); - $out .= Add($row['szip1']); + $out .= custom_labworks_Add($row['lname1']); + $out .= custom_labworks_Add($row['fname1']); + $out .= custom_labworks_Add(substr($row['mname1'], 0, 1)); + $out .= custom_labworks_Add($row['sstreet1']); + $out .= custom_labworks_Add(""); + $out .= custom_labworks_Add($row['scity1']); + $out .= custom_labworks_Add($row['sstate1']); + $out .= custom_labworks_Add($row['szip1']); } else { - $out .= Add($row['lname']); - $out .= Add($row['fname']); - $out .= Add(substr($row['mname'], 0, 1)); - $out .= Add($row['street']); - $out .= Add(""); - $out .= Add($row['city']); - $out .= Add($row['state']); - $out .= Add($row['postal_code']); + $out .= custom_labworks_Add($row['lname']); + $out .= custom_labworks_Add($row['fname']); + $out .= custom_labworks_Add(substr($row['mname'], 0, 1)); + $out .= custom_labworks_Add($row['street']); + $out .= custom_labworks_Add(""); + $out .= custom_labworks_Add($row['city']); + $out .= custom_labworks_Add($row['state']); + $out .= custom_labworks_Add($row['postal_code']); } // Primary Insurance Section. // - $out .= Add($row['provider1']); - $out .= Add($row['name1']); - $out .= Add($row['street11']); - $out .= Add($row['street21']); - $out .= Add($row['city1']); - $out .= Add($row['state1']); - $out .= Add($row['zip1']); - $out .= Add(""); - $out .= Add(InsType($row['instype1'])); - $out .= Add($row['fname1'] . " " . $row['lname1']); - $out .= Add(ucfirst($row['relationship1'])); - $out .= Add($row['group1']); - $out .= Add($row['policy1']); + $out .= custom_labworks_Add($row['provider1']); + $out .= custom_labworks_Add($row['name1']); + $out .= custom_labworks_Add($row['street11']); + $out .= custom_labworks_Add($row['street21']); + $out .= custom_labworks_Add($row['city1']); + $out .= custom_labworks_Add($row['state1']); + $out .= custom_labworks_Add($row['zip1']); + $out .= custom_labworks_Add(""); + $out .= custom_labworks_Add(InsType($row['instype1'])); + $out .= custom_labworks_Add($row['fname1'] . " " . $row['lname1']); + $out .= custom_labworks_Add(ucfirst($row['relationship1'])); + $out .= custom_labworks_Add($row['group1']); + $out .= custom_labworks_Add($row['policy1']); // Secondary Insurance Section. // - $out .= Add($row['provider2']); - $out .= Add($row['name2']); - $out .= Add($row['street12']); - $out .= Add($row['street22']); - $out .= Add($row['city2']); - $out .= Add($row['state2']); - $out .= Add($row['zip2']); - $out .= Add(""); - $out .= Add(InsType($row['instype2'])); - $out .= Add($row['fname2'] . " " . $row['lname2']); - $out .= Add(ucfirst($row['relationship2'])); - $out .= Add($row['group2']); - $out .= Add($row['policy2']); + $out .= custom_labworks_Add($row['provider2']); + $out .= custom_labworks_Add($row['name2']); + $out .= custom_labworks_Add($row['street12']); + $out .= custom_labworks_Add($row['street22']); + $out .= custom_labworks_Add($row['city2']); + $out .= custom_labworks_Add($row['state2']); + $out .= custom_labworks_Add($row['zip2']); + $out .= custom_labworks_Add(""); + $out .= custom_labworks_Add(InsType($row['instype2'])); + $out .= custom_labworks_Add($row['fname2'] . " " . $row['lname2']); + $out .= custom_labworks_Add(ucfirst($row['relationship2'])); + $out .= custom_labworks_Add($row['group2']); + $out .= custom_labworks_Add($row['policy2']); // Primary Care Physician Section. // - $out .= Add($prow['id']); - $out .= Add($prow['lname']); - $out .= Add($prow['fname']); - $out .= Add(substr($prow['mname'], 0, 1)); - $out .= Add(""); // UPIN not available + $out .= custom_labworks_Add($prow['id']); + $out .= custom_labworks_Add($prow['lname']); + $out .= custom_labworks_Add($prow['fname']); + $out .= custom_labworks_Add(substr($prow['mname'], 0, 1)); + $out .= custom_labworks_Add(""); // UPIN not available // All done. $out .= "\rEND"; diff --git a/custom/export_xml.php b/custom/export_xml.php index d01917c6939c..e47ddf85739a 100644 --- a/custom/export_xml.php +++ b/custom/export_xml.php @@ -21,7 +21,7 @@ $indent = 0; // Add a string to output with some basic sanitizing. -function Add($tag, $text): void +function custom_xml_Add($tag, $text): void { global $out, $indent; $text = trim(str_replace(array("\r", "\n", "\t"), " ", ($text ?? ''))); @@ -84,39 +84,39 @@ function addInsurance($row, $seq): void { if ($row["name$seq"]) { OpenTag("insurance"); - Add("priority", $seq); - Add("group", $row["group$seq"]); - Add("policy", $row["policy$seq"]); - Add("provider", $row["provider$seq"]); - Add("name", $row["name$seq"]); - Add("street1", $row["street1$seq"]); - Add("street2", $row["street2$seq"]); - Add("city", $row["city$seq"]); - Add("state", $row["state$seq"]); - Add("zip", $row["zip$seq"]); - Add("country", $row["country$seq"]); - Add("type", $row["instype$seq"]); - Add("copay", $row["copay$seq"]); + custom_xml_Add("priority", $seq); + custom_xml_Add("group", $row["group$seq"]); + custom_xml_Add("policy", $row["policy$seq"]); + custom_xml_Add("provider", $row["provider$seq"]); + custom_xml_Add("name", $row["name$seq"]); + custom_xml_Add("street1", $row["street1$seq"]); + custom_xml_Add("street2", $row["street2$seq"]); + custom_xml_Add("city", $row["city$seq"]); + custom_xml_Add("state", $row["state$seq"]); + custom_xml_Add("zip", $row["zip$seq"]); + custom_xml_Add("country", $row["country$seq"]); + custom_xml_Add("type", $row["instype$seq"]); + custom_xml_Add("copay", $row["copay$seq"]); OpenTag("subscriber"); - Add("relationship", $row["relationship$seq"]); - Add("lname", $row["lname$seq"]); - Add("fname", $row["fname$seq"]); - Add("mname", $row["mname$seq"]); - Add("street", $row["sstreet$seq"]); - Add("city", $row["scity$seq"]); - Add("state", $row["sstate$seq"]); - Add("zip", $row["szip$seq"]); - Add("country", $row["scountry$seq"]); - Add("dob", $row["sdob$seq"]); - Add("ss", $row["sss$seq"]); - Add("phone", $row["sphone$seq"]); - Add("employer", $row["semployer$seq"]); - Add("sex", $row["ssex$seq"]); - Add("employer_street", $row["semployer_street$seq"]); - Add("employer_city", $row["semployer_city$seq"]); - Add("employer_state", $row["semployer_state$seq"]); - Add("employer_zip", $row["semployer_zip$seq"]); - Add("employer_country", $row["semployer_country$seq"]); + custom_xml_Add("relationship", $row["relationship$seq"]); + custom_xml_Add("lname", $row["lname$seq"]); + custom_xml_Add("fname", $row["fname$seq"]); + custom_xml_Add("mname", $row["mname$seq"]); + custom_xml_Add("street", $row["sstreet$seq"]); + custom_xml_Add("city", $row["scity$seq"]); + custom_xml_Add("state", $row["sstate$seq"]); + custom_xml_Add("zip", $row["szip$seq"]); + custom_xml_Add("country", $row["scountry$seq"]); + custom_xml_Add("dob", $row["sdob$seq"]); + custom_xml_Add("ss", $row["sss$seq"]); + custom_xml_Add("phone", $row["sphone$seq"]); + custom_xml_Add("employer", $row["semployer$seq"]); + custom_xml_Add("sex", $row["ssex$seq"]); + custom_xml_Add("employer_street", $row["semployer_street$seq"]); + custom_xml_Add("employer_city", $row["semployer_city$seq"]); + custom_xml_Add("employer_state", $row["semployer_state$seq"]); + custom_xml_Add("employer_zip", $row["semployer_zip$seq"]); + custom_xml_Add("employer_country", $row["semployer_country$seq"]); CloseTag("subscriber"); CloseTag("insurance"); } @@ -193,45 +193,45 @@ function addInsurance($row, $seq): void // Patient Section. // - Add("pid", $pid); - Add("pubpid", $row['pubpid']); - Add("lname", $row['lname']); - Add("fname", $row['fname']); - Add("mname", $row['mname']); - Add("title", $row['title']); - Add("ss", Digits($row['ss'])); - Add("dob", LWDate($row['DOB'])); - Add("sex", Sex($row['sex'])); - Add("street", $row['street']); - Add("city", $row['city']); - Add("state", $row['state']); - Add("zip", $row['postal_code']); - Add("country", $row['country_code']); - Add("phone_home", Digits($row['phone_home'])); - Add("phone_biz", Digits($row['phone_biz'])); - Add("phone_contact", Digits($row['phone_contact'])); - Add("phone_cell", Digits($row['phone_cell'])); - Add("occupation", $row['occupation']); - Add("status", $row['status']); - Add("contact_relationship", $row['contact_relationship']); - Add("referrer", $row['referrer']); - Add("referrerID", $row['referrerID']); - Add("email", $row['email']); - Add("language", $row['language']); - Add("ethnoracial", $row['ethnoracial']); - Add("interpreter", $row['interpretter']); - Add("migrantseasonal", $row['migrantseasonal']); - Add("family_size", $row['family_size']); - Add("monthly_income", $row['monthly_income']); - Add("homeless", $row['homeless']); - Add("financial_review", LWDate(substr($row['financial_review'], 0, 10))); - Add("genericname1", $row['genericname1']); - Add("genericval1", $row['genericval1']); - Add("genericname2", $row['genericname2']); - Add("genericval2", $row['genericval2']); - Add("billing_note", $row['billing_note']); - Add("hipaa_mail", $row['hipaa_mail']); - Add("hipaa_voice", $row['hipaa_voice']); + custom_xml_Add("pid", $pid); + custom_xml_Add("pubpid", $row['pubpid']); + custom_xml_Add("lname", $row['lname']); + custom_xml_Add("fname", $row['fname']); + custom_xml_Add("mname", $row['mname']); + custom_xml_Add("title", $row['title']); + custom_xml_Add("ss", Digits($row['ss'])); + custom_xml_Add("dob", LWDate($row['DOB'])); + custom_xml_Add("sex", Sex($row['sex'])); + custom_xml_Add("street", $row['street']); + custom_xml_Add("city", $row['city']); + custom_xml_Add("state", $row['state']); + custom_xml_Add("zip", $row['postal_code']); + custom_xml_Add("country", $row['country_code']); + custom_xml_Add("phone_home", Digits($row['phone_home'])); + custom_xml_Add("phone_biz", Digits($row['phone_biz'])); + custom_xml_Add("phone_contact", Digits($row['phone_contact'])); + custom_xml_Add("phone_cell", Digits($row['phone_cell'])); + custom_xml_Add("occupation", $row['occupation']); + custom_xml_Add("status", $row['status']); + custom_xml_Add("contact_relationship", $row['contact_relationship']); + custom_xml_Add("referrer", $row['referrer']); + custom_xml_Add("referrerID", $row['referrerID']); + custom_xml_Add("email", $row['email']); + custom_xml_Add("language", $row['language']); + custom_xml_Add("ethnoracial", $row['ethnoracial']); + custom_xml_Add("interpreter", $row['interpretter']); + custom_xml_Add("migrantseasonal", $row['migrantseasonal']); + custom_xml_Add("family_size", $row['family_size']); + custom_xml_Add("monthly_income", $row['monthly_income']); + custom_xml_Add("homeless", $row['homeless']); + custom_xml_Add("financial_review", LWDate(substr($row['financial_review'], 0, 10))); + custom_xml_Add("genericname1", $row['genericname1']); + custom_xml_Add("genericval1", $row['genericval1']); + custom_xml_Add("genericname2", $row['genericname2']); + custom_xml_Add("genericval2", $row['genericval2']); + custom_xml_Add("billing_note", $row['billing_note']); + custom_xml_Add("hipaa_mail", $row['hipaa_mail']); + custom_xml_Add("hipaa_voice", $row['hipaa_voice']); // Insurance Sections. // @@ -246,10 +246,10 @@ function addInsurance($row, $seq): void $query .= " AND id = ?"; $prow = sqlFetchArray(sqlStatement($query, array($row['providerID']))); OpenTag("pcp"); - Add("id", $prow['id']); - Add("lname", $prow['lname']); - Add("fname", $prow['fname']); - Add("mname", $prow['mname']); + custom_xml_Add("id", $prow['id']); + custom_xml_Add("lname", $prow['lname']); + custom_xml_Add("fname", $prow['fname']); + custom_xml_Add("mname", $prow['mname']); CloseTag("pcp"); } @@ -257,12 +257,12 @@ function addInsurance($row, $seq): void // if (!empty($rowed['id'])) { OpenTag("employer"); - Add("name", $rowed['name']); - Add("street", $rowed['street']); - Add("zip", $rowed['postal_code']); - Add("city", $rowed['city']); - Add("state", $rowed['state']); - Add("country", $rowed['country']); + custom_xml_Add("name", $rowed['name']); + custom_xml_Add("street", $rowed['street']); + custom_xml_Add("zip", $rowed['postal_code']); + custom_xml_Add("city", $rowed['city']); + custom_xml_Add("state", $rowed['state']); + custom_xml_Add("country", $rowed['country']); CloseTag("employer"); } diff --git a/interface/forms/eye_mag/php/eye_mag_functions.php b/interface/forms/eye_mag/php/eye_mag_functions.php index 9e5cd0ed69be..6d506b94e8c8 100644 --- a/interface/forms/eye_mag/php/eye_mag_functions.php +++ b/interface/forms/eye_mag/php/eye_mag_functions.php @@ -1142,47 +1142,47 @@ function display_PRIOR_section($zone, $orig_id, $id_to_show, $pid, $report = '0'
 
-
+
 
 
 
 
 
-
+
 
 
 
 
 
-
+
 
-
+
 
 
 
 
-
+
 
 
 
 
-
+
 
 
 
-
+
 
 
 
-
+
 
 
 
-
+
 
 
@@ -1190,13 +1190,13 @@ function display_PRIOR_section($zone, $orig_id, $id_to_show, $pid, $report = '0'
 
 
 
-
+
 
 
-
+
 
 
-
+
 
 
 
@@ -1218,17 +1218,17 @@ function display_PRIOR_section($zone, $orig_id, $id_to_show, $pid, $report = '0'
 
-
-
-
-
+
+
+
+
 
 
 
-
-
-
-
+
+
+
+
 
@@ -1250,13 +1250,13 @@ function display_PRIOR_section($zone, $orig_id, $id_to_show, $pid, $report = '0'
 
 
 
-
+
 
 
-
+
 
 
-
+
 
 
 
@@ -1264,47 +1264,47 @@ function display_PRIOR_section($zone, $orig_id, $id_to_show, $pid, $report = '0'
 
 
-
+
 
 
 
-
+
 
 
 
-
+
 
 
 
-
+
 
 
 
 
-
+
 
 
 
 
-
+
-
+
 
 
 
 
 
-
+
 
 
 
 
 
-
+
 
@@ -1315,47 +1315,47 @@ function display_PRIOR_section($zone, $orig_id, $id_to_show, $pid, $report = '0'
 
-
+
 
 
 
 
 
-
+
 
 
 
 
 
-
+
 
-
+
 
 
 
 
-
+
 
 
 
 
-
+
 
 
 
-
+
 
 
 
-
+
 
 
 
-
+
 
 
@@ -1363,13 +1363,13 @@ function display_PRIOR_section($zone, $orig_id, $id_to_show, $pid, $report = '0'
 
 
 
-
+
 
 
-
+
 
 
-
+
 
 
 
@@ -1391,17 +1391,17 @@ function display_PRIOR_section($zone, $orig_id, $id_to_show, $pid, $report = '0'
 
-
-
-
-
+
+
+
+
 
 
 
-
-
-
-
+
+
+
+
 
@@ -1423,13 +1423,13 @@ function display_PRIOR_section($zone, $orig_id, $id_to_show, $pid, $report = '0'
 
 
 
-
+
 
 
-
+
 
 
-
+
 
 
 
@@ -1437,48 +1437,48 @@ function display_PRIOR_section($zone, $orig_id, $id_to_show, $pid, $report = '0'
 
 
-
+
 
 
 
-
+
 
 
 
-
+
 
 
 
-
+
 
 
 
 
-
+
 
 
 
 
-
+
 
-
+
 
 
 
 
 
-
+
 
 
 
 
 
-
+
 
@@ -3797,64 +3797,6 @@ function document_engine($pid) } } - if (!$zone['AntSeg Laser']) { - $sql = "select id from categories ORDER by id desc LIMIT 1"; - $last_row = sqlQuery($sql); - $counter = $last_row['id']; - $counter++; - $sql = "INSERT INTO `categories` ( `id`, `name`, `value`, `parent`, `aco_spec`, `codes`) - VALUES (?, 'AntSeg Laser', 'ANTSEG', '14', 'patients|docs', '');"; - sqlStatement($sql, [$counter]); - - $sql = "SELECT * from categories where id = ?"; - $sql2 = sqlStatement($sql, [$counter]); - while ($row1 = sqlFetchArray($sql2)) { - $categories[] = $row1; - $my_name[$row1['id']] = $row1['name']; - $children_names[$row1['parent'] ?? ''][] = $row1['name'] ?? ''; - $parent_name[$row1['name']] = $my_name[$row1['parent']]; - $zones[$row1['value']][] = $row1; - } - } - if (!$zone['Retina Laser']) { - $sql = "select id from categories ORDER by id desc LIMIT 1"; - $last_row = sqlQuery($sql); - $counter = $last_row['id']; - $counter++; - $sql = "INSERT INTO `categories` (`id`, `name`, `value`, `parent`, `aco_spec`, `codes`) - VALUES (?, 'Retina Laser', 'POSTSEG', '14', 'patients|docs', '');"; - sqlStatement($sql, [$counter]); - - $sql = "SELECT * from categories where id = ?"; - $sql2 = sqlStatement($sql, [$counter]); - while ($row1 = sqlFetchArray($sql2)) { - $categories[] = $row1; - $my_name[$row1['id']] = $row1['name']; - $children_names[$row1['parent'] ?? ''][] = $row1['name'] ?? ''; - $parent_name[$row1['name']] = $my_name[$row1['parent']]; - $zones[$row1['value']][] = $row1; - } - } - if (!$zone['Injections']) { - $sql = "select id from categories ORDER by id desc LIMIT 1"; - $last_row = sqlQuery($sql); - $counter = $last_row['id']; - $counter++; - $sql = "INSERT INTO `categories` (`id`, `name`, `value`, `parent`, `aco_spec`, `codes`) - VALUES (?, 'Injections', 'POSTSEG', '14', 'patients|docs', '');"; - sqlStatement($sql, [$counter]); - - $sql = "SELECT * from categories where id = ?"; - $sql2 = sqlStatement($sql, [$counter]); - while ($row1 = sqlFetchArray($sql2)) { - $categories[] = $row1; - $my_name[$row1['id']] = $row1['name']; - $children_names[$row1['parent'] ?? ''][] = $row1['name'] ?? ''; - $parent_name[$row1['name']] = $my_name[$row1['parent']]; - $zones[$row1['value']][] = $row1; - } - } - $query = "Select *, categories.name as cat_name from categories, documents, categories_to_documents @@ -5911,34 +5853,34 @@ function display_VisualAcuities($pid = 0): void foreach ($flip_priors_CC as $prior) { ?> - + - + - + - + - + - + - + - + diff --git a/interface/globals.php b/interface/globals.php index e1809efdc9e5..19f67f42ea48 100644 --- a/interface/globals.php +++ b/interface/globals.php @@ -23,6 +23,8 @@ use OpenEMR\Core\ModulesApplication; use OpenEMR\Common\Logging\EventAuditLogger; use OpenEMR\Common\Session\SessionUtil; +use OpenEMR\Common\Http\HttpRestRequest; +use OpenEMR\Core\OEGlobalsBag; // Throw error if the php openssl module is not installed. if (!(extension_loaded('openssl'))) { @@ -153,6 +155,20 @@ function GetCallingScriptName() * scope of this globals instance. Goal is to unlock session file as quickly as possible * instead of waiting for calling script to complete before releasing flock. */ +if (empty($restRequest)) { + $restRequest = HttpRestRequest::createFromGlobals(); +} +if (empty($globalsBag)) { + $globalsBag = new OeGlobalsBag([], true); +} +$globalsBag->set('webserver_root', $webserver_root); +$globalsBag->set('web_root', $web_root); +$globalsBag->set('vendor_dir', $globalsBag->get('vendor_dir', $GLOBALS['vendor_dir'] ?? null)); +$globalsBag->set('restRequest', $restRequest); +$globalsBag->set('OE_SITES_BASE', $globalsBag->get('OE_SITES_BASE', $GLOBALS['OE_SITES_BASE'] ?? null)); +$globalsBag->set('debug_ssl_mysql_connection', $globalsBag->get('debug_ssl_mysql_connection', $GLOBALS['debug_ssl_mysql_connection'] ?? null)); +$globalsBag->set('eventDispatcher', $eventDispatcher ?? null); +$globalsBag->set('ignoreAuth_onsite_portal', $ignoreAuth_onsite_portal); $read_only = empty($sessionAllowWrite); if (session_status() === PHP_SESSION_NONE) { //error_log("1. LOCK ".GetCallingScriptName()); // debug start lock @@ -170,8 +186,9 @@ function GetCallingScriptName() // mdsupport - Don't die if logout menu link is called from expired session. // Eliminate this code when close method is available for session management. if ((isset($_GET['auth'])) && ($_GET['auth'] == "logout")) { - $GLOBALS['login_screen'] = "login_screen.php"; + $globalsBag->set('login_screen', "login_screen.php"); $srcdir = "../library"; + $globalsBag->set('srcdir', $srcdir); require_once("$srcdir/auth.inc.php"); } die("Site ID is missing from session data!"); @@ -213,59 +230,60 @@ function GetCallingScriptName() } // Set the site-specific directory path. -$GLOBALS['OE_SITE_DIR'] = $GLOBALS['OE_SITES_BASE'] . "/" . $_SESSION['site_id']; +$globalsBag->set('OE_SITE_DIR', $globalsBag->getString('OE_SITES_BASE') . "/" . $_SESSION['site_id']); // Set a site-specific uri root path. -$GLOBALS['OE_SITE_WEBROOT'] = $web_root . "/sites/" . $_SESSION['site_id']; +$globalsBag->set('OE_SITE_WEBROOT', $web_root . "/sites/" . $_SESSION['site_id']); // Root directory, relative to the webserver root: -$GLOBALS['rootdir'] = "$web_root/interface"; -$rootdir = $GLOBALS['rootdir']; +$globalsBag->set('rootdir', "$web_root/interface"); +$rootdir = $globalsBag->getString('rootdir'); // Absolute path to the source code include and headers file directory (Full path): -$GLOBALS['srcdir'] = "$webserver_root/library"; +$globalsBag->set('srcdir', "$webserver_root/library"); // Absolute path to the location of documentroot directory for use with include statements: -$GLOBALS['fileroot'] = "$webserver_root"; +$globalsBag->set('fileroot', $webserver_root); // Absolute path to the location of interface directory for use with include statements: $include_root = "$webserver_root/interface"; +$globalsBag->set('include_root', $include_root); // Absolute path to the location of documentroot directory for use with include statements: -$GLOBALS['webroot'] = $web_root; +$globalsBag->set('webroot', $web_root); // Static assets directory, relative to the webserver root. // (it is very likely that this path will be changed in the future)) -$GLOBALS['assets_static_relative'] = "$web_root/public/assets"; +$globalsBag->set('assets_static_relative', "$web_root/public/assets"); // Relative themes directory, relative to the webserver root. -$GLOBALS['themes_static_relative'] = "$web_root/public/themes"; +$globalsBag->set('themes_static_relative', "$web_root/public/themes"); // Relative images directory, relative to the webserver root. -$GLOBALS['images_static_relative'] = "$web_root/public/images"; +$globalsBag->set('images_static_relative', "$web_root/public/images"); // Static images directory, absolute to the webserver root. -$GLOBALS['images_static_absolute'] = "$webserver_root/public/images"; +$globalsBag->set('images_static_absolute', "$webserver_root/public/images"); -$GLOBALS['template_dir'] = $GLOBALS['fileroot'] . "/templates/"; -$GLOBALS['incdir'] = $include_root; +$globalsBag->set('template_dir', $globalsBag->getString('fileroot') . "/templates/"); +$globalsBag->set('incdir', $include_root); // Location of the login screen file -$GLOBALS['login_screen'] = $GLOBALS['rootdir'] . "/login_screen.php"; +$globalsBag->set('login_screen', $globalsBag->getString('rootdir') . "/login_screen.php"); // Variable set for Eligibility Verification [EDI-271] path -$GLOBALS['edi_271_file_path'] = $GLOBALS['OE_SITE_DIR'] . "/documents/edi/"; +$globalsBag->set('edi_271_file_path', $globalsBag->getString('OE_SITE_DIR') . "/documents/edi/"); // Check necessary writable paths (add them if do not exist) -if (! is_dir($GLOBALS['OE_SITE_DIR'] . '/documents/smarty/gacl')) { - if (!mkdir($concurrentDirectory = $GLOBALS['OE_SITE_DIR'] . '/documents/smarty/gacl', 0755, true) && !is_dir($concurrentDirectory)) { +if (! is_dir($globalsBag->getString('OE_SITE_DIR') . '/documents/smarty/gacl')) { + if (!mkdir($concurrentDirectory = $globalsBag->getString('OE_SITE_DIR') . '/documents/smarty/gacl', 0755, true) && !is_dir($concurrentDirectory)) { throw new RuntimeException(sprintf('Directory "%s" was not created', $concurrentDirectory)); } } -if (! is_dir($GLOBALS['OE_SITE_DIR'] . '/documents/smarty/main')) { - if (!mkdir($concurrentDirectory = $GLOBALS['OE_SITE_DIR'] . '/documents/smarty/main', 0755, true) && !is_dir($concurrentDirectory)) { +if (! is_dir($globalsBag->getString('OE_SITE_DIR') . '/documents/smarty/main')) { + if (!mkdir($concurrentDirectory = $globalsBag->getString('OE_SITE_DIR') . '/documents/smarty/main', 0755, true) && !is_dir($concurrentDirectory)) { throw new RuntimeException(sprintf('Directory "%s" was not created', $concurrentDirectory)); } } // Set and check that necessary writeable path exist for mPDF tool -$GLOBALS['MPDF_WRITE_DIR'] = $GLOBALS['OE_SITE_DIR'] . '/documents/mpdf/pdf_tmp'; +$GLOBALS['MPDF_WRITE_DIR'] = $globalsBag->getString('OE_SITE_DIR') . '/documents/mpdf/pdf_tmp'; if (! is_dir($GLOBALS['MPDF_WRITE_DIR'])) { if (!mkdir($concurrentDirectory = $GLOBALS['MPDF_WRITE_DIR'], 0755, true) && !is_dir($concurrentDirectory)) { throw new RuntimeException(sprintf('Directory "%s" was not created', $concurrentDirectory)); @@ -291,11 +309,14 @@ function GetCallingScriptName() // - DEBUG/INFO are great for development // - INFO/WARN/ERROR are great for production // - TRACE is useful when debugging hard to spot bugs +// @deprecated log_level doesn't appear to be used anywhere $GLOBALS["log_level"] = "OFF"; try { + // we inject the eventDispatcher if we have one setup already + // TODO: @adunsulag is there a better way to do this? /** @var Kernel */ - $GLOBALS["kernel"] = new Kernel(); + $globalsBag->set("kernel", new Kernel($globalsBag->get('eventDispatcher'))); } catch (\Exception $e) { error_log(errorLogEscape($e->getMessage())); die(); @@ -303,9 +324,20 @@ function GetCallingScriptName() // This will open the openemr mysql connection. require_once(__DIR__ . "/../library/sql.inc.php"); +$globalsBag->set("adodb", $GLOBALS['adodb'] ?? null); +$globalsBag->set("dbh", $GLOBALS['dbh'] ?? null); +$globalsBag->set("disable_utf8_flag", $disable_utf8_flag ?? false); // Include the version file require_once(__DIR__ . "/../version.php"); +$globalsBag->set("v_major", $v_major ?? null); +$globalsBag->set("v_minor", $v_minor ?? null); +$globalsBag->set("v_patch", $v_patch ?? null); +$globalsBag->set("v_tag", $v_tag ?? null); +$globalsBag->set("v_realpatch", $v_realpatch ?? null); +$globalsBag->set("v_database", $v_database ?? null); +$globalsBag->set("v_acl", $v_acl ?? null); +$globalsBag->set("v_js_includes", $v_js_includes ?? null); // Collecting the utf8 disable flag from the sqlconf.php file in order // to set the correct html encoding. utf8 vs iso-8859-1. If flag is set @@ -321,12 +353,12 @@ function GetCallingScriptName() } // Defaults for specific applications. -$GLOBALS['weight_loss_clinic'] = false; -$GLOBALS['ippf_specific'] = false; +$globalsBag->set('weight_loss_clinic', false); +$globalsBag->set('ippf_specific', false); // Defaults for drugs and products. -$GLOBALS['inhouse_pharmacy'] = false; -$GLOBALS['sell_non_drug_products'] = 0; +$globalsBag->set('inhouse_pharmacy', false); +$globalsBag->set('sell_non_drug_products', 0); $glrow = sqlQueryNoLog("SHOW TABLES LIKE 'globals'"); if (!empty($glrow)) { @@ -390,11 +422,13 @@ function GetCallingScriptName() if (!file_exists($webserver_root . '/public/themes/' . attr($gl_value))) { $gl_value = 'style_light.css'; } - $GLOBALS[$gl_name] = $web_root . '/public/themes/' . attr($gl_value) . '?v=' . $v_js_includes; - $GLOBALS['compact_header'] = $web_root . '/public/themes/compact_' . attr($gl_value) . '?v=' . $v_js_includes; - $compact_header = $GLOBALS['compact_header']; - $css_header = $GLOBALS[$gl_name]; + $globalsBag->set($gl_name, $web_root . '/public/themes/' . attr($gl_value) . '?v=' . $v_js_includes); + $globalsBag->set('compact_header', $web_root . '/public/themes/compact_' . attr($gl_value) . '?v=' . $v_js_includes); + $compact_header = $globalsBag->getString('compact_header'); + $css_header = $globalsBag->get($gl_name); + $globalsBag->set('css_header', $css_header); $temp_css_theme_name = $gl_value; + $globalsBag->set('temp_css_theme_name', $gl_value); } elseif ($gl_name == 'portal_css_header' && $ignoreAuth_onsite_portal) { // does patient have a portal theme selected? $current_theme = sqlQueryNoLog( @@ -407,22 +441,22 @@ function GetCallingScriptName() $portal_css_header = $GLOBALS[$gl_name]; $portal_temp_css_theme_name = $gl_value; } elseif ($gl_name == 'weekend_days') { - $GLOBALS[$gl_name] = explode(',', $gl_value); + $globalsBag->set($gl_name, explode(',', $gl_value)); } elseif ($gl_name == 'specific_application') { if ($gl_value == '2') { - $GLOBALS['ippf_specific'] = true; + $globalsBag->set('ippf_specific', true); } elseif ($gl_value == '3') { - $GLOBALS['weight_loss_clinic'] = true; + $globalsBag->set('weight_loss_clinic', true); } } elseif ($gl_name == 'inhouse_pharmacy') { if ($gl_value) { - $GLOBALS['inhouse_pharmacy'] = true; + $globalsBag->set('inhouse_pharmacy', true); } if ($gl_value == '2') { - $GLOBALS['sell_non_drug_products'] = 1; + $globalsBag->set('sell_non_drug_products', 1); } elseif ($gl_value == '3') { - $GLOBALS['sell_non_drug_products'] = 2; + $globalsBag->set('sell_non_drug_products', 2); } } elseif ($gl_name == 'gbl_time_zone') { // The default PHP time zone is set here if it was specified, and is used @@ -435,26 +469,26 @@ function GetCallingScriptName() // Synchronize MySQL time zone with PHP time zone. sqlStatementNoLog("SET time_zone = ?", array((new DateTime())->format("P"))); } else { - $GLOBALS[$gl_name] = $gl_value; + $globalsBag->set($gl_name, $gl_value); } } // Set any user settings that are not also in GLOBALS. // This is for modules support. foreach ($gl_user as $setting) { if (!array_key_exists($setting['setting_label'], $GLOBALS)) { - $GLOBALS[$setting['setting_label']] = $setting['setting_value']; + $globalsBag->set($setting['setting_label'], $setting['setting_value']); } } // Language cleanup stuff. - $GLOBALS['language_menu_login'] = false; - if ((!empty($GLOBALS['language_menu_show']) && count($GLOBALS['language_menu_show']) > 1) || $GLOBALS['language_menu_showall']) { - $GLOBALS['language_menu_login'] = true; + $globalsBag->set('language_menu_login', false); + if ((!empty($globalsBag->get('language_menu_show')) && count($globalsBag->get('language_menu_show')) > 1) || $globalsBag->get('language_menu_showall')) { + $globalsBag->set('language_menu_login', true); } // Added this $GLOBALS['concurrent_layout'] set to 3 in order to support legacy forms // that may use this; note this global has been removed from the standard codebase. - $GLOBALS['concurrent_layout'] = 3; + $globalsBag->set('concurrent_layout', 3); // Additional logic to override theme name. // For RTL languages we substitute the theme name with the name of RTL-adapted CSS file. @@ -463,7 +497,7 @@ function GetCallingScriptName() if (isset($_SESSION['language_direction']) && empty($_SESSION['patient_portal_onsite_two'])) { if ( $_SESSION['language_direction'] == 'rtl' && - !strpos($GLOBALS['css_header'], 'rtl') + !strpos($globalsBag->get('css_header', ''), 'rtl') ) { // the $css_header_value is set above $rtl_override = true; @@ -473,7 +507,7 @@ function GetCallingScriptName() $_SESSION['language_direction'] = getLanguageDir($_SESSION['language_choice']); if ( $_SESSION['language_direction'] == 'rtl' && - !strpos($GLOBALS['portal_css_header'], 'rtl') + !strpos($globalsBag->get('portal_css_header', ''), 'rtl') ) { // the $css_header_value is set above $rtl_portal_override = true; @@ -481,7 +515,7 @@ function GetCallingScriptName() } else { //$_SESSION['language_direction'] is not set, so will use the default language $default_lang_id = sqlQueryNoLog('SELECT lang_id FROM lang_languages WHERE lang_description = ?', array($GLOBALS['language_default'] ?? '')); - + $globalsBag->set('default_lang_id', $default_lang_id); if (getLanguageDir($default_lang_id['lang_id'] ?? '') === 'rtl' && !strpos($GLOBALS['css_header'], 'rtl')) { // @todo eliminate 1 SQL query $rtl_override = true; @@ -516,7 +550,8 @@ function GetCallingScriptName() if (file_exists($webserver_root . '/public/themes/' . $new_theme)) { //Escape css file name using 'attr' for security (prevent XSS). $GLOBALS['portal_css_header'] = $web_root . '/public/themes/' . attr($new_theme) . '?v=' . $v_js_includes; - $portal_css_header = $GLOBALS['portal_css_header']; + $globalsBag->set('portal_css_header', $GLOBALS['portal_css_header']); + $portal_css_header = $globalsBag->getString('portal_css_header'); } else { // throw a warning if rtl'ed file does not exist. error_log("Missing theme file " . errorLogEscape($webserver_root) . '/public/themes/' . errorLogEscape($new_theme)); @@ -531,40 +566,44 @@ function GetCallingScriptName() // Temporary stuff to handle the case where the globals table does not // exist yet. This will happen in sql_upgrade.php on upgrading to the // first release containing this table. - $GLOBALS['language_menu_login'] = true; - $GLOBALS['language_menu_showall'] = true; - $GLOBALS['language_menu_show'] = array('English (Standard)','Swedish'); - $GLOBALS['language_default'] = "English (Standard)"; - $GLOBALS['translate_layout'] = true; - $GLOBALS['translate_lists'] = true; - $GLOBALS['translate_gacl_groups'] = true; - $GLOBALS['translate_form_titles'] = true; - $GLOBALS['translate_document_categories'] = true; - $GLOBALS['translate_appt_categories'] = true; - $GLOBALS['timeout'] = 7200; + $globalsBag->set('language_menu_login', true); + $globalsBag->set('language_menu_showall', true); + $globalsBag->set('language_menu_show', array('English (Standard)','Swedish')); + $globalsBag->set('language_default', "English (Standard)"); + $globalsBag->set('translate_layout', true); + $globalsBag->set('translate_lists', true); + $globalsBag->set('translate_gacl_groups', true); + $globalsBag->set('translate_form_titles', true); + $globalsBag->set('translate_document_categories', true); + $globalsBag->set('translate_appt_categories', true); + $globalsBag->set('timeout', 7200); $openemr_name = 'OpenEMR'; $css_header = "$web_root/public/themes/style_default.css"; - $GLOBALS['css_header'] = $css_header; + $globalsBag->set('openemr_name', $openemr_name); + $globalsBag->set('css_header', $css_header); $compact_header = "$web_root/public/themes/style_default.css"; - $GLOBALS['compact_header'] = $compact_header; - $GLOBALS['schedule_start'] = 8; - $GLOBALS['schedule_end'] = 17; - $GLOBALS['calendar_interval'] = 15; - $GLOBALS['phone_country_code'] = '1'; - $GLOBALS['disable_non_default_groups'] = true; - $GLOBALS['ippf_specific'] = false; + $globalsBag->set('compact_header', $compact_header); + $globalsBag->set('schedule_start', 8); + $globalsBag->set('schedule_end', 17); + $globalsBag->set('calendar_interval', 15); + $globalsBag->set('phone_country_code', '1'); + $globalsBag->set('disable_non_default_groups', true); + $globalsBag->set('ippf_specific', false); } // Migrated this to populate after the standard globals in order to support globals that require // more security. -require_once($GLOBALS['OE_SITE_DIR'] . "/config.php"); +require_once($globalsBag->getString('OE_SITE_DIR') . "/config.php"); // Resolve server globals (use the manual override if set already in globals) -if (empty($GLOBALS['site_addr_oath'])) { - $GLOBALS['site_addr_oath'] = $ResolveServerHost(); +if (empty($globalsBag->getString('site_addr_oath'))) { + $globalsBag->set('site_addr_oath', $ResolveServerHost()); } -if (empty($GLOBALS['qualified_site_addr'])) { - $GLOBALS['qualified_site_addr'] = rtrim($GLOBALS['site_addr_oath'] . trim($GLOBALS['webroot']), "/"); +if (empty($globalsBag->getString('qualified_site_addr'))) { + $globalsBag->set( + 'qualified_site_addr', + rtrim($globalsBag->getString('site_addr_oath') . trim($globalsBag->getString('webroot')), "/") + ); } // Need to utilize a session since library/sql.inc.php is established before there are any globals established yet. @@ -573,28 +612,33 @@ function GetCallingScriptName() // Also important to note that changes to this global setting will not take effect during the same // session (ie. user needs to logout) since not worth it to use resources to open session and write to it // for every call to interface/globals.php . -$_SESSION["enable_database_connection_pooling"] = $GLOBALS["enable_database_connection_pooling"] ?? null; +$_SESSION["enable_database_connection_pooling"] = $globalsBag->get("enable_database_connection_pooling", null); // If >0 this will enforce a separate PHP session for each top-level // browser window. You must log in separately for each. This is not // thoroughly tested yet and some browsers might have trouble with it, // so make it 0 if you must. Alternatively, you can set it to 2 to be // notified when the session ID changes. -$GLOBALS['restore_sessions'] = 1; // 0=no, 1=yes, 2=yes+debug +$globalsBag->set('restore_sessions', 1); // 0=no, 1=yes, 2=yes+debug // Theme definition. All this stuff should be moved to CSS. // $top_bg_line = ' bgcolor="#dddddd" '; -$GLOBALS['style']['BGCOLOR2'] = "#dddddd"; +$globalsStyle = $globalsBag->get('style', array()); +$globalsStyle['BGCOLOR2'] = "#dddddd"; +$globalsStyle['BGCOLOR1'] = "#cccccc"; +$globalsBag->set('style', $globalsStyle); $logocode = ""; // optimal size for the tiny logo is height 43 width 86 px // inside the open emr they will be auto reduced $tinylogocode1 = ""; $tinylogocode2 = ""; +$globalsBag->set('logocode', $logocode); +$globalsBag->set('tinylogocode1', $tinylogocode1); +$globalsBag->set('tinylogocode2', $tinylogocode2); -$GLOBALS['style']['BGCOLOR1'] = "#cccccc"; // The height in pixels of the Title bar: -$GLOBALS['titleBarHeight'] = 50; +$globalsBag->set('titleBarHeight', 50); // The assistant word, MORE printed next to titles that can be clicked: // Note this label gets translated here via the xl function @@ -604,39 +648,42 @@ function GetCallingScriptName() // Note this label gets translated here via the xl function // -if you don't want it translated, then strip the xl function away $tback = xl('(Back)'); +$globalsBag->set('tmore', $tmore); +$globalsBag->set('tback', $tback); -$srcdir = $GLOBALS['srcdir']; -$login_screen = $GLOBALS['login_screen']; -$GLOBALS['backpic'] = $backpic ?? ''; +$srcdir = $globalsBag->getString('srcdir'); +$login_screen = $globalsBag->getString('login_screen'); +$globalsBag->set('backpic', $backpic ?? ''); // 1 = send email message to given id for Emergency Login user activation, // else 0. -$GLOBALS['Emergency_Login_email'] = empty($GLOBALS['Emergency_Login_email_id']) ? 0 : 1; +$globalsBag->set('Emergency_Login_email', empty($GLOBALS['Emergency_Login_email_id']) ? 0 : 1); //set include_de_identification to enable De-identification (currently de-identification works fine only with linux machines) //Run de_identification_upgrade.php script to upgrade OpenEMR database to include procedures, //functions, tables for de-identification(Mysql root user and password is required for successful //execution of the de-identification upgrade script) -$GLOBALS['include_de_identification'] = 0; +$globalsBag->set('include_de_identification', 0); // Include the authentication module code here, but the rule is // if the file has the word "login" in the source code file name, // don't include the authentication module - we do this to avoid // include loops. // EMAIL SETTINGS -$GLOBALS['SMTP_Auth'] = !empty($GLOBALS['SMTP_USER']); +$globalsBag->set('SMTP_Auth', !empty($globalsBag->get('SMTP_USER', null))); -if (($ignoreAuth_onsite_portal === true) && ($GLOBALS['portal_onsite_two_enable'] == 1)) { +if (($ignoreAuth_onsite_portal === true) && ($globalsBag->getInt('portal_onsite_two_enable', 0) == 1)) { $ignoreAuth = true; } if (!$ignoreAuth) { require_once("$srcdir/auth.inc.php"); + $globalsBag->set('incoming_site_id', $GLOBALS['incoming_site_id'] ?? null); } // This is the background color to apply to form fields that are searchable. // Currently it is applicable only to the "Search or Add Patient" form. -$GLOBALS['layout_search_color'] = '#ff9919'; +$globalsBag->set('layout_search_color', '#ff9919'); // module configurations // upgrade fails for versions prior to 4.2.0 since no modules table @@ -647,9 +694,9 @@ function GetCallingScriptName() } if (!empty($checkModulesTableExists)) { - $GLOBALS['baseModDir'] = "interface/modules/"; //default path of modules - $GLOBALS['customModDir'] = "custom_modules"; //non zend modules - $GLOBALS['zendModDir'] = "zend_modules"; //zend modules + $globalsBag->set('baseModDir', "interface/modules/"); //default path of modules + $globalsBag->set('customModDir', "custom_modules"); //non zend modules + $globalsBag->set('zendModDir', "zend_modules"); //zend modules try { // load up the modules system and bootstrap them. @@ -657,12 +704,12 @@ function GetCallingScriptName() // registering event listeners, etc. // TODO: why do we have 3 different directories we need to pass in for the zend dir path. shouldn't zendModDir already have all the paths set up? /** @var ModulesApplication */ - $GLOBALS['modules_application'] = new ModulesApplication( - $GLOBALS["kernel"], - $GLOBALS['fileroot'], - $GLOBALS['baseModDir'], - $GLOBALS['zendModDir'] - ); + $globalsBag->set('modules_application', new ModulesApplication( + $globalsBag->get('kernel'), + $globalsBag->getString('fileroot'), + $globalsBag->getString('baseModDir'), + $globalsBag->getString('zendModDir') + )); } catch (\OpenEMR\Common\Acl\AccessDeniedException $accessDeniedException) { // this occurs when the current SCRIPT_PATH is to a module that is not currently allowed to be accessed http_response_code(401); @@ -690,6 +737,12 @@ function GetCallingScriptName() //This is crucial for therapy groups and patients mechanisms to work together properly $attendant_type = (empty($pid) && isset($_SESSION['therapy_group'])) ? 'gid' : 'pid'; $therapy_group = (empty($pid) && isset($_SESSION['therapy_group'])) ? $_SESSION['therapy_group'] : 0; +$globalsBag->set('encounter', $encounter); +$globalsBag->set('pid', $pid); +$globalsBag->set('userauthorized', $userauthorized); +$globalsBag->set('groupname', $groupname); +$globalsBag->set('attendant_type', $attendant_type); +$globalsBag->set('groupname', $groupname); // global interface function to format text length using ellipses function strterm($string, $length) @@ -718,12 +771,14 @@ function UrlIfImageExists($filename, $append = true) } // Override temporary_files_dir -$GLOBALS['temporary_files_dir'] = rtrim(sys_get_temp_dir(), '/'); +$globalsBag->set('temporary_files_dir', rtrim(sys_get_temp_dir(), '/')); error_reporting(error_reporting() & ~E_USER_DEPRECATED & ~E_USER_WARNING); // user debug mode -if (!empty($GLOBALS['user_debug']) && ((int) $GLOBALS['user_debug'] > 1)) { +if ($globalsBag->getInt('user_debug', 0) > 1) { error_reporting(error_reporting() & ~E_WARNING & ~E_NOTICE & ~E_USER_WARNING & ~E_USER_DEPRECATED); ini_set('display_errors', 1); } EventAuditLogger::instance()->logHttpRequest(); + +return $globalsBag; // if anyone wants to use the global bag they can just use the return value diff --git a/interface/main/calendar/add_edit_event.php b/interface/main/calendar/add_edit_event.php index e31d3bb08f42..9115ba09a0f7 100644 --- a/interface/main/calendar/add_edit_event.php +++ b/interface/main/calendar/add_edit_event.php @@ -1067,8 +1067,8 @@ function set_display() { style_prefcat.display = ''; f.form_apptstatus.style.display = 'none'; f.form_prefcat.style.display = ''; - f.form_duration.disabled = true; - f.form_duration.value = ''; + f.form_duration.disabled = false; + f.form_duration.value = 0; document.getElementById('tdallday4').style.color = 'var(--gray)'; } else { style_prefcat.display = 'none'; @@ -1878,6 +1878,7 @@ function are_days_checked(){ * */ var collectvalidation = ; function validateform(event,valu){ + let allDay = document.getElementById('rballday1').checked; collectvalidation.form_hour = { numericality: { onlyInteger: true, @@ -1904,6 +1905,9 @@ function validateform(event,valu){ } }; + if ( allDay == true) { + collectvalidation.form_duration ={}; + } else { collectvalidation.form_duration = { numericality: { onlyInteger: true, @@ -1915,6 +1919,7 @@ function validateform(event,valu){ message: "Duration is required" } }; + } $('#form_save').attr('disabled', true); //Make sure if days_every_week is checked that at least one weekday is checked. diff --git a/interface/modules/custom_modules/oe-module-claimrev-connect/src/Bootstrap.php b/interface/modules/custom_modules/oe-module-claimrev-connect/src/Bootstrap.php index 228a2426fffc..b4b3a0408578 100644 --- a/interface/modules/custom_modules/oe-module-claimrev-connect/src/Bootstrap.php +++ b/interface/modules/custom_modules/oe-module-claimrev-connect/src/Bootstrap.php @@ -333,7 +333,7 @@ public function addApiScope(RestApiScopeEvent $event) $scopes[] = 'user/CustomSkeletonResource.read'; $scopes[] = 'patient/CustomSkeletonResource.read'; // only add system scopes if they are actually enabled - if (\RestConfig::areSystemScopesEnabled()) { + if ($event->isSystemScopesEnabled()) { $scopes[] = 'system/CustomSkeletonResource.read'; } $event->setScopes($scopes); diff --git a/interface/modules/custom_modules/oe-module-faxsms/messageUI.php b/interface/modules/custom_modules/oe-module-faxsms/messageUI.php index 15512d656a0c..6f1e534c28f1 100644 --- a/interface/modules/custom_modules/oe-module-faxsms/messageUI.php +++ b/interface/modules/custom_modules/oe-module-faxsms/messageUI.php @@ -862,7 +862,7 @@ function makeRingoutCall(callTo, callFrom = '', id = '') { $param = ['is_universal' => 1, 'type' => 'email']; $GLOBALS['kernel']->getEventDispatcher()-> dispatch( - new SendNotificationEvent($pid, $param), + new SendNotificationEvent($pid ?? 0, $param), SendNotificationEvent::ACTIONS_RENDER_NOTIFICATION_POST ); ?> diff --git a/interface/smart/admin-client.php b/interface/smart/admin-client.php index 6578f798033f..375e1c35e59a 100644 --- a/interface/smart/admin-client.php +++ b/interface/smart/admin-client.php @@ -12,7 +12,10 @@ */ // need to make sure our autoloader is present. -require_once("../globals.php"); +/** + * @var \OpenEMR\Core\OEGlobalsBag $oeGlobals + */ +$oeGlobals = require_once("../globals.php"); use OpenEMR\Common\Acl\AccessDeniedException; use OpenEMR\Common\Auth\OpenIDConnect\Repositories\ClientRepository; @@ -20,18 +23,26 @@ use OpenEMR\Common\Csrf\CsrfUtils; use OpenEMR\FHIR\SMART\ClientAdminController; use OpenEMR\Common\Logging\SystemLogger; -use OpenEMR\Common\Twig\TwigContainer; use Symfony\Component\HttpFoundation\Request; +use OpenEMR\Common\Http\HttpRestRequest; +use OpenEMR\Common\Http\HttpSessionFactory; -$twig = (new TwigContainer(null, $GLOBALS['kernel']))->getTwig(); -$router = new ClientAdminController(new ClientRepository(), new SystemLogger(), $twig, 'admin-client.php'); try { + // TODO: @adunsulag at some point we'd like to have a CoreApplication like the ApiApplication that will dispatch controllers, refactor this once we have that + $request = HttpRestRequest::createFromGlobals(); + $sessionFactory = new HttpSessionFactory($request, $oeGlobals->getString('web_root'), HttpSessionFactory::SESSION_TYPE_CORE); + $sessionFactory->setUseExistingSessionBridge(true); + $session = $sessionFactory->createSession(); $request = Request::createFromGlobals(); + $router = new ClientAdminController( + $oeGlobals, + $session, + new ClientRepository(), + 'admin-client.php' + ); $response = $router->dispatch($request); - if (isset($response) && $response instanceof \Symfony\Component\HttpFoundation\Response) { - $response->send(); - } + $response->send(); } catch (CsrfInvalidException $exception) { CsrfUtils::csrfNotVerified(); } catch (AccessDeniedException $exception) { diff --git a/interface/smart/register-app.php b/interface/smart/register-app.php index 224fad2ba2d3..4a89901ff261 100644 --- a/interface/smart/register-app.php +++ b/interface/smart/register-app.php @@ -1,7 +1,9 @@ /registeration endpoint. + * TODO: @adunsulag we should twigify this file. * * @package OpenEMR * @link http://www.open-emr.org @@ -31,7 +33,6 @@ // not sure if we need the site id or not... $ignoreAuth = true; require_once("../globals.php"); -require_once("./../../_rest_config.php"); // exit if fhir api is not turned on if (empty($GLOBALS['rest_fhir_api'])) { @@ -70,11 +71,15 @@ // TODO: adunsulag find out where our openemr name comes from $openemr_name = $openemr_name ?? ''; -$scopeRepo = new ScopeRepository(RestConfig::GetInstance()); +$serverConfig = new ServerConfig(); +$fhirRegisterURL = $serverConfig->getRegistrationUrl(); +$audienceUrl = $serverConfig->getFhirUrl(); + +$scopeRepo = new ScopeRepository(); +$scopeRepo->setServerConfig($serverConfig); $scopes = $scopeRepo->getCurrentSmartScopes(); // TODO: adunsulag there's gotta be a better way for this url... -$fhirRegisterURL = AuthorizationController::getAuthBaseFullURL() . AuthorizationController::getRegistrationPath(); -$audienceUrl = (new ServerConfig())->getFhirUrl(); + $dsiService = new DecisionSupportInterventionService(); $evidenceService = $dsiService->getEmptyService(ClientEntity::DSI_TYPE_EVIDENCE); diff --git a/library/classes/Installer.class.php b/library/classes/Installer.class.php index 0a36bfa75d44..88726200936c 100644 --- a/library/classes/Installer.class.php +++ b/library/classes/Installer.class.php @@ -1,17 +1,18 @@ * @author Ranganath Pathak * @author Brady Miller + * @author Michael A. Smith * @copyright Copyright (c) 2010 Andrew Moore * @copyright Copyright (c) 2019 Ranganath Pathak * @copyright Copyright (c) 2019 Brady Miller + * @copyright Copyright (c) 2025 OpenCoreEMR Inc * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ @@ -19,42 +20,48 @@ class Installer { - public $iuser; - public $iuserpass; - public $iuname; - public $iufname; - public $igroup; - public $i2faEnable; - public $i2faSecret; - public $server; - public $loginhost; - public $port; - public $root; - public $rootpass; - public $login; - public $pass; - public $dbname; - public $collate; - public $site; - public $source_site_id; - public $clone_database; - public $no_root_db_access; - public $development_translations; - public $new_theme; - public $ippf_specific; - public $conffile; - public $main_sql; - public $translation_sql; - public $devel_translation_sql; - public $ippf_sql; - public $cvx; - public $additional_users; - public $dumpfiles; - public $error_message; - public $debug_message; - public $dbh; - - public function __construct($cgi_variables) + public array $custom_globals; + public array $dumpfiles; + public mysqli|false $dbh; + public string $additional_users; + public string $clone_database; + public string $collate; + public string $conffile; + public string $cvx; + public string $dbname; + public string $debug_message; + public string $devel_translation_sql; + public string $development_translations; + public string $error_message; + public string $i2faEnable; + public string $i2faSecret; + public string $igroup; + public string $ippf_specific; + public string $ippf_sql; + public string $iufname; + public string $iuname; + public string $iuser; + public string $iuserpass; + public string $login; + public string $loginhost; + public string $main_sql; + public string $new_theme; + public string $no_root_db_access; + public string $pass; + public string $port; + public string $root; + public string $rootpass; + public string $server; + public string $site; + public string $source_site_id; + public string $translation_sql; + + /** + * Initialize the Installer with configuration variables. + * + * @param array $cgi_variables Configuration array containing installation parameters + */ + public function __construct(array $cgi_variables) { // Installation variables // For a good explanation of these variables, see documentation in @@ -81,6 +88,7 @@ public function __construct($cgi_variables) $this->no_root_db_access = isset($cgi_variables['no_root_db_access']) ? ($cgi_variables['no_root_db_access']) : ''; // no root access to database. user/privileges pre-configured $this->development_translations = isset($cgi_variables['development_translations']) ? ($cgi_variables['development_translations']) : ''; $this->new_theme = isset($cgi_variables['new_theme']) ? ($cgi_variables['new_theme']) : ''; + $this->custom_globals = isset($cgi_variables['custom_globals']) ? json_decode($cgi_variables['custom_globals'], true) : []; // Make this true for IPPF. $this->ippf_specific = false; @@ -108,9 +116,14 @@ public function __construct($cgi_variables) $this->dbh = false; } - public function login_is_valid() + /** + * Validate if the database login is valid. + * + * @return bool True if login is valid, false otherwise + */ + public function login_is_valid(): bool { - if (($this->login == '') || (! isset($this->login))) { + if ($this->login === '') { $this->error_message = "login is invalid: '$this->login'"; return false; } @@ -118,10 +131,18 @@ public function login_is_valid() return true; } - public function char_is_valid($input_text) + /** + * Validate if input text contains only safe characters. + * + * Prevents PHP injection by checking for dangerous characters. + * + * @param string $input_text Text to validate + * @return bool True if text is safe, false otherwise + */ + public function char_is_valid(string $input_text): bool { // to prevent php injection - trim($input_text); + $input_text = trim($input_text); if ($input_text == '') { return false; } @@ -133,7 +154,13 @@ public function char_is_valid($input_text) return true; } - public function databaseNameIsValid($name) + /** + * Validate if database name contains only allowed characters. + * + * @param string $name Database name to validate + * @return bool True if name is valid, false otherwise + */ + public function databaseNameIsValid(string $name): bool { if (preg_match('/[^A-Za-z0-9_-]/', $name)) { return false; @@ -141,7 +168,13 @@ public function databaseNameIsValid($name) return true; } - public function collateNameIsValid($name) + /** + * Validate if collation name contains only allowed characters. + * + * @param string $name Collation name to validate + * @return bool True if name is valid, false otherwise + */ + public function collateNameIsValid(string $name): bool { if (preg_match('/[^A-Za-z0-9_-]/', $name)) { return false; @@ -149,7 +182,12 @@ public function collateNameIsValid($name) return true; } - public function iuser_is_valid() + /** + * Validate if the initial user name is valid. + * + * @return bool True if initial user is valid, false otherwise + */ + public function iuser_is_valid(): bool { if (strpos($this->iuser, " ")) { $this->error_message = "Initial user is invalid: '$this->iuser'"; @@ -159,9 +197,14 @@ public function iuser_is_valid() return true; } - public function iuname_is_valid() + /** + * Validate if the initial user last name is valid. + * + * @return bool True if initial user last name is valid, false otherwise + */ + public function iuname_is_valid(): bool { - if ($this->iuname == "" || !isset($this->iuname)) { + if ($this->iuname === '') { $this->error_message = "Initial user last name is invalid: '$this->iuname'"; return false; } @@ -169,9 +212,14 @@ public function iuname_is_valid() return true; } - public function password_is_valid() + /** + * Validate if the database password is valid. + * + * @return bool True if password is valid, false otherwise + */ + public function password_is_valid(): bool { - if ($this->pass == "" || !isset($this->pass)) { + if ($this->pass === '') { $this->error_message = "The password for the new database account is invalid: '$this->pass'"; return false; } @@ -179,9 +227,14 @@ public function password_is_valid() return true; } - public function user_password_is_valid() + /** + * Validate if the initial user password is valid. + * + * @return bool True if user password is valid, false otherwise + */ + public function user_password_is_valid(): bool { - if ($this->iuserpass == "" || !isset($this->iuserpass)) { + if ($this->iuserpass === '') { $this->error_message = "The password for the user is invalid: '$this->iuserpass'"; return false; } @@ -189,9 +242,14 @@ public function user_password_is_valid() return true; } - - - public function root_database_connection() + /** + * Establish a database connection using root credentials. + * + * Connects to the database server using root privileges and sets strict SQL mode. + * + * @return bool True if connection successful, false otherwise + */ + public function root_database_connection(): bool { $this->dbh = $this->connect_to_database($this->server, $this->root, $this->rootpass, $this->port); if ($this->dbh) { @@ -207,7 +265,15 @@ public function root_database_connection() } } - public function user_database_connection() + /** + * Establish a database connection using user credentials. + * + * Connects to the database server using the configured user account, + * sets strict SQL mode, collation, and selects the target database. + * + * @return bool True if connection successful, false otherwise + */ + public function user_database_connection(): bool { $this->dbh = $this->connect_to_database($this->server, $this->login, $this->pass, $this->port, $this->dbname); if (! $this->dbh) { @@ -225,7 +291,7 @@ public function user_database_connection() return false; } - if (! mysqli_select_db($this->dbh, $this->dbname)) { + if (! $this->mysqliSelectDb($this->dbh, $this->dbname)) { $this->error_message = "unable to select database: '$this->dbname'"; return false; } @@ -233,7 +299,15 @@ public function user_database_connection() return true; } - public function create_database() + /** + * Create the target database with UTF8MB4 character set. + * + * Creates the database using the configured name and collation, + * defaulting to utf8mb4_general_ci if not specified. + * + * @return bool True if database creation successful, false otherwise + */ + public function create_database(): bool { $sql = "create database " . $this->escapeDatabaseName($this->dbname); if (empty($this->collate) || ($this->collate == 'utf8_general_ci')) { @@ -245,69 +319,96 @@ public function create_database() return $this->execute_sql($sql); } - public function drop_database() + /** + * Drop the target database if it exists. + * + * @return bool True if database drop successful, false otherwise + */ + public function drop_database(): bool { $sql = "drop database if exists " . $this->escapeDatabaseName($this->dbname); return $this->execute_sql($sql); } - public function create_database_user() + /** + * Create or update the database user account. + * + * Checks if the user exists in mysql.user (or mysql.global_priv for MariaDB 10.4+), + * creates the user if it doesn't exist, or updates the password if it does. + * Supports X509 and SSL connection requirements based on environment variables. + * + * @return mysqli_result|bool Query result or false on error + */ + public function create_database_user(): mysqli_result|bool { + $escapedLogin = $this->escapeSql($this->login); + $escapedHost = $this->escapeSql($this->loginhost); + $escapedPass = $this->escapeSql($this->pass); + // First, check for database user in the mysql.user table (this works for all except mariadb 10.4+) - $checkUser = $this->execute_sql("SELECT user FROM mysql.user WHERE user = '" . $this->escapeSql($this->login) . "' AND host = '" . $this->escapeSql($this->loginhost) . "'", false); + $checkUser = $this->execute_sql("SELECT user FROM mysql.user WHERE user = '{$escapedLogin}' AND host = '{$escapedHost}'", false); if ($checkUser === false) { // Above caused error, so is MariaDB 10.4+, and need to do below query instead in the mysql.global_priv table - $checkUser = $this->execute_sql("SELECT user FROM mysql.global_priv WHERE user = '" . $this->escapeSql($this->login) . "' AND host = '" . $this->escapeSql($this->loginhost) . "'"); + $checkUser = $this->execute_sql("SELECT user FROM mysql.global_priv WHERE user = '{$escapedLogin}' AND host = '{$escapedHost}'"); } if ($checkUser === false) { // there was an error in the check database user query, so return false return false; - } elseif ($checkUser->num_rows > 0) { + } elseif ($this->mysqliNumRows($checkUser) > 0) { // the mysql user already exists, so do not need to create the user, but need to set the password // Note need to try two different methods, first is for newer mysql versions and second is for older mysql versions (if the first method fails) - $returnSql = $this->execute_sql("ALTER USER '" . $this->escapeSql($this->login) . "'@'" . $this->escapeSql($this->loginhost) . "' IDENTIFIED BY '" . $this->escapeSql($this->pass) . "'", false); + $returnSql = $this->execute_sql("ALTER USER '{$escapedLogin}'@'{$escapedHost}' IDENTIFIED BY '{$escapedPass}'", false); if ($returnSql === false) { error_log("Using older mysql version method to set password for the mysql user"); - $returnSql = $this->execute_sql("SET PASSWORD FOR '" . $this->escapeSql($this->login) . "'@'" . $this->escapeSql($this->loginhost) . "' = PASSWORD('" . $this->escapeSql($this->pass) . "')"); + $returnSql = $this->execute_sql("SET PASSWORD FOR '{$escapedLogin}'@'{$escapedHost}' = PASSWORD('{$escapedPass}')"); } return $returnSql; } else { // the mysql user does not yet exist, so create the user if (getenv('FORCE_DATABASE_X509_CONNECT', true) == 1) { // this use case is to allow enforcement of x509 database connection use in applicable docker and kubernetes auto installations - return $this->execute_sql("CREATE USER '" . $this->escapeSql($this->login) . "'@'" . $this->escapeSql($this->loginhost) . "' IDENTIFIED BY '" . $this->escapeSql($this->pass) . "' REQUIRE X509"); + return $this->execute_sql("CREATE USER '{$escapedLogin}'@'{$escapedHost}' IDENTIFIED BY '{$escapedPass}' REQUIRE X509"); } elseif (getenv('FORCE_DATABASE_SSL_CONNECT', true) == 1) { // this use case is to allow enforcement of ssl database connection use in applicable docker and kubernetes auto installations - return $this->execute_sql("CREATE USER '" . $this->escapeSql($this->login) . "'@'" . $this->escapeSql($this->loginhost) . "' IDENTIFIED BY '" . $this->escapeSql($this->pass) . "' REQUIRE SSL"); + return $this->execute_sql("CREATE USER '{$escapedLogin}'@'{$escapedHost}' IDENTIFIED BY '{$escapedPass}' REQUIRE SSL"); } else { - return $this->execute_sql("CREATE USER '" . $this->escapeSql($this->login) . "'@'" . $this->escapeSql($this->loginhost) . "' IDENTIFIED BY '" . $this->escapeSql($this->pass) . "'"); + return $this->execute_sql("CREATE USER '{$escapedLogin}'@'{$escapedHost}' IDENTIFIED BY '{$escapedPass}'"); } } } - public function grant_privileges() + /** + * Grant all privileges on the database to the user account. + * + * @return bool True if privileges granted successfully, false otherwise + */ + public function grant_privileges(): bool { return $this->execute_sql("GRANT ALL PRIVILEGES ON " . $this->escapeDatabaseName($this->dbname) . ".* TO '" . $this->escapeSql($this->login) . "'@'" . $this->escapeSql($this->loginhost) . "'"); } - public function disconnect() - { - return mysqli_close($this->dbh); - } - /** * This method creates any dumpfiles necessary. * This is actually only done if we're cloning an existing site * and we need to dump their database into a file. - * @return bool indicating success + * + * @return string name of the backup file */ - public function create_dumpfiles() + public function create_dumpfiles(): string { return $this->dumpSourceDatabase(); } - public function load_dumpfiles() + /** + * Load all configured database dump files. + * + * Iterates through the list of dump files and loads each one, + * accumulating results and returning combined output. + * + * @return string|false Combined results from all loaded files, or false on error + */ + public function load_dumpfiles(): string|false { $sql_results = ''; // information string which is returned foreach ($this->dumpfiles as $filename => $title) { @@ -323,11 +424,22 @@ public function load_dumpfiles() return $sql_results; } - public function load_file($filename, $title) + /** + * Load and execute SQL commands from a database dump file. + * + * Opens the specified file, reads it line by line, and executes + * SQL statements. Uses transactions for improved performance with InnoDB. + * Ignores comment lines starting with -- or #. + * + * @param string $filename Path to the SQL dump file + * @param string $title Descriptive title for the operation + * @return string|false Success message or false on error + */ + public function load_file(string $filename, string $title): string|false { $sql_results = ''; // information string which is returned $sql_results .= "Creating $title tables...\n"; - $fd = fopen($filename, 'r'); + $fd = $this->openFile($filename, 'r'); if ($fd == false) { $this->error_message = "ERROR. Could not open dumpfile '$filename'.\n"; return false; @@ -345,30 +457,22 @@ public function load_file($filename, $title) return false; } - while (!feof($fd)) { - $line = fgets($fd, 1024); + while (!$this->atEndOfFile($fd)) { + $line = $this->getLine($fd, 1024); $line = rtrim($line); - if (substr($line, 0, 2) == "--") { // Kill comments - continue; - } - - if (substr($line, 0, 1) == "#") { // Kill comments - continue; - } - - if ($line == "") { - continue; + if ($line === "" || substr($line, 0, 2) === "--" || substr($line, 0, 1) === "#") { + continue; } $query .= $line; // Check for full query $chr = substr($query, strlen($query) - 1, 1); if ($chr == ";") { // valid query, execute - $query = rtrim($query, ";"); + $query = rtrim($query, ";"); if (! $this->execute_sql($query)) { return false; } - $query = ""; + $query = ""; } } @@ -382,11 +486,19 @@ public function load_file($filename, $title) } $sql_results .= "OK.
\n"; - fclose($fd); + $this->closeFile($fd); return $sql_results; } - public function add_version_info() + /** + * Add version information to the database. + * + * Loads version constants from version.php and updates the version table + * with current OpenEMR version information. + * + * @return bool True if version info added successfully, false otherwise + */ + public function add_version_info(): bool { include __DIR__ . "/../../version.php"; /** @@ -421,44 +533,57 @@ public function add_version_info() return true; } $this->error_message = "ERROR. Unable insert version information into database\n" . - "

" . mysqli_error($this->dbh) . " (#" . mysqli_errno($this->dbh) . ")\n"; + "

" . $this->mysqliError($this->dbh) . " (#" . $this->mysqliErrno($this->dbh) . ")\n"; return false; } - public function add_initial_user() + /** + * Add the initial administrator user to the database. + * + * Creates the initial user group, user account, secure password hash, + * and optionally sets up 2FA if enabled during installation. + * + * @return bool True if initial user added successfully, false otherwise + */ + public function add_initial_user(): bool { - if ($this->execute_sql("INSERT INTO `groups` (id, name, user) VALUES (1,'" . $this->escapeSql($this->igroup) . "','" . $this->escapeSql($this->iuser) . "')") == false) { + $escapedGroup = $this->escapeSql($this->igroup); + $escapedUser = $this->escapeSql($this->iuser); + $escapedFirstName = $this->escapeSql($this->iufname); + $escapedLastName = $this->escapeSql($this->iuname); + if ($this->execute_sql("INSERT INTO `groups` (id, name, user) VALUES (1,'{$escapedGroup}', '{$escapedUser}')") == false) { $this->error_message = "ERROR. Unable to add initial user group\n" . - "

" . mysqli_error($this->dbh) . " (#" . mysqli_errno($this->dbh) . ")\n"; + "

" . $this->mysqliError($this->dbh) . " (#" . $this->mysqliErrno($this->dbh) . ")\n"; return false; } - if ($this->execute_sql("INSERT INTO users (id, username, password, authorized, lname, fname, facility_id, calendar, cal_ui) VALUES (1,'" . $this->escapeSql($this->iuser) . "','NoLongerUsed',1,'" . $this->escapeSql($this->iuname) . "','" . $this->escapeSql($this->iufname) . "',3,1,3)") == false) { + if ($this->execute_sql("INSERT INTO users (id, username, password, authorized, lname, fname, facility_id, calendar, cal_ui) VALUES (1,'{$escapedUser}','NoLongerUsed',1,'{$escapedLastName}','{$escapedFirstName}',3,1,3)") == false) { $this->error_message = "ERROR. Unable to add initial user\n" . - "

" . mysqli_error($this->dbh) . " (#" . mysqli_errno($this->dbh) . ")\n"; + "

" . $this->mysqliError($this->dbh) . " (#" . $this->mysqliErrno($this->dbh) . ")\n"; return false; } $hash = password_hash($this->iuserpass, PASSWORD_DEFAULT); + $escapedHash = $this->escapeSql($hash); if (empty($hash)) { // Something is seriously wrong error_log('OpenEMR Error : OpenEMR is not working because unable to create a hash.'); - die("OpenEMR Error : OpenEMR is not working because unable to create a hash."); + $this->die("OpenEMR Error : OpenEMR is not working because unable to create a hash."); } - if ($this->execute_sql("INSERT INTO users_secure (id, username, password, last_update_password) VALUES (1,'" . $this->escapeSql($this->iuser) . "','" . $this->escapeSql($hash) . "',NOW())") == false) { + if ($this->execute_sql("INSERT INTO users_secure (id, username, password, last_update_password) VALUES (1,'{$escapedUser}','{$escapedHash}',NOW())") == false) { $this->error_message = "ERROR. Unable to add initial user login credentials\n" . - "

" . mysqli_error($this->dbh) . " (#" . mysqli_errno($this->dbh) . ")\n"; + "

" . $this->mysqliError($this->dbh) . " (#" . $this->mysqliErrno($this->dbh) . ")\n"; return false; } // Create new 2fa if enabled - if (($this->i2faEnable) && (!empty($this->i2faSecret)) && (class_exists('Totp')) && (class_exists('OpenEMR\Common\Crypto\CryptoGen'))) { + if (($this->i2faEnable) && (!empty($this->i2faSecret)) && $this->totpClassExists() && $this->cryptoGenClassExists()) { // Encrypt the new secret with the hashed password - $cryptoGen = new OpenEMR\Common\Crypto\CryptoGen(); - $secret = $cryptoGen->encryptStandard($this->i2faSecret, $hash); - if ($this->execute_sql("INSERT INTO login_mfa_registrations (user_id, name, method, var1, var2) VALUES (1, 'App Based 2FA', 'TOTP', '" . $this->escapeSql($secret) . "', '')") == false) { + $secret = $this->encryptTotpSecret($this->i2faSecret, $hash); + $escapedSecret = $this->escapeSql($secret); + if ($this->execute_sql("INSERT INTO login_mfa_registrations (user_id, name, method, var1, var2) VALUES (1, 'App Based 2FA', 'TOTP', '{$escapedSecret}', '')") == false) { $this->error_message = "ERROR. Unable to add initial user's 2FA credentials\n" . - "

" . mysqli_error($this->dbh) . " (#" . mysqli_errno($this->dbh) . ")\n"; + "

" . $this->mysqliError($this->dbh) . " (#" . $this->mysqliErrno($this->dbh) . ")\n"; return false; } } @@ -468,9 +593,10 @@ public function add_initial_user() /** * Handle the additional users now that our gacl's have finished installing. + * * @return bool */ - public function install_additional_users() + public function install_additional_users(): bool { // Add the official openemr users (services) if ($this->load_file($this->additional_users, "Additional Official Users") == false) { @@ -479,10 +605,18 @@ public function install_additional_users() return true; } - public function on_care_coordination() + /** + * Configure Care Coordination module ACL permissions. + * + * Sets up module access control by linking the Carecoordination module + * to the admin group with appropriate permissions. + * + * @return bool True if configuration successful, false otherwise + */ + public function on_care_coordination(): bool { $resource = $this->execute_sql("SELECT `mod_id` FROM `modules` WHERE `mod_name` = 'Carecoordination' LIMIT 1"); - $resource_array = mysqli_fetch_array($resource, MYSQLI_ASSOC); + $resource_array = $this->mysqliFetchArray($resource, MYSQLI_ASSOC); $modId = $resource_array['mod_id']; if (empty($modId)) { $this->error_message = "ERROR configuring Care Coordination module. Unable to get mod_id for Carecoordination module\n"; @@ -490,7 +624,7 @@ public function on_care_coordination() } $resource = $this->execute_sql("SELECT `section_id` FROM `module_acl_sections` WHERE `section_identifier` = 'carecoordination' LIMIT 1"); - $resource_array = mysqli_fetch_array($resource, MYSQLI_ASSOC); + $resource_array = $this->mysqliFetchArray($resource, MYSQLI_ASSOC); $sectionId = $resource_array['section_id']; if (empty($sectionId)) { $this->error_message = "ERROR configuring Care Coordination module. Unable to get section_id for carecoordination module section\n"; @@ -498,7 +632,7 @@ public function on_care_coordination() } $resource = $this->execute_sql("SELECT `id` FROM `gacl_aro_groups` WHERE `value` = 'admin' LIMIT 1"); - $resource_array = mysqli_fetch_array($resource, MYSQLI_ASSOC); + $resource_array = $this->mysqliFetchArray($resource, MYSQLI_ASSOC); $groupId = $resource_array['id']; if (empty($groupId)) { $this->error_message = "ERROR configuring Care Coordination module. Unable to get id for gacl_aro_groups admin section\n"; @@ -515,25 +649,26 @@ public function on_care_coordination() /** * Generates the initial user's 2FA QR Code - * @return bool|string|void + * + * @return Totp|false */ - public function get_initial_user_mfa_totp() + public function get_initial_user_mfa_totp(): Totp|false { - if (($this->i2faEnable) && (!empty($this->i2faSecret)) && (class_exists('Totp'))) { - $adminTotp = new Totp($this->i2faSecret, $this->iuser); - return $adminTotp; + if (($this->i2faEnable) && (!empty($this->i2faSecret)) && $this->totpClassExists()) { + return $this->createTotpInstance($this->i2faSecret, $this->iuser); } return false; } /** * Create site directory if it is missing. + * * @global string $GLOBALS['OE_SITE_DIR'] contains the name of the site directory to create - * @return name of the site directory or False + * @return bool true if the site directory was created or false if it already exists */ - public function create_site_directory() + public function create_site_directory(): bool { - if (!file_exists($GLOBALS['OE_SITE_DIR'])) { + if (!$this->fileExists($GLOBALS['OE_SITE_DIR'])) { $source_directory = $GLOBALS['OE_SITES_BASE'] . "/" . $this->source_site_id; $destination_directory = $GLOBALS['OE_SITE_DIR']; if (! $this->recurse_copy($source_directory, $destination_directory)) { @@ -542,20 +677,31 @@ public function create_site_directory() } // the new site will create it's own keys so okay to delete these copied from the source site if (!$this->clone_database) { - array_map('unlink', glob($destination_directory . "/documents/logs_and_misc/methods/*")); + $files = $this->globPattern($destination_directory . "/documents/logs_and_misc/methods/*"); + if ($files !== false) { + array_map([$this, 'unlinkFile'], $files); + } } } return true; } - public function write_configuration_file() + /** + * Write the database configuration file (sqlconf.php). + * + * Creates the site directory if needed and writes the database + * connection configuration to the sqlconf.php file. + * + * @return bool True if configuration written successfully, false otherwise + */ + public function write_configuration_file(): bool { - if (!file_exists($GLOBALS['OE_SITE_DIR'])) { + if (!$this->fileExists($GLOBALS['OE_SITE_DIR'])) { $this->create_site_directory(); } - @touch($this->conffile); // php bug - $fd = @fopen($this->conffile, 'w'); + @$this->touchFile($this->conffile); // php bug + $fd = @$this->openFile($this->conffile, 'w'); if (! $fd) { $this->error_message = 'unable to open configuration file for writing: ' . $this->conffile; return false; @@ -569,15 +715,15 @@ public function write_configuration_file() $it_died = 0; //fmg: variable keeps running track of any errors - fwrite($fd, $string) or $it_died++; - fwrite($fd, "global \$disable_utf8_flag;\n") or $it_died++; - fwrite($fd, "\$disable_utf8_flag = false;\n\n") or $it_died++; - fwrite($fd, "\$host\t= '$this->server';\n") or $it_died++; - fwrite($fd, "\$port\t= '$this->port';\n") or $it_died++; - fwrite($fd, "\$login\t= '$this->login';\n") or $it_died++; - fwrite($fd, "\$pass\t= '$this->pass';\n") or $it_died++; - fwrite($fd, "\$dbase\t= '$this->dbname';\n") or $it_died++; - fwrite($fd, "\$db_encoding\t= 'utf8mb4';\n") or $it_died++; + $this->writeToFile($fd, $string) or $it_died++; + $this->writeToFile($fd, "global \$disable_utf8_flag;\n") or $it_died++; + $this->writeToFile($fd, "\$disable_utf8_flag = false;\n\n") or $it_died++; + $this->writeToFile($fd, "\$host\t= '$this->server';\n") or $it_died++; + $this->writeToFile($fd, "\$port\t= '$this->port';\n") or $it_died++; + $this->writeToFile($fd, "\$login\t= '$this->login';\n") or $it_died++; + $this->writeToFile($fd, "\$pass\t= '$this->pass';\n") or $it_died++; + $this->writeToFile($fd, "\$dbase\t= '$this->dbname';\n") or $it_died++; + $this->writeToFile($fd, "\$db_encoding\t= 'utf8mb4';\n") or $it_died++; $string = ' $sqlconf = array(); @@ -600,8 +746,8 @@ public function write_configuration_file() ?> '; - fwrite($fd, $string) or $it_died++; - fclose($fd) or $it_died++; + $this->writeToFile($fd, $string) or $it_died++; + $this->closeFile($fd) or $it_died++; //it's rather irresponsible to not report errors when writing this file. if ($it_died != 0) { @@ -610,14 +756,24 @@ public function write_configuration_file() } // Tell PHP that its cached bytecode version of sqlconf.php is no longer usable. + // @codeCoverageIgnoreStart if (function_exists('opcache_invalidate')) { opcache_invalidate($this->conffile, true); } + // @codeCoverageIgnoreEnd return true; } - public function insert_globals() + /** + * Insert global configuration settings into the database. + * + * Loads the global settings metadata and inserts default values + * into the globals table for system configuration. + * + * @return true Always returns true + */ + public function insert_globals(): true { $GLOBALS['temp_skip_translations'] = true; $skipGlobalEvent = true; // use in globals.inc.php script to skip event stuff @@ -627,12 +783,7 @@ public function insert_globals() foreach ($grparr as $fldid => $fldarr) { list($fldname, $fldtype, $flddef, $flddesc) = $fldarr; if (is_array($fldtype) || substr($fldtype, 0, 2) !== 'm_') { - $res = $this->execute_sql("SELECT count(*) AS count FROM globals WHERE gl_name = '" . $this->escapeSql($fldid) . "'"); - $row = mysqli_fetch_array($res, MYSQLI_ASSOC); - if (empty($row['count'])) { - $this->execute_sql("INSERT INTO globals ( gl_name, gl_index, gl_value ) " . - "VALUES ( '" . $this->escapeSql($fldid) . "', '0', '" . $this->escapeSql($flddef) . "' )"); - } + $this->writeGlobal($fldid, $flddef, 0, true); } } } @@ -640,13 +791,76 @@ public function insert_globals() return true; } - public function install_gacl() + /** + * Write a global setting to the database + * + * @param string $name Global name + * @param string $value Global value + * @param int $index Global index (default: 0) + * @param bool $insert_only If true, only insert if not exists; if false, use REPLACE INTO (default: false) + * @return bool True on success, false on failure + */ + protected function writeGlobal(string $name, string $value, int $index = 0, bool $insert_only = false): bool { + $expression = "%s INTO globals ( gl_name, gl_index, gl_value ) VALUES ( '%s', '%d', '%s' )"; + if ($insert_only) { + $check_sql = "SELECT count(*) AS count FROM globals WHERE gl_name = '%s'"; + $sql = sprintf($check_sql, $this->escapeSql($name)); + $res = $this->execute_sql($sql); + $row = $this->mysqliFetchArray($res, MYSQLI_ASSOC); + + if (!empty($row['count'])) { + return true; // Already exists, skip + } - $gacl = new GaclApi(); + $sql = sprintf($expression, 'INSERT', $this->escapeSql($name), $index, $this->escapeSql($value)); + } else { + $sql = sprintf($expression, 'REPLACE', $this->escapeSql($name), $index, $this->escapeSql($value)); + } + + return $this->execute_sql($sql) !== false; + } + + /** + * Add arbitrary custom globals to the database after insert_globals + * + * @param array $new_globals Associative array where keys are global names and values are configuration arrays. + * Each configuration array can contain: + * - 'value' (string): The global value (default: '') + * - 'index' (int): The global index (default: 0) + * @return bool True on success, false on failure + */ + public function upsertCustomGlobals(array $new_globals): bool + { + foreach ($new_globals as $global_name => $global_config) { + if (!is_array($global_config) || empty($global_name)) { + continue; + } + + $global_value = isset($global_config['value']) ? $global_config['value'] : ''; + $global_index = isset($global_config['index']) ? intval($global_config['index']) : 0; + + if (!$this->writeGlobal($global_name, $global_value, $global_index, false)) { + return false; + } + } + + return true; + } + + /** + * Install the Generic Access Control List (GACL) system. + * + * Creates all access control objects (ACOs), sections, and groups + * needed for OpenEMR's role-based access control system. + * + * @return bool True if GACL installation successful, false otherwise + */ + public function install_gacl(): bool + { + $gacl = $this->newGaclApi(); // Create the ACO sections. Every ACO must have a section. - // if ($gacl->add_object_section('Accounting', 'acct', 10, 0, 'ACO') === false) { $this->error_message = "ERROR, Unable to create the access controls for OpenEMR."; return false; @@ -678,7 +892,6 @@ public function install_gacl() // xl('Inventory') // Create Accounting ACOs. - // $gacl->add_object('acct', 'Billing (write optional)', 'bill', 10, 0, 'ACO'); // xl('Billing (write optional)') $gacl->add_object('acct', 'Price Discounting', 'disc', 10, 0, 'ACO'); @@ -691,7 +904,6 @@ public function install_gacl() // xl('Financial Reporting - anything') // Create Administration ACOs. - // $gacl->add_object('admin', 'Superuser', 'super', 10, 0, 'ACO'); // xl('Superuser') $gacl->add_object('admin', 'Calendar Settings', 'calendar', 10, 0, 'ACO'); @@ -723,7 +935,6 @@ public function install_gacl() // Create ACOs for encounters. - // $gacl->add_object('encounters', 'Authorize - my encounters', 'auth', 10, 0, 'ACO'); // xl('Authorize - my encounters') $gacl->add_object('encounters', 'Authorize - any encounters', 'auth_a', 10, 0, 'ACO'); @@ -738,11 +949,10 @@ public function install_gacl() // xl('Notes - any encounters (write,addonly optional)') $gacl->add_object('encounters', 'Fix encounter dates - any encounters', 'date_a', 10, 0, 'ACO'); // xl('Fix encounter dates - any encounters') - $gacl->add_object('encounters', 'Less-private information (write,addonly optional)', 'relaxed', 10, 0, 'ACO'); - // xl('Less-private information (write,addonly optional)') + $gacl->add_object('encounters', 'Less-protected information (write,addonly optional)', 'relaxed', 10, 0, 'ACO'); + // xl('Less-protected information (write,addonly optional)') // Create ACOs for lists. - // $gacl->add_object('lists', 'Default List (write,addonly optional)', 'default', 10, 0, 'ACO'); // xl('Default List (write,addonly optional)') $gacl->add_object('lists', 'State List (write,addonly optional)', 'state', 10, 0, 'ACO'); @@ -755,17 +965,14 @@ public function install_gacl() // xl('Ethnicity-Race List (write,addonly optional)') // Create ACOs for patientportal. - // $gacl->add_object('patientportal', 'Patient Portal', 'portal', 10, 0, 'ACO'); // xl('Patient Portal') // Create ACOs for modules. - // $gacl->add_object('menus', 'Modules', 'modle', 10, 0, 'ACO'); // xl('Modules') // Create ACOs for patients. - // $gacl->add_object('patients', 'Appointments (write,wsome optional)', 'appt', 10, 0, 'ACO'); // xl('Appointments (write,wsome optional)') $gacl->add_object('patients', 'Demographics (write,addonly optional)', 'demo', 10, 0, 'ACO'); @@ -810,24 +1017,20 @@ public function install_gacl() // xl('Send message from the permanent group therapist to the personal therapist') // Create ACOs for sensitivities. - // $gacl->add_object('sensitivities', 'Normal', 'normal', 10, 0, 'ACO'); // xl('Normal') $gacl->add_object('sensitivities', 'High', 'high', 20, 0, 'ACO'); // xl('High') // Create ACO for placeholder. - // $gacl->add_object('placeholder', 'Placeholder (Maintains empty ACLs)', 'filler', 10, 0, 'ACO'); // xl('Placeholder (Maintains empty ACLs)') // Create ACO for nationnotes. - // $gacl->add_object('nationnotes', 'Nation Notes Configure', 'nn_configure', 10, 0, 'ACO'); // xl('Nation Notes Configure') // Create ACOs for Inventory. - // $gacl->add_object('inventory', 'Lots', 'lots', 10, 0, 'ACO'); // xl('Lots') $gacl->add_object('inventory', 'Sales', 'sales', 20, 0, 'ACO'); @@ -846,7 +1049,6 @@ public function install_gacl() // xl('Reporting') // Create ARO groups. - // $users = $gacl->add_group('users', 'OpenEMR Users', 0, 'ARO'); // xl('OpenEMR Users') $admin = $gacl->add_group('admin', 'Administrators', $users, 'ARO'); @@ -864,7 +1066,6 @@ public function install_gacl() // Create a Users section for the AROs (humans). - // $gacl->add_object_section('Users', 'users', 10, 0, 'ARO'); // xl('Users') @@ -873,19 +1074,13 @@ public function install_gacl() // If this script is being used by OpenEMR's setup, then will // incorporate the installation values. Otherwise will // hardcode the 'admin' user. - if (isset($this->iuser)) { - $gacl->add_object('users', $this->iuname, $this->iuser, 10, 0, 'ARO'); - $gacl->add_group_object($admin, 'users', $this->iuser, 'ARO'); - } else { - $gacl->add_object('users', 'Administrator', 'admin', 10, 0, 'ARO'); - $gacl->add_group_object($admin, 'users', 'admin', 'ARO'); - } + $gacl->add_object('users', $this->iuname, $this->iuser, 10, 0, 'ARO'); + $gacl->add_group_object($admin, 'users', $this->iuser, 'ARO'); // Declare return terms for language translations // xl('write') xl('wsome') xl('addonly') xl('view') // Set permissions for administrators. - // $gacl->add_acl( array( 'acct' => array('bill', 'disc', 'eob', 'rep', 'rep_a'), @@ -912,7 +1107,6 @@ public function install_gacl() // xl('Administrators can do anything') // Set permissions for physicians. - // $gacl->add_acl( array( 'patients' => array('pat_rep') @@ -977,7 +1171,6 @@ public function install_gacl() // xl('Things that physicians can read and modify') // Set permissions for clinicians. - // $gacl->add_acl( array( 'patients' => array('pat_rep') @@ -1041,7 +1234,6 @@ public function install_gacl() // xl('Things that clinicians can read and modify') // Set permissions for front office staff. - // $gacl->add_acl( array( 'patients' => array('alert') @@ -1101,7 +1293,6 @@ public function install_gacl() // xl('Things that front office can read and modify') // Set permissions for back office staff. - // $gacl->add_acl( array( 'patients' => array('alert') @@ -1163,7 +1354,6 @@ public function install_gacl() // xl('Things that back office can read and modify') // Set permissions for Emergency Login. - // $gacl->add_acl( array( 'acct' => array('bill', 'disc', 'eob', 'rep', 'rep_a'), @@ -1192,7 +1382,16 @@ public function install_gacl() return true; } - public function quick_install() + /** + * Perform a complete OpenEMR installation process. + * + * Orchestrates the entire installation by validating settings, + * creating databases and users, loading SQL files, configuring + * access controls, and setting up the initial system state. + * + * @return bool True if installation completed successfully, false otherwise + */ + public function quick_install(): bool { // Validation of OpenEMR user settings // (applicable if not cloning from another database) @@ -1290,7 +1489,7 @@ public function quick_install() // Load the version information, globals settings, // initial user, and set up gacl access controls. - // (applicable if not cloning from another database) + // (applicable if not cloning from another database) if (empty($this->clone_database)) { if (! $this->add_version_info()) { return false; @@ -1300,6 +1499,10 @@ public function quick_install() return false; } + if (is_array($this->custom_globals) && ! $this->upsertCustomGlobals($this->custom_globals)) { + return false; + } + if (! $this->add_initial_user()) { return false; } @@ -1320,30 +1523,51 @@ public function quick_install() return true; } - private function escapeSql($sql) - { - return mysqli_real_escape_string($this->dbh, $sql); - } - - private function escapeDatabaseName($name) + /** + * Validate and escape database name. + * + * Ensures database name contains only safe characters. + * + * @param string $name Database name to validate + * @return string Validated database name + * @throws void Dies if invalid characters found + */ + protected function escapeDatabaseName(string $name): string { if (preg_match('/[^A-Za-z0-9_-]/', $name)) { - error_log("Illegal character(s) in database name"); - die("Illegal character(s) in database name"); + $this->die("Illegal character(s) in database name"); } return $name; } - private function escapeCollateName($name) + /** + * Validate and escape collation name. + * + * Ensures collation name contains only safe characters. + * + * @param string $name Collation name to validate + * @return string Validated collation name + * @throws void Dies if invalid characters found + */ + protected function escapeCollateName(string $name): string { if (preg_match('/[^A-Za-z0-9_-]/', $name)) { - error_log("Illegal character(s) in collation name"); - die("Illegal character(s) in collation name"); + $this->die("Illegal character(s) in collation name"); } return $name; } - private function execute_sql($sql, $showError = true) + /** + * Execute SQL query with error handling. + * + * Executes a SQL query against the database connection, + * with optional error reporting and logging. + * + * @param string $sql SQL query to execute + * @param bool $showError Whether to log/display errors + * @return mysqli_result|bool Query result or false on error + */ + protected function execute_sql(string $sql, bool $showError = true): mysqli_result|bool { $this->error_message = ''; if (! $this->dbh) { @@ -1351,12 +1575,12 @@ private function execute_sql($sql, $showError = true) } try { - $results = mysqli_query($this->dbh, $sql); + $results = $this->mysqliQuery($this->dbh, $sql); if ($results) { return $results; } else { if ($showError) { - $error_mes = mysqli_error($this->dbh); + $error_mes = $this->mysqliError($this->dbh); $this->error_message = "unable to execute SQL: '$sql' due to: " . $error_mes; error_log("ERROR IN OPENEMR INSTALL: Unable to execute SQL: " . htmlspecialchars($sql, ENT_QUOTES) . " due to: " . htmlspecialchars($error_mes, ENT_QUOTES)); } @@ -1372,19 +1596,19 @@ private function execute_sql($sql, $showError = true) } } - private function connect_to_database($server, $user, $password, $port, $dbname = '') + protected function connect_to_database(string $server, string $user, string $password, int|string $port, string $dbname = ''): mysqli|false { $pathToCerts = __DIR__ . "/../../sites/" . $this->site . "/documents/certificates/"; $mysqlSsl = false; - $mysqli = mysqli_init(); - if (defined('MYSQLI_CLIENT_SSL') && file_exists($pathToCerts . "mysql-ca")) { + $mysqli = $this->mysqliInit(); + if (defined('MYSQLI_CLIENT_SSL') && $this->fileExists($pathToCerts . "mysql-ca")) { $mysqlSsl = true; if ( - file_exists($pathToCerts . "mysql-key") && - file_exists($pathToCerts . "mysql-cert") + $this->fileExists($pathToCerts . "mysql-key") && + $this->fileExists($pathToCerts . "mysql-cert") ) { // with client side certificate/key - mysqli_ssl_set( + $this->mysqliSslSet( $mysqli, $pathToCerts . "mysql-key", $pathToCerts . "mysql-cert", @@ -1394,7 +1618,7 @@ private function connect_to_database($server, $user, $password, $port, $dbname = ); } else { // without client side certificate/key - mysqli_ssl_set( + $this->mysqliSslSet( $mysqli, null, null, @@ -1405,11 +1629,16 @@ private function connect_to_database($server, $user, $password, $port, $dbname = } } try { - if ($mysqlSsl) { - $ok = mysqli_real_connect($mysqli, $server, $user, $password, $dbname, (int)$port != 0 ? (int)$port : 3306, '', MYSQLI_CLIENT_SSL); - } else { - $ok = mysqli_real_connect($mysqli, $server, $user, $password, $dbname, (int)$port != 0 ? (int)$port : 3306); - } + $ok = $this->mysqliRealConnect( + $mysqli, + $server, + $user, + $password, + $dbname, + (int)$port != 0 ? (int)$port : 3306, + '', + $mysqlSsl ? MYSQLI_CLIENT_SSL : 0 + ); } catch (mysqli_sql_exception $e) { $this->error_message = "unable to connect to sql server because of mysql error: " . $e->getMessage(); return false; @@ -1421,25 +1650,42 @@ private function connect_to_database($server, $user, $password, $port, $dbname = return $mysqli; } - private function set_sql_strict() + /** + * Disable strict SQL mode for installation. + * + * Turns off MySQL strict mode to allow legacy SQL patterns + * during installation. + * + * @return mysqli_result|bool Result of SQL execution + */ + protected function set_sql_strict() { // Turn off STRICT SQL return $this->execute_sql("SET sql_mode = ''"); } - private function set_collation() + /** + * Set database character encoding to UTF8MB4. + * + * Configures the connection to use UTF8MB4 character set + * for proper Unicode support. + * + * @return mysqli_result|bool Result of SQL execution + */ + protected function set_collation() { return $this->execute_sql("SET NAMES 'utf8mb4'"); } - /** - * innitialize $this->dumpfiles, an array of the dumpfiles that will - * be loaded into the database, including the correct translation - * dumpfile. - * The keys are the paths of the dumpfiles, and the values are the titles - * @return array - */ - private function initialize_dumpfile_list() + /** + * Initialize $this->dumpfiles, an array of the dumpfiles that will + * be loaded into the database, including the correct translation + * dumpfile. + * The keys are the paths of the dumpfiles, and the values are the titles + * + * @return array + */ + protected function initialize_dumpfile_list(): array { if ($this->clone_database) { $this->dumpfiles = array( $this->get_backup_filename() => 'clone database' ); @@ -1458,7 +1704,7 @@ private function initialize_dumpfile_list() } // Load CVX codes if present - if (file_exists($this->cvx)) { + if ($this->fileExists($this->cvx)) { $dumpfiles[ $this->cvx ] = "CVX Immunization Codes"; } @@ -1468,15 +1714,15 @@ private function initialize_dumpfile_list() return $this->dumpfiles; } - /** - * - * Directory copy logic borrowed from a user comment at - * http://www.php.net/manual/en/function.copy.php - * @param string $src name of the directory to copy - * @param string $dst name of the destination to copy to - * @return bool indicating success - */ - private function recurse_copy($src, $dst) + /** + * Directory copy logic borrowed from a user comment at + * http://www.php.net/manual/en/function.copy.php + * + * @param string $src name of the directory to copy + * @param string $dst name of the destination to copy to + * @return bool indicating success + */ + protected function recurse_copy(string $src, string $dst): bool { $dir = opendir($src); if (! @mkdir($dst)) { @@ -1498,13 +1744,13 @@ private function recurse_copy($src, $dst) return true; } - /** - * - * dump a site's database to a temporary file. - * @param string $source_site_id the site_id of the site to dump - * @return filename of the backup - */ - private function dumpSourceDatabase() + /** + * Dump a site's database to a temporary file. + * + * @param string $source_site_id the site_id of the site to dump + * @return string filename of the backup + */ + protected function dumpSourceDatabase(): string { global $OE_SITES_BASE; $source_site_id = $this->source_site_id; @@ -1512,7 +1758,7 @@ private function dumpSourceDatabase() include("$OE_SITES_BASE/$source_site_id/sqlconf.php"); if (empty($config)) { - die("Source site $source_site_id has not been set up!"); + $this->die("Source site $source_site_id has not been set up!"); } /** @@ -1531,16 +1777,16 @@ private function dumpSourceDatabase() $tmp1 = []; $tmp0 = exec($cmd, $tmp1, $tmp2); if ($tmp2) { - die("Error $tmp2 running \"$cmd\": $tmp0 " . implode(' ', $tmp1)); + $this->die("Error $tmp2 running \"$cmd\": $tmp0 " . implode(' ', $tmp1)); } return $backup_file; } - /** - * @return filename of the source backup database for cloning - */ - private function get_backup_filename() + /** + * @return string filename of the source backup database for cloning + */ + protected function get_backup_filename(): string { if (stristr(PHP_OS, 'WIN')) { $backup_file = 'C:/windows/temp/setup_dump.sql'; @@ -1550,14 +1796,27 @@ private function get_backup_filename() return $backup_file; } - //RP_ADDED + + /** + * Get the currently selected theme. + * + * @return string Current theme name from globals table + */ public function getCurrentTheme() { - $current_theme = $this->execute_sql("SELECT gl_value FROM globals WHERE gl_name LIKE '%css_header%'"); - $current_theme = mysqli_fetch_array($current_theme); + $current_theme = $this->execute_sql("SELECT gl_value FROM globals WHERE gl_name LIKE '%css_header%'"); + $current_theme = $this->mysqliFetchArray($current_theme); return $current_theme[0]; } + /** + * Set the current theme in the database. + * + * Updates the globals table with the selected theme. + * For cloned sites, uses current theme if no new theme specified. + * + * @return mysqli_result|bool Result of the update operation + */ public function setCurrentTheme() { $current_theme = $this->getCurrentTheme(); @@ -1568,16 +1827,23 @@ public function setCurrentTheme() return $this->execute_sql("UPDATE globals SET gl_value='" . $this->escapeSql($this->new_theme) . "' WHERE gl_name LIKE '%css_header%'"); } - public function listThemes() + /** + * Get list of available themes. + * + * Scans the themes directory and returns available theme files. + * + * @return array List of theme file names + */ + public function listThemes(): array { $themes_img_dir = "public/images/stylesheets/"; - $arr_themes_img = array_values(array_filter(scandir($themes_img_dir), function ($item) { + $arr_themes_img = array_values(array_filter($this->scanDir($themes_img_dir), function ($item) { return $item[0] !== '.'; })); return $arr_themes_img; } - private function extractFileName($theme_file_name = '') + protected function extractFileName(string $theme_file_name = ''): array { $under_score = strpos($theme_file_name, '_') + 1; $dot = strpos($theme_file_name, '.'); @@ -1586,7 +1852,15 @@ private function extractFileName($theme_file_name = '') return array('theme_value' => $theme_value, 'theme_title' => $theme_title); } - public function displayThemesDivs() + /** + * Display HTML divs for theme selection interface. + * + * Generates radio button interface with theme preview images + * for the installation theme selection step. + * + * @return void + */ + public function displayThemesDivs(): void { $themes_number = count($this->listThemes()); for ($i = 0; $i < $themes_number; $i++) { @@ -1631,10 +1905,16 @@ public function displayThemesDivs() break; } } - return; } - public function displaySelectedThemeDiv() + /** + * Display the currently selected theme information. + * + * Shows theme preview and details for the currently active theme. + * + * @return void + */ + public function displaySelectedThemeDiv(): void { $theme_file_name = $this->getCurrentTheme(); $arr_extracted_file_name = $this->extractFileName($theme_file_name); @@ -1656,10 +1936,17 @@ public function displaySelectedThemeDiv()
DSTD; echo $display_selected_theme_div . "\r\n"; - return; } - public function displayNewThemeDiv() + /** + * Display the newly selected theme information. + * + * Shows preview of the theme that will be applied after installation. + * For cloned sites, defaults to current theme if no new theme selected. + * + * @return void + */ + public function displayNewThemeDiv(): void { // cloned sites don't get a chance to set a new theme if (!$this->new_theme) { @@ -1684,10 +1971,17 @@ public function displayNewThemeDiv()
DSTD; echo $display_selected_theme_div . "\r\n"; - return; } - public function setupHelpModal() + /** + * Display the installation help modal dialog. + * + * Generates HTML and JavaScript for a modal popup that shows + * installation help documentation in an iframe. + * + * @return void + */ + public function setupHelpModal(): void { $setup_help_modal = << @@ -1727,6 +2021,376 @@ public function setupHelpModal() SETHLP; echo $setup_help_modal . "\r\n"; - return; + } + + /** + * Wrapper for feof to facilitate unit testing. + * + * @codeCoverageIgnore + * + * @param resource $stream + * @return bool + */ + protected function atEndOfFile($stream): bool + { + return feof($stream); + } + + /** + * Wrapper for fclose to facilitate unit testing. + * + * @codeCoverageIgnore + * + * @param resource $stream + * @return bool + */ + protected function closeFile($stream): bool + { + return fclose($stream); + } + + /** + * Create a new Totp instance. + * + * @codeCoverageIgnore + * + * @param string $secret The TOTP secret + * @param string $user The username + * @return Totp + */ + protected function createTotpInstance(string $secret, string $user): Totp + { + return new Totp($secret, $user); + } + + /** + * Check if OpenEMR CryptoGen class exists. + * + * @codeCoverageIgnore + * + * @return bool + */ + protected function cryptoGenClassExists(): bool + { + return class_exists('OpenEMR\Common\Crypto\CryptoGen'); + } + + /** + * Wrapper for die() to facilitate unit testing. + * + * @codeCoverageIgnore + * + * @return never + */ + protected function die(string $message): never + { + error_log($message); + die($message); + } + + /** + * Close the mysqli connection. + * + * @codeCoverageIgnore + * + * @return true + */ + public function disconnect(): true + { + return mysqli_close($this->dbh); + } + + /** + * Encrypt TOTP secret using CryptoGen. + * + * @codeCoverageIgnore + * + * @param string $secret The TOTP secret to encrypt + * @param string $hash The password hash to use for encryption + * @return string Encrypted secret + */ + protected function encryptTotpSecret(string $secret, string $hash): string + { + $cryptoGen = new \OpenEMR\Common\Crypto\CryptoGen(); + return $cryptoGen->encryptStandard($secret, $hash); + } + + /** + * Escape SQL strings to prevent injection attacks. + * + * @codeCoverageIgnore + * + * @param string $sql SQL string to escape + * @return string Escaped SQL string + */ + protected function escapeSql(string $sql): string + { + return mysqli_real_escape_string($this->dbh, $sql); + } + + /** + * Wrapper for file_exists to facilitate unit testing. + * + * @codeCoverageIgnore + * + * @param string $fileName + * @return bool + */ + protected function fileExists(string $fileName): bool + { + return file_exists($fileName); + } + + /** + * Wrapper for fgets to facilitate unit testing. + * + * @codeCoverageIgnore + * + * @param resource $stream + * @param int $length + * @return string|false + */ + protected function getLine($stream, int $length): string|false + { + return fgets($stream, $length); + } + + /** + * Wrapper for glob to facilitate unit testing. + * + * @codeCoverageIgnore + * + * @param string $pattern + * @param int $flags + * @return array|false + */ + protected function globPattern(string $pattern, int $flags = 0): array|false + { + return glob($pattern, $flags); + } + + /** + * Wrapper for mysqli_errno to facilitate unit testing. + * + * @codeCoverageIgnore + * + * @param mysqli $mysql + * @return int + */ + protected function mysqliErrno(mysqli $mysql): int + { + return mysqli_errno($mysql); + } + + /** + * Wrapper for mysqli_error to facilitate unit testing. + * + * @codeCoverageIgnore + * + * @param mysqli $mysql + * @return string + */ + protected function mysqliError(mysqli $mysql): string + { + return mysqli_error($mysql); + } + + /** + * Wrapper for mysqli_fetch_array to facilitate unit testing. + * + * @codeCoverageIgnore + * + * @param mysqli_result $result + * @param int $mode + * @return array|null|false + */ + protected function mysqliFetchArray(mysqli_result $result, int $mode = MYSQLI_BOTH): array|null|false + { + return mysqli_fetch_array($result, $mode); + } + + /** + * Wrapper for mysqli_init to facilitate unit testing. + * + * @codeCoverageIgnore + * + * @return mysqli|false + */ + protected function mysqliInit(): mysqli|false + { + return mysqli_init(); + } + + /** + * Wrapper for mysqli_connect to facilitate unit testing. + * + * @codeCoverageIgnore + * + * @param mysqli_result $result + * @return int + */ + protected function mysqliNumRows(mysqli_result $result): int + { + return mysqli_num_rows($result); + } + + /** + * Wrapper for mysqli_query to facilitate unit testing. + * + * @codeCoverageIgnore + * + * @param mysqli $mysql + * @param string $query + * @return mysqli_result|bool + */ + protected function mysqliQuery(mysqli $mysql, string $query): mysqli_result|bool + { + return mysqli_query($mysql, $query); + } + + /** + * Wrapper for mysqli_real_connect to facilitate unit testing. + * + * @codeCoverageIgnore + * + * @param mysqli $link + * @param string $host + * @param string $user + * @param string $password + * @param string $database + * @param int $port + * @param string $socket + * @param int $flags + * @return bool + */ + protected function mysqliRealConnect(mysqli $link, string $host, string $user, string $password, string $database = '', int $port = 0, string $socket = '', int $flags = 0): bool + { + return mysqli_real_connect($link, $host, $user, $password, $database, $port, $socket, $flags); + } + + /** + * Wrapper for mysqli_connect to facilitate unit testing. + * + * @codeCoverageIgnore + * + * @param mysqli $mysql + * @param string $dbname + * @return bool + */ + protected function mysqliSelectDb(mysqli $mysql, string $dbname): bool + { + return mysqli_select_db($mysql, $dbname); + } + + /** + * Wrapper for mysqli_ssl_set to facilitate unit testing. + * + * @codeCoverageIgnore + * + * @param mysqli $link + * @param ?string $key + * @param ?string $cert + * @param ?string $ca + * @param ?string $capath + * @param ?string $cipher + * @return bool + */ + protected function mysqliSslSet(mysqli $link, ?string $key, ?string $cert, ?string $ca, ?string $capath, ?string $cipher): bool + { + return mysqli_ssl_set($link, $key, $cert, $ca, $capath, $cipher); + } + + /** + * Create a new instance of the GaclApi class. + * + * @codeCoverageIgnore + * + * @return GaclApi New instance of GaclApi + */ + protected function newGaclApi(): GaclApi + { + return new GaclApi(); + } + + /** + * Wrapper for fopen to facilitate unit testing. + * + * @codeCoverageIgnore + * + * @param string $filename + * @param string $mode + * @return resource|false + */ + protected function openFile(string $filename, string $mode) + { + return fopen($filename, $mode); + } + + /** + * Wrapper for scandir to facilitate unit testing. + * + * @codeCoverageIgnore + * + * @param string $directory + * @return array|false + */ + protected function scanDir(string $directory) + { + return scandir($directory); + } + + /** + * Check if Totp class exists. + * + * @codeCoverageIgnore + * + * @return bool + */ + protected function totpClassExists(): bool + { + return class_exists('Totp'); + } + + /** + * Wrapper for touch to facilitate unit testing. + * + * @codeCoverageIgnore + * + * @param string $filename + * @param ?int $mtime + * @param ?int $atime + * @return bool + */ + protected function touchFile(string $filename, ?int $mtime = null, ?int $atime = null): bool + { + return touch($filename, $mtime, $atime); + } + + /** + * Wrapper for unlink to facilitate unit testing. + * + * @codeCoverageIgnore + * + * @param string $filename + * @return bool + */ + protected function unlinkFile(string $filename): bool + { + return unlink($filename); + } + + /** + * Wrapper for fwrite to facilitate unit testing. + * + * @codeCoverageIgnore + * + * @param resource $stream + * @param string $data + * @param ?int $length + * @return int|false + */ + protected function writeToFile($stream, string $data, ?int $length = null): int|false + { + return $length !== null ? fwrite($stream, $data, $length) : fwrite($stream, $data); } } diff --git a/library/smarty_legacy/smarty/Smarty_Compiler_Legacy.class.php b/library/smarty_legacy/smarty/Smarty_Compiler_Legacy.class.php index cdd1a5c336a6..50dc4b56915e 100644 --- a/library/smarty_legacy/smarty/Smarty_Compiler_Legacy.class.php +++ b/library/smarty_legacy/smarty/Smarty_Compiler_Legacy.class.php @@ -965,7 +965,7 @@ function _compile_insert_tag($tag_args) $this->_add_plugin('insert', $name, $delayed_loading); - $_params = "array('args' => array(".implode(', ', (array)$arg_list)."))"; + $_params = "array('args' => array(".implode(', ', $arg_list)."))"; return "" . $this->_additional_newline; } diff --git a/library/smarty_legacy/smarty/internals/core.assemble_plugin_filepath.php b/library/smarty_legacy/smarty/internals/core.assemble_plugin_filepath.php index 22c02483fcd2..4d3a8e58d90a 100644 --- a/library/smarty_legacy/smarty/internals/core.assemble_plugin_filepath.php +++ b/library/smarty_legacy/smarty/internals/core.assemble_plugin_filepath.php @@ -43,7 +43,7 @@ function smarty_core_assemble_plugin_filepath($params, &$smarty) if($_return === false) { // still not found, try PHP include_path if(isset($_relative_paths)) { - foreach ((array)$_relative_paths as $_plugin_dir) { + foreach ($_relative_paths as $_plugin_dir) { $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename; diff --git a/oauth2/.htaccess b/oauth2/.htaccess index 6c336f591486..574c5b395a49 100644 --- a/oauth2/.htaccess +++ b/oauth2/.htaccess @@ -5,4 +5,7 @@ SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-l +# It would be best if we didn't use a query param for the rewrite and instead used it as a path segment, +# however that will break a lot of existing openemr installations so we will use a query param for now and +# perhaps issue a deprecation warning in the future. RewriteRule (.*) authorize.php?_REWRITE_COMMAND=$1 [QSA,L] diff --git a/oauth2/authorize.php b/oauth2/authorize.php index 03b03dd61f60..e8590fa0d7c5 100644 --- a/oauth2/authorize.php +++ b/oauth2/authorize.php @@ -10,130 +10,25 @@ * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ -// below brings in autoloader -require_once(__DIR__ . "/../_rest_config.php"); - use OpenEMR\Common\Csrf\CsrfUtils; use OpenEMR\Common\Logging\SystemLogger; use OpenEMR\Common\Session\SessionUtil; use OpenEMR\RestControllers\AuthorizationController; -$gbl = RestConfig::GetInstance(); -if (empty($gbl::$SITE)) { - http_response_code(401); - exit; -} - -// Will start the oauth OpenEMR session/cookie. -SessionUtil::oauthSessionStart($gbl::$web_root); - -$_GET['site'] = $gbl::$SITE; -// No need for sessionAllowWrite since using oauth session -$ignoreAuth = true; -require_once __DIR__ . '/../interface/globals.php'; - -$logger = new SystemLogger(); - -// exit if api is not turned on -if (empty($GLOBALS['rest_api']) && empty($GLOBALS['rest_fhir_api']) && empty($GLOBALS['rest_portal_api'])) { - $logger->debug("api disabled exiting call"); - SessionUtil::oauthSessionCookieDestroy(); - http_response_code(404); - exit; -} - -// ensure 1) sane site 2) site from gbl and globals are the same and 3) ensure the site exists on filesystem -if (empty($gbl::$SITE) || empty($_SESSION['site_id']) || preg_match('/[^A-Za-z0-9\\-.]/', $gbl::$SITE) || ($gbl::$SITE != $_SESSION['site_id']) || !file_exists($GLOBALS['OE_SITES_BASE'] . '/' . $_SESSION['site_id'])) { - // error collecting site - $logger->error("OpenEMR error - oauth2 error since unable to properly collect site, so forced exit"); - SessionUtil::oauthSessionCookieDestroy(); - http_response_code(400); - exit; -} - -// set up csrf -// used to prevent csrf in the 2 different types of submissions by oauth2/provider/login.php -if (empty($_SESSION['csrf_private_key'])) { - CsrfUtils::setupCsrfKey(); -} - -$end_point = $gbl::getRequestEndPoint(); -$logger->debug("oauth2 request received", ["endpoint" => $end_point]); - -// let's quickly be able to enable our CORS at the PHP level. -header("Access-Control-Allow-Credentials: true"); -header("Access-Control-Allow-Headers: origin, authorization, accept, content-type, x-requested-with"); -header("Access-Control-Allow-Methods: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS"); -header("Access-Control-Allow-Origin: *"); - -$authServer = new AuthorizationController(); - -if (false !== stripos($end_point, '/token')) { - // session is destroyed within below function - $authServer->oauthAuthorizeToken(); - exit; -} - -if (false !== stripos($end_point, '/openid-configuration')) { - $oauthdisc = true; - $base_url = $authServer->authBaseFullUrl; - require_once("provider/.well-known/discovery.php"); - exit; -} - -if (false !== stripos($end_point, '/authorize')) { - // session is destroyed (when throws exception) within below function - $authServer->oauthAuthorizationFlow(); - exit; -} - -if (false !== stripos($end_point, '/device/code')) { - // session is destroyed within below function - $authServer->authorizeUser(); - exit; -} - -if (false !== stripos($end_point, '/jwk')) { - $oauthjwk = true; - require_once(__DIR__ . "/provider/jwk.php"); - exit; -} - -if (false !== stripos($end_point, '/login')) { - // session is maintained - $authServer->userLogin(); - exit; -} -if ($authServer->isSMARTAuthorizationEndPoint($end_point)) { - $authServer->dispatchSMARTAuthorizationEndpoint($end_point); -} - -if (false !== stripos($end_point, '/scope-authorize-confirm')) { - // session is maintained - $authServer->scopeAuthorizeConfirm(); - exit; -} - -if (false !== stripos($end_point, '/registration')) { - // session is destroyed within below function - $authServer->clientRegistration(); - exit; -} - -if (false !== stripos($end_point, '/client')) { - // session is destroyed within below function - $authServer->clientRegisteredDetails(); - exit; -} - -if (false !== stripos($end_point, '/logout')) { - // session is destroyed within below function - $authServer->userSessionLogout(); - exit; -} - -if (false !== stripos($end_point, '/introspect')) { - // session is destroyed within below function - $authServer->tokenIntrospection(); - exit; +require_once "../vendor/autoload.php"; + +// TODO: @adunsulag at some point we can have the .htaccess file just hit +// everything in the dispatch.php file and then we can remove this file +use OpenEMR\Common\Http\HttpRestRequest; +use OpenEMR\RestControllers\ApiApplication; +// create the Request object +try { + $request = HttpRestRequest::createFromGlobals(); + $apiApplication = new ApiApplication(); + $apiApplication->run($request); +} catch (\Throwable $e) { + // TODO: handle exceptions properly + error_log($e->getMessage()); + // should never get here, but if we do, we can return a generic error response + die("An error occurred while processing the request. Please check the logs for more details."); } diff --git a/oauth2/provider/.well-known/discovery.php b/oauth2/provider/.well-known/discovery.php deleted file mode 100644 index 1caedd80225d..000000000000 --- a/oauth2/provider/.well-known/discovery.php +++ /dev/null @@ -1,93 +0,0 @@ -getSupportedClaims(); -$claims = json_encode($claims_array, JSON_PRETTY_PRINT); - -$scopes_array_smart = $scopeRepository->getCurrentSmartScopes(); -$scopes_array = $scopeRepository->getCurrentStandardScopes(); -$scopes_array = array_merge($scopes_array_smart, $scopes_array); - -$scopes = json_encode($scopes_array, JSON_PRETTY_PRINT); - -// Note: for token_endpoint_auth_signing_alg_values_supported we only support RS384 to be spec compliant -// @see http://hl7.org/fhir/uv/bulkdata/authorization/index.html#registering-a-smart-backend-service-communicating-public-keys -// We can't support ES384 right now because lobucci/jwt does not support that. - -$discovery = <<