diff --git a/.gitattributes b/.gitattributes index 18787cdf..5c3eb8fe 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,4 +4,5 @@ /README.md export-ignore /output export-ignore /input export-ignore -/phpunit export-ignore \ No newline at end of file +/phpunit export-ignore +fhir_test_resources.tar.gz export-ignore \ No newline at end of file diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 64bdfd05..6e463131 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,13 +1,2 @@ -# These are supported funding model platforms - github: dcarbone -patreon: # Replace with a single Patreon username -open_collective: # Replace with a single Open Collective username -ko_fi: dcarbone -tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel -community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry -liberapay: # Replace with a single Liberapay username -issuehunt: # Replace with a single IssueHunt username -otechie: # Replace with a single Otechie username -lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry -custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] +ko_fi: dcarbone \ No newline at end of file diff --git a/.github/actions/load-fhir-validator/action.yaml b/.github/actions/load-fhir-validator/action.yaml index 81c5a574..64d4b8f3 100644 --- a/.github/actions/load-fhir-validator/action.yaml +++ b/.github/actions/load-fhir-validator/action.yaml @@ -27,14 +27,14 @@ runs: echo 'url=${{ inputs.base-url }}/${{ inputs.version }}/${{ inputs.filename }}' >> $GITHUB_OUTPUT echo 'cache-key=fhir-validator-${{ inputs.version }}-2' >> $GITHUB_OUTPUT - - uses: actions/cache@v4 - id: cache + - name: 'Init validator cache' + uses: actions/cache@v4 + id: validator-cache with: path: | ${{ github.workspace }}/bin /home/runner/.fhir key: '${{ steps.vars.outputs.cache-key }}' - save-always: true - name: 'Install Java' if: steps.cache.outputs.cache-hit != 'true' && steps.cache.outputs.cache-hit != true @@ -62,4 +62,3 @@ runs: java -jar '${{ github.workspace }}/bin/validator_cli.jar' -version 4.3.0 java -jar '${{ github.workspace }}/bin/validator_cli.jar' -version 5.0.0 echo '::endgroup::' - diff --git a/.github/actions/load-fhir-xsd/action.yaml b/.github/actions/load-fhir-xsd/action.yaml index 79cdf9f8..fc1c1606 100644 --- a/.github/actions/load-fhir-xsd/action.yaml +++ b/.github/actions/load-fhir-xsd/action.yaml @@ -67,5 +67,10 @@ runs: unzip -o -qq '${{ steps.vars.outputs.zip-filename }}' -d '${{ steps.vars.outputs.xsd-cache-dir }}' + if [ -d '${{ steps.vars.outputs.xsd-cache-dir }}/fhir-all-xsd' ]; then + mv '${{ steps.vars.outputs.xsd-cache-dir }}/fhir-all-xsd'/* '${{ steps.vars.outputs.xsd-cache-dir }}' + rmdir '${{ steps.vars.outputs.xsd-cache-dir }}/fhir-all-xsd' + fi + ls -l '${{ steps.vars.outputs.cache-dir}}' ls -l '${{ steps.vars.outputs.xsd-cache-dir }}' \ No newline at end of file diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 91555001..42378785 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -27,19 +27,25 @@ on: jobs: load-fhir-source: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 strategy: fail-fast: true matrix: - fhir-version: [ 'DSTU1', 'DSTU2', 'STU3', 'R4', 'R5' ] - - name: 'Download ${{ matrix.fhir-version }} Source' + test-target: + - 'DSTU1' + - 'DSTU2' + - 'STU3' + - 'R4' + - 'R4B' + - 'R5' + + name: 'Download ${{ matrix.test-target }} Source' steps: - uses: actions/checkout@v4 - uses: ./.github/actions/load-fhir-xsd with: - version: '${{ matrix.fhir-version }}' + version: '${{ matrix.test-target }}' # load-fhir-validator: @@ -58,8 +64,19 @@ jobs: strategy: fail-fast: false matrix: - php-version: [ '8.1', '8.2', '8.3' ] - fhir-version: [ 'DSTU1', 'DSTU2', 'STU3', 'R4', 'R5' ] + php-version: + - '8.1' + - '8.2' + - '8.3' + - '8.4' + test-target: + - 'Core' + - 'DSTU1' + - 'DSTU2' + - 'STU3' + - 'R4' + - 'R4B' + - 'R5' include: - php-version: '8.1' phpunit-version: '10.5' @@ -67,15 +84,19 @@ jobs: phpunit-version: '11.1' - php-version: '8.3' phpunit-version: '11.1' - name: '${{ matrix.fhir-version }} - PHP ${{ matrix.php-version }} - PHPUnit ${{ matrix.phpunit-version }}' + - php-version: '8.4' + phpunit-version: '11.1' + + name: '${{ matrix.test-target }} - PHP ${{ matrix.php-version }} - PHPUnit ${{ matrix.phpunit-version }}' steps: - name: 'Check the stuff out' uses: actions/checkout@v4 - - name: 'Load FHIR ${{ matrix.fhir-version }} Source' + - name: 'Load FHIR ${{ matrix.test-target }} Source' + if: matrix.test-target != 'Core' uses: ./.github/actions/load-fhir-xsd with: - version: '${{ matrix.fhir-version }}' + version: '${{ matrix.test-target }}' # - name: 'Install FHIR validator' # uses: ./.github/actions/load-fhir-validator @@ -105,12 +126,12 @@ jobs: run: | echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - name: 'Cache Composer Stuff' + - name: 'Init composer dep cache' + id: cache uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.dir }} key: "composer-${{ runner.os }}-${{ matrix.php-version }}-${{ matrix.phpunit-version }}-${{ hashFiles('composer.lock') }}" - save-always: true - name: 'Install Composer deps' # language=sh @@ -118,10 +139,21 @@ jobs: rm composer.lock composer install --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist - - name: 'Generate code' + - name: 'Save composer dep cache' + if: steps.cache.outputs.cache-hit != 'true' && steps.cache.outputs.cache-hit != true + uses: actions/cache/save@v4 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: "composer-${{ runner.os }}-${{ matrix.php-version }}-${{ matrix.phpunit-version }}-${{ hashFiles('composer.lock') }}" + + - name: "Generate ${{ matrix.test-target }} code" # language=sh run: | - ./bin/generate.sh --useExisting --versions '${{ matrix.fhir-version }}' + if [ '${{ matrix.test-target }}' == 'Core' ]; then + ./bin/generate.sh --useExisting --onlyCore + else + ./bin/generate.sh --useExisting --versions '${{ matrix.test-target }}' + fi # - name: 'Install Java' # uses: actions/setup-java@v4 @@ -132,4 +164,4 @@ jobs: - name: 'Run tests' # language=sh run: | - ./vendor/bin/phpunit -c 'phpunit/${{ matrix.fhir-version }}.xml' + ./vendor/bin/phpunit -c 'phpunit/${{ matrix.test-target }}.xml' diff --git a/README.md b/README.md index 912d7afd..f64b1fc3 100644 --- a/README.md +++ b/README.md @@ -84,8 +84,11 @@ You can view an example config array here: [bin/config.php](./bin/config.php). // first, build new configuration class $config = new \DCarbone\PHPFHIR\Config(require 'config.php'); +// if you wish to limit the versions generated to a subset of those configured: +// $config->setVersionsToGenerate(['DSTU2', 'STU3']); + // next, iterate through all configured versions and render code: -foreach ($config->getVersions() as $versionConfig) { +foreach ($config->getVersionsIterator() as $versionConfig) { $versionConfig->getDefinition()->getBuilder()->render(); } ``` diff --git a/bin/config.php b/bin/config.php index 39645652..66202f76 100644 --- a/bin/config.php +++ b/bin/config.php @@ -20,51 +20,69 @@ */ return [ // The path to look look for and optionally download source XSD files to - 'schemaPath' => __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'input/', + 'schemaPath' => __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'input' . DIRECTORY_SEPARATOR, - // The path to place generated type class files - 'classesPath' => __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'output/', + // The path to place generated files + 'outputPath' => __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'output' . DIRECTORY_SEPARATOR, - // If true, will use a noop null logger - 'silent' => false, + // The root namespace for all generated classes + 'rootNamespace' => '\\DCarbone\\PHPFHIRGenerated', - // If true, will skip generation of test classes - 'skipTests' => false, + // If true, will use a noop null logger + 'silent' => false, - // If you wish to specify alternative libxml opts, do so here. - 'libxmlOpts' => LIBXML_NONET | LIBXML_BIGLINES | LIBXML_PARSEHUGE | LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD | LIBXML_NOXMLDECL, + // The libxml opts to use for parsing source XSD's. + 'libxmlOpts' => LIBXML_NONET | LIBXML_BIGLINES | LIBXML_PARSEHUGE | LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD | LIBXML_NOXMLDECL, - // Map of versions and configurations to generate - // Each entry in this map will grab the latest revision of that particular version. If you wish to use a specific - // version, please see https://www.hl7.org/fhir/directory.html - 'versions' => [ + // Map of versions and configurations to generate. + // Each entry in this map will grab the latest revision of that particular version. + // + // For a list of base versions, see here: https://www.hl7.org/fhir/directory.html + 'versions' => [ 'DSTU1' => [ // Source URL - 'url' => 'https://hl7.org/fhir/DSTU1/fhir-all-xsd.zip', - // Namespace to prefix the generated classes with - 'namespace' => '\\HL7\\FHIR\\DSTU1', - // if defined, enables integration and validation test generation against the provided endpoint. - 'testEndpoint' => '', + 'sourceUrl' => 'https://hl7.org/fhir/DSTU1/fhir-all-xsd.zip', + // Namespace to generate classes into + 'namespace' => 'Versions\\DSTU1', + + // The default configuration for all instances of this version. May be overridden per version during + // instantiation. + 'defaultConfig' => [ + 'unserializeConfig' => [ + // Libxml options to use when unserializing types from XML + 'libxmlOptMask' => 'LIBXML_NONET | LIBXML_BIGLINES | LIBXML_PARSEHUGE | LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD | LIBXML_NOXMLDECL', + // Maximum depth to allow when decoding JSON + 'jsonDecodeMaxDepth' => 512, + ], + 'serializeConfig' => [ + // If true, will override the default xmlns value with the value provided in the rootXmlns key + 'overrideSourceXMLNS' => false, + // If overrideSourceXmlns is true, this value will be used as the root xmlns value + 'rootXMLNS' => 'http://hl7.org/fhir', + // Libxml options to use when serializing XHTML content + 'xhtmlLibxmlOptMask' => 'LIBXML_NONET | LIBXML_BIGLINES | LIBXML_PARSEHUGE | LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD | LIBXML_NOXMLDECL', + ] + ] ], 'DSTU2' => [ - 'url' => 'https://hl7.org/fhir/DSTU2/fhir-all-xsd.zip', - 'namespace' => '\\HL7\\FHIR\\DSTU2', - 'testEndpoint' => 'https://hapi.fhir.org/baseDstu2', + 'sourceUrl' => 'https://hl7.org/fhir/DSTU2/fhir-all-xsd.zip', + 'namespace' => 'Versions\\DSTU2', + ], + 'STU3' => [ + 'sourceUrl' => 'https://hl7.org/fhir/STU3/fhir-all-xsd.zip', + 'namespace' => 'Versions\\STU3', ], - 'STU3' => [ - 'url' => 'https://hl7.org/fhir/STU3/fhir-all-xsd.zip', - 'namespace' => '\\HL7\\FHIR\\STU3', - 'testEndpoint' => 'https://hapi.fhir.org/baseDstu3', + 'R4' => [ + 'sourceUrl' => 'https://hl7.org/fhir/R4/fhir-all-xsd.zip', + 'namespace' => 'Versions\\R4', ], - 'R4' => [ - 'url' => 'https://hl7.org/fhir/R4/fhir-all-xsd.zip', - 'namespace' => '\\HL7\\FHIR\\R4', - 'testEndpoint' => 'https://hapi.fhir.org/baseR4', + 'R4B' => [ + 'sourceUrl' => 'https://hl7.org/fhir/R4B/fhir-all-xsd.zip', + 'namespace' => 'Versions\\R4B', ], 'R5' => [ - 'url' => 'https://hl7.org/fhir/R5/fhir-all-xsd.zip', - 'namespace' => '\\HL7\\FHIR\\R5', - 'testEndpoint' => 'https://hapi.fhir.org/baseR5', + 'sourceUrl' => 'https://hl7.org/fhir/R5/fhir-all-xsd.zip', + 'namespace' => 'Versions\\R5', ] // 'Build' => [ diff --git a/bin/generate.php b/bin/generate.php index 457e3634..88668cb8 100644 --- a/bin/generate.php +++ b/bin/generate.php @@ -26,25 +26,21 @@ // --- autoload setup const AUTOLOAD_CLASS_FILEPATH = __DIR__ . '/../vendor/autoload.php'; +$autoloadClasspath = realpath(AUTOLOAD_CLASS_FILEPATH); + // ensure composer autoload class exists. -if (!file_exists(AUTOLOAD_CLASS_FILEPATH)) { - echo sprintf("Unable to locate composer autoload file expected at path: %s\n\n", AUTOLOAD_CLASS_FILEPATH); - echo "Please run \"composer install\" from the root of the project directory\n\n"; +if (!$autoloadClasspath) { + echo 'Unable to locate composer autoload file expected at path: ' . AUTOLOAD_CLASS_FILEPATH . PHP_EOL . PHP_EOL; + echo "Please run \"composer install\" from the root of the project directory" . PHP_EOL . PHP_EOL; exit(1); } -require AUTOLOAD_CLASS_FILEPATH; +require $autoloadClasspath; -// --- use statements +// ----- use statements use DCarbone\PHPFHIR\Builder; use DCarbone\PHPFHIR\Config; -use DCarbone\PHPFHIR\Definition; -use JetBrains\PhpStorm\NoReturn; -use Monolog\Formatter\LineFormatter; -use Monolog\Handler\StreamHandler; -use Monolog\Logger; -use Monolog\Processor\PsrLogMessageProcessor; use Psr\Log\LogLevel; use Psr\Log\NullLogger; @@ -56,9 +52,10 @@ const FLAG_FORCE_DELETE = '--forceDelete'; const FLAG_USE_EXISTING = '--useExisting'; const FLAG_CONFIG = '--config'; +const FLAG_ONLY_CORE = '--onlyCore'; const FLAG_ONLY_LIBRARY = '--onlyLibrary'; -const FLAG_ONLY_TESTS = '--onlyTests'; const FLAG_VERSIONS = '--versions'; +const FLAG_USERAGENT = '--userAgent'; const FLAG_LOG_LEVEL = '--logLevel'; // ----- cli and config opts @@ -69,19 +66,20 @@ $config_location_env = getenv(ENV_GENERATE_CONFIG_FILE); $config_location_arg = ''; $config_file = null; +$only_core = false; $only_library = false; -$only_tests = false; $versions_to_generate = null; $use_existing = false; $log_level = LogLevel::WARNING; +$user_agent_def = 'Mozilla/5.0 (Android 4.4; Mobile; rv:41.0) Gecko/41.0 Firefox/41.0'; +$user_agent = $user_agent_def; // ----- functions /** - * @param bool $return * @return string */ -function missing_config_text(bool $return): string +function missing_config_text(): string { global $config_location_env, $config_location_arg, $config_location_def; $out = 'Unable to locate generate script configuration file. I looked in the following locations:' . PHP_EOL; @@ -113,21 +111,17 @@ function missing_config_text(bool $return): string STRING; - if ($return) { - return $out; - } - - echo $out; - exit(1); + return $out; } /** - * @param bool $err + * @return string */ -#[NoReturn] function exit_with_help(bool $err = false): void +function help_text(): string { - global $config_location_def; - $env_var = ENV_GENERATE_CONFIG_FILE; + global $config_location_def, $user_agent_def; + + $config_env_var = ENV_GENERATE_CONFIG_FILE; $out = << 1) { + echo help_text(); + echo PHP_EOL; + echo "Flags " . FLAG_ONLY_CORE . " and " . FLAG_ONLY_LIBRARY . " are mutually exclusive." . PHP_EOL; exit(1); } +// determine what to generate +$generate_core = $only_core || (0 === $only_count); +$generate_library = $only_library || (0 === $only_count); + // determine if monolog is present, otherwise use null logger if (class_exists('\\Monolog\\Logger')) { - $formatter = new LineFormatter(LineFormatter::SIMPLE_FORMAT); - $handler = new StreamHandler('php://stdout', $log_level); - $handler->setFormatter($formatter); - $processor = new PsrLogMessageProcessor(\DateTimeInterface::W3C); - $logger = new Logger( + $logger = new \Monolog\Logger( 'php-fhir', - [$handler], - [$processor] + [ + (new \Monolog\Handler\StreamHandler('php://stdout', $log_level)) + ->setFormatter( + new \Monolog\Formatter\LineFormatter(\Monolog\Formatter\LineFormatter::SIMPLE_FORMAT), + ), + ], + [ + new \Monolog\Processor\PsrLogMessageProcessor(\DateTimeInterface::W3C), + ] ); } else { $logger = new NullLogger(); @@ -362,11 +379,8 @@ function is_dir_empty(string $dir): bool // test specified versions foreach ($versions_to_generate as $vg) { if (!$config->hasVersion($vg)) { - echo sprintf( - "Version \"%s\" not found in config. Available: %s\n\n", - $vg, - implode(', ', $config->listVersions()) - ); + echo 'Version "' . $vg . '" not found in config. Available: ' . + implode(', ', $config->listVersions()) . PHP_EOL . PHP_EOL; exit(1); } } @@ -374,149 +388,136 @@ function is_dir_empty(string $dir): bool $ins = [STDIN]; $null = null; -echo sprintf( - "\nGenerating classes for versions: %s\n\n", - implode(', ', $versions_to_generate) -); - -foreach ($versions_to_generate as $version) { - $version_config = $config->getVersion($version); - $url = $version_config->getUrl(); - - // build vars - $namespace = $version_config->getFullyQualifiedName(true); - $version = trim($version); - $schema_dir = $config->getSchemaPath() . DIRECTORY_SEPARATOR . $version; - - // Download zip files - $zip_file_name = $config->getSchemaPath() . DIRECTORY_SEPARATOR . $version . '.zip'; - $zip_exists = file_exists($zip_file_name); - - $download = $unzip = true; - - if ($zip_exists) { - if (!$use_existing && ($force_delete || - ask("ZIP \"{$zip_file_name}\" already exists.\nWould you like to re-download from \"{$url}\"?")) - ) { - echo "Deleting {$zip_file_name} ...\n"; - unlink($zip_file_name); - if (file_exists($zip_file_name)) { - echo "Unable to delete file {$zip_file_name}\n"; - exit(1); - } - echo "Deleted.\n"; - } else { - echo "Using existing local copy\n"; - $download = false; - } - } +if (!$only_core) { + echo PHP_EOL; - if ($download) { - // Download zip file... - echo sprintf('Downloading %s from %s to %s%s', $version, $url, $zip_file_name, PHP_EOL); - $fh = fopen($zip_file_name, 'w'); - $ch = curl_init($url); - curl_setopt_array( - $ch, - [ - CURLOPT_USERAGENT => 'Mozilla/5.0 (Android 4.4; Mobile; rv:41.0) Gecko/41.0 Firefox/41.0', - CURLOPT_FOLLOWLOCATION => true, - CURLOPT_HEADER => 0, - CURLOPT_FILE => $fh, - ] - ); - $resp = curl_exec($ch); - $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); - $err = curl_error($ch); - curl_close($ch); - fclose($fh); - if ('' !== $err) { - echo sprintf('Error downloading from %s: %s%s', $version, $err, PHP_EOL); - exit(1); - } - if ($code !== 200) { - echo sprintf('Error downlodaing from %s: %d (%s)%s', $version, $code, $resp, PHP_EOL); - exit(1); + echo 'Locating source(s) for versions: ' . implode(', ', $versions_to_generate) . PHP_EOL . PHP_EOL; + + foreach ($versions_to_generate as $version_name) { + $version_name = trim($version_name); + + $version_config = $config->getVersion($version_name); + + $source_url = $version_config->getSourceUrl(); + $schema_dir = $version_config->getSchemaPath(); + + // Download zip files + $zip_file_name = $schema_dir . DIRECTORY_SEPARATOR . $version_name . '.zip'; + $zip_exists = file_exists($zip_file_name); + + $download = $unzip = true; + + if ($zip_exists) { + if (!$use_existing && ($force_delete || + ask("ZIP \"{$zip_file_name}\" already exists." . PHP_EOL . "Would you like to re-download from \"{$source_url}\"?")) + ) { + echo "Deleting {$zip_file_name} ..." . PHP_EOL; + unlink($zip_file_name); + if (file_exists($zip_file_name)) { + echo "Unable to delete file {$zip_file_name}" . PHP_EOL; + exit(1); + } + echo "File {$zip_file_name} deleted." . PHP_EOL; + } else { + echo "Using existing local copy" . PHP_EOL; + $download = false; + } } - } - if (is_dir($schema_dir)) { - if (is_dir_empty($schema_dir)) { - // TODO: is this necessary...? - echo "Schema dir \"{$schema_dir}\" is empty, will remove and re-create\n"; - nuke_dir($schema_dir); - if (!mkdir($schema_dir, 0755, true)) { - echo "Unable to create directory \"{$schema_dir}\. Exiting\n"; + if ($download) { + // Download zip file... + echo "Downloading FHIR schema for version {$version_name} from {$source_url} to {$zip_file_name}" . PHP_EOL; + $fh = fopen($zip_file_name, 'w'); + $ch = curl_init($source_url); + curl_setopt_array( + $ch, + [ + CURLOPT_USERAGENT => $user_agent, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HEADER => 0, + CURLOPT_FILE => $fh, + ] + ); + $resp = curl_exec($ch); + $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $err = curl_error($ch); + curl_close($ch); + fclose($fh); + if ('' !== $err) { + echo "Error downloading version {$version_name} from {$source_url}: {$err}" . PHP_EOL; + exit(1); + } + if ($code !== 200) { + echo "Error downloading version {$version_name} from {$source_url}: {$code} ({$resp})" . PHP_EOL; exit(1); } - } elseif (!$download) { - echo "Did not download new zip and schema dir \"{$schema_dir}\" already exists, using...\n"; - $unzip = false; - } elseif (!$use_existing) { - if ($force_delete || ask("Schema dir \"{$schema_dir}\" already exists, ok to delete?")) { + } + + if (is_dir($schema_dir)) { + if (is_dir_empty($schema_dir)) { + // TODO: is this necessary...? + echo "Schema dir \"{$schema_dir}\" is empty, will remove and re-create" . PHP_EOL; nuke_dir($schema_dir); if (!mkdir($schema_dir, 0755, true)) { - echo "Unable to create directory \"{$schema_dir}\. Exiting\n"; + echo "Unable to create directory \"{$schema_dir}\. Exiting" . PHP_EOL; exit(1); } - } else { - echo "Exiting\n"; - exit(0); + } elseif (!$download) { + echo "Did not download new zip and schema dir \"{$schema_dir}\" already exists, using..." . PHP_EOL; + $unzip = false; + } elseif (!$use_existing) { + if ($force_delete || ask("Schema dir \"{$schema_dir}\" already exists, ok to delete?")) { + nuke_dir($schema_dir); + if (!mkdir($schema_dir, 0755, true)) { + echo "Unable to create directory \"{$schema_dir}\. Exiting" . PHP_EOL; + exit(1); + } + } else { + echo "Exiting" . PHP_EOL; + exit(0); + } } } - } - if ($unzip) { - if (class_exists('\\ZipArchive')) { - echo "ext-zip found\n"; + if ($unzip) { + if (class_exists('\\ZipArchive')) { + echo "ext-zip found" . PHP_EOL; - $zip = new \ZipArchive(); + $zip = new \ZipArchive(); - if (true !== ($res = $zip->open($schema_dir . '.zip'))) { - echo "Unable to open file {$schema_dir}.zip. ZipArchive err: {$res}\n"; - exit(1); - } + if (true !== ($res = $zip->open($schema_dir . '.zip'))) { + echo "Unable to open file {$schema_dir}.zip. ZipArchive err: {$res}" . PHP_EOL; + exit(1); + } - // Extract Zip - $zip->extractTo($schema_dir); - $zip->close(); - } else { - echo "ext-zip not found, trying \"unzip\" directly...\n"; - $cmd = "unzip -o -qq {$schema_dir}.zip -d {$schema_dir}"; - $output = []; - $code = 0; - echo "executing: {$cmd}\n"; - exec($cmd, $output, $code); - if (0 !== $code) { - echo "unzip failed with code {$code}\noutput:\n"; - foreach ($output as $line) { - echo "-----> {$line}\n"; + // Extract Zip + $zip->extractTo($schema_dir); + $zip->close(); + } else { + echo "ext-zip not found, trying \"unzip\" directly..." . PHP_EOL; + $cmd = "unzip -o -qq {$schema_dir}.zip -d {$schema_dir}"; + $output = []; + $code = 0; + echo "executing: {$cmd}" . PHP_EOL; + exec($cmd, $output, $code); + if (0 !== $code) { + echo "unzip failed with code {$code}" . PHP_EOL . "output:" . PHP_EOL; + foreach ($output as $line) { + echo "-----> {$line}" . PHP_EOL; + } + exit(1); } - exit(1); } } } +} - echo sprintf( - 'Generating "%s" into %s%s%s%s', - $version, - $config->getClassesPath(), - DIRECTORY_SEPARATOR, - str_replace('\\', DIRECTORY_SEPARATOR, trim($namespace, "\\")), - PHP_EOL - ); +echo PHP_EOL; - $definition = new Definition($version_config); - $definition->buildDefinition(); +// create builder +$builder = new Builder($config); - $builder = new Builder($version_config, $definition); - if ($only_library) { - $builder->writeFhirTypeFiles(); - } elseif ($only_tests) { - $builder->writeFhirTestFiles(); - } else { - $builder->render(); - } -} +// render entities based on flags. +$builder->render($generate_core, $generate_library ? $versions_to_generate : []); echo PHP_EOL . 'Generation completed' . PHP_EOL; diff --git a/composer.json b/composer.json index 5130f754..98e736f7 100644 --- a/composer.json +++ b/composer.json @@ -22,15 +22,16 @@ "php": "^8.1", "ext-ctype": "*", "ext-curl": "*", + "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-simplexml": "*", - "psr/log": "^3.0" - }, - "require-dev": { - "ext-dom": "*", "ext-xmlreader": "*", "ext-xmlwriter": "*", + "psr/log": "^3.0", + "composer/semver": "^3.4" + }, + "require-dev": { "phpunit/phpunit": "^10.5 || ^11.0", "monolog/monolog": "^3.2.0" }, @@ -52,14 +53,6 @@ "DCarbone\\PHPFHIR\\": "src/" } }, - "autoload-dev": { - "psr-4": { - "HL7\\": "output/HL7" - } - }, - "config": { - "platform-check": false - }, "suggest": { "ext-zip": "To enable unzipping of downloaded source files" } diff --git a/composer.lock b/composer.lock index 6eace382..a34db51f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,89 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b2856e631e42f5154f843c494fe3f8f0", + "content-hash": "62264fb6e427821b78fda5dcc603f221", "packages": [ + { + "name": "composer/semver", + "version": "3.4.3", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.11", + "symfony/phpunit-bridge": "^3 || ^7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.3" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-09-19T14:15:21+00:00" + }, { "name": "psr/log", "version": "3.0.2", @@ -163,16 +244,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.12.0", + "version": "1.12.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", "shasum": "" }, "require": { @@ -211,7 +292,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" }, "funding": [ { @@ -219,20 +300,20 @@ "type": "tidelift" } ], - "time": "2024-06-12T14:39:25+00:00" + "time": "2024-11-08T17:47:46+00:00" }, { "name": "nikic/php-parser", - "version": "v5.1.0", + "version": "v5.4.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1" + "reference": "447a020a1f875a434d62f2a401f53b82a396e494" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1", - "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", + "reference": "447a020a1f875a434d62f2a401f53b82a396e494", "shasum": "" }, "require": { @@ -275,9 +356,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" }, - "time": "2024-07-01T20:03:41+00:00" + "time": "2024-12-30T11:07:19+00:00" }, { "name": "phar-io/manifest", @@ -399,35 +480,35 @@ }, { "name": "phpunit/php-code-coverage", - "version": "10.1.15", + "version": "11.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae" + "reference": "418c59fd080954f8c4aa5631d9502ecda2387118" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae", - "reference": "5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/418c59fd080954f8c4aa5631d9502ecda2387118", + "reference": "418c59fd080954f8c4aa5631d9502ecda2387118", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1", - "phpunit/php-file-iterator": "^4.0", - "phpunit/php-text-template": "^3.0", - "sebastian/code-unit-reverse-lookup": "^3.0", - "sebastian/complexity": "^3.0", - "sebastian/environment": "^6.0", - "sebastian/lines-of-code": "^2.0", - "sebastian/version": "^4.0", - "theseer/tokenizer": "^1.2.0" + "nikic/php-parser": "^5.3.1", + "php": ">=8.2", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-text-template": "^4.0.1", + "sebastian/code-unit-reverse-lookup": "^4.0.1", + "sebastian/complexity": "^4.0.1", + "sebastian/environment": "^7.2.0", + "sebastian/lines-of-code": "^3.0.1", + "sebastian/version": "^5.0.2", + "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^10.1" + "phpunit/phpunit": "^11.5.0" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -436,7 +517,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "10.1-dev" + "dev-main": "11.0.x-dev" } }, "autoload": { @@ -465,7 +546,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/10.1.15" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.8" }, "funding": [ { @@ -473,32 +554,32 @@ "type": "github" } ], - "time": "2024-06-29T08:25:15+00:00" + "time": "2024-12-11T12:34:27+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "4.1.0", + "version": "5.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", - "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -526,7 +607,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0" }, "funding": [ { @@ -534,28 +615,28 @@ "type": "github" } ], - "time": "2023-08-31T06:24:48+00:00" + "time": "2024-08-27T05:02:59+00:00" }, { "name": "phpunit/php-invoker", - "version": "4.0.0", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", - "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { "ext-pcntl": "*", - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "suggest": { "ext-pcntl": "*" @@ -563,7 +644,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -589,7 +670,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" }, "funding": [ { @@ -597,32 +679,32 @@ "type": "github" } ], - "time": "2023-02-03T06:56:09+00:00" + "time": "2024-07-03T05:07:44+00:00" }, { "name": "phpunit/php-text-template", - "version": "3.0.1", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", - "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -649,7 +731,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" + "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" }, "funding": [ { @@ -657,32 +739,32 @@ "type": "github" } ], - "time": "2023-08-31T14:07:24+00:00" + "time": "2024-07-03T05:08:43+00:00" }, { "name": "phpunit/php-timer", - "version": "6.0.0", + "version": "7.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", - "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -708,7 +790,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" }, "funding": [ { @@ -716,20 +799,20 @@ "type": "github" } ], - "time": "2023-02-03T06:57:52+00:00" + "time": "2024-07-03T05:09:35+00:00" }, { "name": "phpunit/phpunit", - "version": "10.5.26", + "version": "11.5.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "42e2f13ceaa2e34461bc89bea75407550b40b2aa" + "reference": "153d0531b9f7e883c5053160cad6dd5ac28140b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/42e2f13ceaa2e34461bc89bea75407550b40b2aa", - "reference": "42e2f13ceaa2e34461bc89bea75407550b40b2aa", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/153d0531b9f7e883c5053160cad6dd5ac28140b3", + "reference": "153d0531b9f7e883c5053160cad6dd5ac28140b3", "shasum": "" }, "require": { @@ -739,26 +822,26 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", - "php": ">=8.1", - "phpunit/php-code-coverage": "^10.1.5", - "phpunit/php-file-iterator": "^4.0", - "phpunit/php-invoker": "^4.0", - "phpunit/php-text-template": "^3.0", - "phpunit/php-timer": "^6.0", - "sebastian/cli-parser": "^2.0", - "sebastian/code-unit": "^2.0", - "sebastian/comparator": "^5.0", - "sebastian/diff": "^5.0", - "sebastian/environment": "^6.0", - "sebastian/exporter": "^5.1", - "sebastian/global-state": "^6.0.1", - "sebastian/object-enumerator": "^5.0", - "sebastian/recursion-context": "^5.0", - "sebastian/type": "^4.0", - "sebastian/version": "^4.0" + "myclabs/deep-copy": "^1.12.1", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.2", + "phpunit/php-code-coverage": "^11.0.8", + "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.2", + "sebastian/comparator": "^6.2.1", + "sebastian/diff": "^6.0.2", + "sebastian/environment": "^7.2.0", + "sebastian/exporter": "^6.3.0", + "sebastian/global-state": "^7.0.2", + "sebastian/object-enumerator": "^6.0.1", + "sebastian/type": "^5.1.0", + "sebastian/version": "^5.0.2", + "staabm/side-effects-detector": "^1.0.5" }, "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files" @@ -769,7 +852,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "10.5-dev" + "dev-main": "11.5-dev" } }, "autoload": { @@ -801,7 +884,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.26" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.2" }, "funding": [ { @@ -817,32 +900,32 @@ "type": "tidelift" } ], - "time": "2024-07-08T05:30:46+00:00" + "time": "2024-12-21T05:51:08+00:00" }, { "name": "sebastian/cli-parser", - "version": "2.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", - "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -866,7 +949,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" }, "funding": [ { @@ -874,32 +957,32 @@ "type": "github" } ], - "time": "2024-03-02T07:12:49+00:00" + "time": "2024-07-03T04:41:36+00:00" }, { "name": "sebastian/code-unit", - "version": "2.0.0", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" + "reference": "ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", - "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca", + "reference": "ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.5" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -922,7 +1005,8 @@ "homepage": "https://github.com/sebastianbergmann/code-unit", "support": { "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.2" }, "funding": [ { @@ -930,32 +1014,32 @@ "type": "github" } ], - "time": "2023-02-03T06:58:43+00:00" + "time": "2024-12-12T09:59:06+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "3.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" + "reference": "183a9b2632194febd219bb9246eee421dad8d45e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", - "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -977,7 +1061,8 @@ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" }, "funding": [ { @@ -985,36 +1070,36 @@ "type": "github" } ], - "time": "2023-02-03T06:59:15+00:00" + "time": "2024-07-03T04:45:54+00:00" }, { "name": "sebastian/comparator", - "version": "5.0.1", + "version": "6.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "2db5010a484d53ebf536087a70b4a5423c102372" + "reference": "43d129d6a0f81c78bee378b46688293eb7ea3739" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2db5010a484d53ebf536087a70b4a5423c102372", - "reference": "2db5010a484d53ebf536087a70b4a5423c102372", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/43d129d6a0f81c78bee378b46688293eb7ea3739", + "reference": "43d129d6a0f81c78bee378b46688293eb7ea3739", "shasum": "" }, "require": { "ext-dom": "*", "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/diff": "^5.0", - "sebastian/exporter": "^5.0" + "php": ">=8.2", + "sebastian/diff": "^6.0", + "sebastian/exporter": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^10.3" + "phpunit/phpunit": "^11.4" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "6.2-dev" } }, "autoload": { @@ -1054,7 +1139,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.1" + "source": "https://github.com/sebastianbergmann/comparator/tree/6.2.1" }, "funding": [ { @@ -1062,33 +1147,33 @@ "type": "github" } ], - "time": "2023-08-14T13:18:12+00:00" + "time": "2024-10-31T05:30:08+00:00" }, { "name": "sebastian/complexity", - "version": "3.2.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "68ff824baeae169ec9f2137158ee529584553799" + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", - "reference": "68ff824baeae169ec9f2137158ee529584553799", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1" + "nikic/php-parser": "^5.0", + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.2-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -1112,7 +1197,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" + "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" }, "funding": [ { @@ -1120,33 +1205,33 @@ "type": "github" } ], - "time": "2023-12-21T08:37:17+00:00" + "time": "2024-07-03T04:49:50+00:00" }, { "name": "sebastian/diff", - "version": "5.1.1", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", - "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0", - "symfony/process": "^6.4" + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.1-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -1179,7 +1264,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" }, "funding": [ { @@ -1187,27 +1272,27 @@ "type": "github" } ], - "time": "2024-03-02T07:15:17+00:00" + "time": "2024-07-03T04:53:05+00:00" }, { "name": "sebastian/environment", - "version": "6.1.0", + "version": "7.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", - "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "suggest": { "ext-posix": "*" @@ -1215,7 +1300,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "6.1-dev" + "dev-main": "7.2-dev" } }, "autoload": { @@ -1243,7 +1328,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" + "source": "https://github.com/sebastianbergmann/environment/tree/7.2.0" }, "funding": [ { @@ -1251,34 +1336,34 @@ "type": "github" } ], - "time": "2024-03-23T08:47:14+00:00" + "time": "2024-07-03T04:54:44+00:00" }, { "name": "sebastian/exporter", - "version": "5.1.2", + "version": "6.3.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "955288482d97c19a372d3f31006ab3f37da47adf" + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf", - "reference": "955288482d97c19a372d3f31006ab3f37da47adf", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/3473f61172093b2da7de1fb5782e1f24cc036dc3", + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3", "shasum": "" }, "require": { "ext-mbstring": "*", - "php": ">=8.1", - "sebastian/recursion-context": "^5.0" + "php": ">=8.2", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.1-dev" + "dev-main": "6.1-dev" } }, "autoload": { @@ -1321,7 +1406,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2" + "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.0" }, "funding": [ { @@ -1329,35 +1414,35 @@ "type": "github" } ], - "time": "2024-03-02T07:17:12+00:00" + "time": "2024-12-05T09:17:50+00:00" }, { "name": "sebastian/global-state", - "version": "6.0.2", + "version": "7.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" + "reference": "3be331570a721f9a4b5917f4209773de17f747d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", - "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7", "shasum": "" }, "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -1383,7 +1468,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" }, "funding": [ { @@ -1391,33 +1476,33 @@ "type": "github" } ], - "time": "2024-03-02T07:19:19+00:00" + "time": "2024-07-03T04:57:36+00:00" }, { "name": "sebastian/lines-of-code", - "version": "2.0.2", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", - "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", "shasum": "" }, "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=8.1" + "nikic/php-parser": "^5.0", + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -1441,7 +1526,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" }, "funding": [ { @@ -1449,34 +1534,34 @@ "type": "github" } ], - "time": "2023-12-21T08:38:20+00:00" + "time": "2024-07-03T04:58:38+00:00" }, { "name": "sebastian/object-enumerator", - "version": "5.0.0", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" + "reference": "f5b498e631a74204185071eb41f33f38d64608aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", - "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa", "shasum": "" }, "require": { - "php": ">=8.1", - "sebastian/object-reflector": "^3.0", - "sebastian/recursion-context": "^5.0" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -1498,7 +1583,8 @@ "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" }, "funding": [ { @@ -1506,32 +1592,32 @@ "type": "github" } ], - "time": "2023-02-03T07:08:32+00:00" + "time": "2024-07-03T05:00:13+00:00" }, { "name": "sebastian/object-reflector", - "version": "3.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", - "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -1553,7 +1639,8 @@ "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" }, "funding": [ { @@ -1561,32 +1648,32 @@ "type": "github" } ], - "time": "2023-02-03T07:06:18+00:00" + "time": "2024-07-03T05:01:32+00:00" }, { "name": "sebastian/recursion-context", - "version": "5.0.0", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "05909fb5bc7df4c52992396d0116aed689f93712" + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", - "reference": "05909fb5bc7df4c52992396d0116aed689f93712", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -1616,7 +1703,8 @@ "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" }, "funding": [ { @@ -1624,32 +1712,32 @@ "type": "github" } ], - "time": "2023-02-03T07:05:40+00:00" + "time": "2024-07-03T05:10:34+00:00" }, { "name": "sebastian/type", - "version": "4.0.0", + "version": "5.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" + "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", - "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/461b9c5da241511a2a0e8f240814fb23ce5c0aac", + "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -1672,7 +1760,8 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/5.1.0" }, "funding": [ { @@ -1680,29 +1769,29 @@ "type": "github" } ], - "time": "2023-02-03T07:10:45+00:00" + "time": "2024-09-17T13:12:04+00:00" }, { "name": "sebastian/version", - "version": "4.0.1", + "version": "5.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", - "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -1725,7 +1814,8 @@ "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" }, "funding": [ { @@ -1733,7 +1823,59 @@ "type": "github" } ], - "time": "2023-02-07T11:34:05+00:00" + "time": "2024-10-09T05:16:32+00:00" + }, + { + "name": "staabm/side-effects-detector", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + }, + "funding": [ + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2024-10-20T05:08:20+00:00" }, { "name": "theseer/tokenizer", @@ -1788,21 +1930,20 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { "php": "^8.1", "ext-ctype": "*", "ext-curl": "*", + "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", - "ext-simplexml": "*" - }, - "platform-dev": { - "ext-dom": "*", + "ext-simplexml": "*", "ext-xmlreader": "*", "ext-xmlwriter": "*" }, + "platform-dev": {}, "plugin-api-version": "2.6.0" } diff --git a/fhir_test_resources.tar.gz b/fhir_test_resources.tar.gz new file mode 100644 index 00000000..6d0fede5 Binary files /dev/null and b/fhir_test_resources.tar.gz differ diff --git a/files/constants.php b/files/constants.php index 0dab6d15..4923c055 100644 --- a/files/constants.php +++ b/files/constants.php @@ -20,14 +20,6 @@ define('PHPFHIR_ROOT_DIR', realpath(dirname(__DIR__))); define('PHPFHIR_BIN_DIR', realpath(__DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'bin')); define('PHPFHIR_DEFAULT_OUTPUT_DIR', realpath(PHPFHIR_ROOT_DIR . DIRECTORY_SEPARATOR . 'output')); -const PHPFHIR_OUTPUT_TMP_DIR = PHPFHIR_DEFAULT_OUTPUT_DIR . DIRECTORY_SEPARATOR . 'tmp'; -const PHPFHIR_FHIR_VALIDATION_JAR = PHPFHIR_BIN_DIR . DIRECTORY_SEPARATOR . 'validator_cli.jar'; - -// format regex -const PHPFHIR_VARIABLE_NAME_REGEX = '{^[a-zA-Z_][a-zA-Z0-9_]*$}S'; -const PHPFHIR_FUNCTION_NAME_REGEX = '{^[a-zA-Z_][a-zA-Z0-9_]*$}S'; -const PHPFHIR_CLASSNAME_REGEX = '{^[a-zA-Z_][a-zA-Z0-9_]*$}S'; -const PHPFHIR_NAMESPACE_REGEX = '{^[a-zA-Z][a-zA-Z0-9_]*(\\\[a-zA-Z0-9_]+)*[a-zA-Z0-9_]$}'; // type suffixes const PHPFHIR_PRIMITIVE_SUFFIX = '-primitive'; @@ -37,7 +29,7 @@ const PHPFHIR_XHTML_DIV = 'xhtml:div'; // raw type -const PHPFHIR_XHTML_TYPE_NAME = 'Xhtml'; +const PHPFHIR_XHTML_TYPE_NAME = 'XHTML'; const PHPFHIR_XHTML_TYPE_DESCRIPTION = 'XHTML type used in special cases'; // FHIR XML NS @@ -59,53 +51,87 @@ const PHPFHIR_NAMESPACE_TRIM_CUTSET = " \t\n\r\0\x0b\\/"; define('PHPFHIR_TEMPLATE_DIR', realpath(__DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'template')); -// "file" directory. will move at some point. -const PHPFHIR_TEMPLATE_FILE_DIR = PHPFHIR_TEMPLATE_DIR . DIRECTORY_SEPARATOR . 'file'; - // Core interfaces, traits, and classes const PHPFHIR_TEMPLATE_CORE_DIR = PHPFHIR_TEMPLATE_DIR . DIRECTORY_SEPARATOR . 'core'; -// Type rendering -const PHPFHIR_TEMPLATE_TYPES_DIR = PHPFHIR_TEMPLATE_DIR . DIRECTORY_SEPARATOR . 'types'; -const PHPFHIR_TEMPLATE_TYPES_PROPERTIES_DIR = PHPFHIR_TEMPLATE_TYPES_DIR . DIRECTORY_SEPARATOR . 'properties'; -const PHPFHIR_TEMPLATE_TYPES_METHODS_DIR = PHPFHIR_TEMPLATE_TYPES_DIR . DIRECTORY_SEPARATOR . 'methods'; -const PHPFHIR_TEMPLATE_TYPES_CONSTRUCTORS_DIR = PHPFHIR_TEMPLATE_TYPES_METHODS_DIR . DIRECTORY_SEPARATOR . 'constructors'; -const PHPFHIR_TEMPLATE_TYPES_SERIALIZATION_DIR = PHPFHIR_TEMPLATE_TYPES_DIR . DIRECTORY_SEPARATOR . 'serialization'; -const PHPFHIR_TEMPLATE_TYPES_VALIDATION_DIR = PHPFHIR_TEMPLATE_TYPES_DIR . DIRECTORY_SEPARATOR . 'validation'; +// Version interfaces, traits, and enums +const PHHPFHIR_TEMPLATE_VERSIONS_DIR = PHPFHIR_TEMPLATE_DIR . DIRECTORY_SEPARATOR . 'versions'; +const PHPFHIR_TEMPLATE_VERSIONS_CORE_DIR = PHHPFHIR_TEMPLATE_VERSIONS_DIR . DIRECTORY_SEPARATOR . 'core'; + +// Version type rendering +const PHPFHIR_TEMPLATE_VERSION_TYPES_DIR = PHHPFHIR_TEMPLATE_VERSIONS_DIR . DIRECTORY_SEPARATOR . 'types'; +const PHPFHIR_TEMPLATE_VERSION_TYPES_PROPERTIES_DIR = PHPFHIR_TEMPLATE_VERSION_TYPES_DIR . DIRECTORY_SEPARATOR . 'properties'; +const PHPFHIR_TEMPLATE_VERSION_TYPES_METHODS_DIR = PHPFHIR_TEMPLATE_VERSION_TYPES_DIR . DIRECTORY_SEPARATOR . 'methods'; +const PHPFHIR_TEMPLATE_VERSION_TYPES_CONSTRUCTORS_DIR = PHPFHIR_TEMPLATE_VERSION_TYPES_METHODS_DIR . DIRECTORY_SEPARATOR . 'constructors'; +const PHPFHIR_TEMPLATE_VERSION_TYPES_SERIALIZATION_DIR = PHPFHIR_TEMPLATE_VERSION_TYPES_DIR . DIRECTORY_SEPARATOR . 'serialization'; +const PHPFHIR_TEMPLATE_VERSION_TYPES_VALIDATION_DIR = PHPFHIR_TEMPLATE_VERSION_TYPES_DIR . DIRECTORY_SEPARATOR . 'validation'; -// Fhir type test templates -const PHPFHIR_TEMPLATE_TYPE_TESTS_DIR = PHPFHIR_TEMPLATE_TYPES_DIR . DIRECTORY_SEPARATOR . 'tests'; +// FHIR type test templates +const PHPFHIR_TEMPLATE_VERSION_TYPE_TESTS_DIR = PHPFHIR_TEMPLATE_VERSION_TYPES_DIR . DIRECTORY_SEPARATOR . 'tests'; // Core class names -const PHPFHIR_CLASSNAME_AUTOLOADER = 'PHPFHIRAutoloader'; -const PHPFHIR_CLASSNAME_CONFIG = 'PHPFHIRConfig'; -const PHPFHIR_CLASSNAME_RESPONSE_PARSER = 'PHPFHIRResponseParser'; -const PHPFHIR_CLASSNAME_CONSTANTS = 'PHPFHIRConstants'; -const PHPFHIR_CLASSNAME_TYPEMAP = 'PHPFHIRTypeMap'; -const PHPFHIR_CLASSNAME_DEBUG_CLIENT = 'PHPFHIRDebugClient'; -const PHPFHIR_CLASSNAME_DEBUG_CLIENT_RESPONSE = 'PHPFHIRDebugClientResponse'; -const PHPFHIR_CLASSNAME_XML_WRITER = 'PHPFHIRXmlWriter'; +const PHPFHIR_CLASSNAME_AUTOLOADER = 'Autoloader'; +const PHPFHIR_CLASSNAME_FACTORY_CONFIG = 'FactoryConfig'; +const PHPFHIR_CLASSNAME_FACTORY_VERSION_CONFIG = 'FactoryVersionConfig'; +const PHPFHIR_CLASSNAME_FACTORY = 'Factory'; +const PHPFHIR_CLASSNAME_VERSION_CONFIG = 'VersionConfig'; +const PHPFHIR_CLASSNAME_UNSERIALIZE_CONFIG = 'UnserializeConfig'; +const PHPFHIR_CLASSNAME_SERIALIZE_CONFIG = 'SerializeConfig'; +const PHPFHIR_CLASSNAME_RESPONSE_PARSER = 'ResponseParser'; +const PHPFHIR_CLASSNAME_CONSTANTS = 'Constants'; +const PHPFHIR_CLASSNAME_API_CLIENT = 'APIClient'; +const PHPFHIR_CLASSNAME_API_CLIENT_CONFIG = 'APIClientConfig'; +const PHPFHIR_CLASSNAME_API_CLIENT_REQUEST = 'APIClientRequest'; +const PHPFHIR_CLASSNAME_API_CLIENT_RESPONSE = 'APIClientResponse'; +const PHPFHIR_CLASSNAME_API_CLIENT_RESPONSE_HEADERS = 'APIClientResponseHeaders'; +const PHPFHIR_CLASSNAME_XML_WRITER = 'XMLWriter'; +const PHPFHIR_CLASSNAME_VALIDATOR = 'Validator'; // Core interface names -const PHPFHIR_INTERFACE_TYPE = 'PHPFHIRTypeInterface'; -const PHPFHIR_INTERFACE_CONTAINED_TYPE = 'PHPFHIRContainedTypeInterface'; -const PHPFHIR_INTERFACE_COMMENT_CONTAINER = 'PHPFHIRCommentContainerInterface'; -const PHPFHIR_INTERFACE_PRIMITIVE_TYPE = 'PHPFHIRPrimitiveTypeInterface'; +const PHPFHIR_INTERFACE_TYPE = 'TypeInterface'; +const PHPFHIR_INTERFACE_CONTAINED_TYPE = 'ContainedTypeInterface'; +const PHPFHIR_INTERFACE_COMMENT_CONTAINER = 'CommentContainerInterface'; +const PHPFHIR_INTERFACE_PRIMITIVE_TYPE = 'PrimitiveTypeInterface'; +const PHPFHIR_INTERFACE_VERSION = 'VersionInterface'; +const PHPFHIR_INTERFACE_VERSION_CONFIG = 'VersionConfigInterface'; +const PHPFHIR_INTERFACE_VERSION_TYPE_MAP = 'VersionTypeMapInterface'; +const PHPFHIR_INTERFACE_API_CLIENT = 'APIClientInterface'; // Core traits -const PHPFHIR_TRAIT_COMMENT_CONTAINER = 'PHPFHIRCommentContainerTrait'; -const PHPFHIR_TRAIT_VALIDATION_ASSERTIONS = 'PHPFHIRValidationAssertionsTrait'; -const PHPFHIR_TRAIT_CHANGE_TRACKING = 'PHPFHIRChangeTrackingTrait'; -const PHPFHIR_TRAIT_SOURCE_XMLNS = 'PHPFHIRSourceXmlNamespaceTrait'; +const PHPFHIR_TRAIT_COMMENT_CONTAINER = 'CommentContainerTrait'; +const PHPFHIR_TRAIT_SOURCE_XMLNS = 'SourceXMLNamespaceTrait'; // Core enums -const PHPFHIR_ENUM_CONFIG_KEY = 'PHPFHIRConfigKeyEnum'; -const PHPFHIR_ENUM_TYPE = 'PHPFHIRTypeEnum'; -const PHPFHIR_ENUM_API_FORMAT = 'PHPFHIRApiFormatEnum'; -const PHPFHIR_ENUM_XML_LOCATION_ENUM = 'PHPFHIRXmlLocationEnum'; - -// validation constants +const PHPFHIR_ENUM_FACTORY_VERSION_CONFIG_KEY = 'FactoryVersionConfigKey'; +const PHPFHIR_ENUM_FACTORY_CONFIG_KEY = 'FactoryConfigKeyEnum'; +const PHPFHIR_ENUM_VERSION_CONFIG_KEY = 'VersionConfigKeyEnum'; +const PHPFHIR_ENUM_UNSERIALIZE_CONFIG_KEY = 'UnserializeConfigKeyEnum'; +const PHPFHIR_ENUM_SERIALIZE_CONFIG_KEY = 'SerializeConfigKeyEnum'; +const PHPFHIR_ENUM_VERSION = 'VersionEnum'; +const PHPFHIR_ENUM_API_FORMAT = 'APIFormatEnum'; +const PHPFHIR_ENUM_XML_LOCATION = 'XMLLocationEnum'; +const PHPFHIR_ENUM_API_RESOURCE_LIST = 'APIResourceListEnum'; +const PHPFHIR_ENUM_API_SORT = 'APISortEnum'; + +// Core exceptions +const PHPFHIR_EXCEPTION_ABSTRACT_API_ERROR = 'AbstractAPIErrorException'; +const PHPFHIR_EXCEPTION_API_CURL_ERROR = 'APICURLErrorException'; +const PHPFHIR_EXCEPTION_API_UNEXPECTED_RESPONSE_CODE = 'APIUnexpectedResponseCodeException'; + +// Version class names +const PHPFHIR_CLASSNAME_VERSION = 'Version'; +const PHPFHIR_CLASSNAME_VERSION_CONSTANTS = 'VersionConstants'; +const PHPFHIR_CLASSNAME_VERSION_TYPE_MAP = 'VersionTypeMap'; +const PHPFHIR_CLASSNAME_VERSION_API_CLIENT = 'VersionAPIClient'; + +// Version interface names +const PHPFHIR_INTERFACE_VERSION_CONTAINED_TYPE = 'VersionContainedTypeInterface'; + +// Version enums +const PHPFHIR_ENUM_VERSION_TYPE = 'VersionTypeEnum'; + +// Validation constants const PHPFHIR_VALIDATION_ENUM = 'enum'; const PHPFHIR_VALIDATION_ENUM_NAME = 'VALIDATE_ENUM'; const PHPFHIR_VALIDATION_MIN_LENGTH = 'min_length'; @@ -119,17 +145,21 @@ const PHPFHIR_VALIDATION_MAX_OCCURS = 'max_occurs'; const PHPFHIR_VALIDATION_MAX_OCCURS_NAME = 'VALIDATE_MAX_OCCURS'; -// static test type, namespace, and class values. -const PHPFHIR_TESTS_NAMESPACE_BASE = 'PHPFHIRTests'; +// Static test type, namespace, and class values. +const PHPFHIR_TESTS_NAMESPACE_BASE = 'Tests'; const PHPFHIR_TESTS_NAMESPACE_UNIT = PHPFHIR_TESTS_NAMESPACE_BASE . '\\Unit'; const PHPFHIR_TESTS_NAMESPACE_INTEGRATION = PHPFHIR_TESTS_NAMESPACE_BASE . '\\Integration'; const PHPFHIR_TESTS_NAMESPACE_VALIDATION = PHPFHIR_TESTS_NAMESPACE_BASE . '\\Validation'; const PHPFHIR_TEST_CLASSNAME_CONSTANTS = PHPFHIR_CLASSNAME_CONSTANTS . 'Test'; const PHPFHIR_TEST_CLASSNAME_AUTOLOADER = PHPFHIR_CLASSNAME_AUTOLOADER . 'Test'; -const PHPFHIR_TEST_CLASSNAME_TYPEMAP = PHPFHIR_CLASSNAME_TYPEMAP . 'Test'; -const PHPFHIR_TEST_CLASSNAME_CONFIG = PHPFHIR_CLASSNAME_CONFIG . 'Test'; +const PHPFHIR_TEST_CLASSNAME_TYPE_MAP = PHPFHIR_CLASSNAME_VERSION_TYPE_MAP . 'Test'; +const PHPFHIR_TEST_CLASSNAME_FACTORY_CONFIG = PHPFHIR_CLASSNAME_FACTORY_CONFIG . 'Test'; + +// Test constant names +const PHPFHIR_TEST_CONSTANT_INTEGRATION_ENDPOINT = 'PHPFHIR_TEST_INTEGRATION_ENDPOINT'; +const PHPFHIR_TEST_CONSTANT_RESOURCE_DOWNLOAD_DIR = 'PHPFHIR_TEST_RESOURCE_DOWNLOAD_DIR'; -// date & time formats +// Date & time formats const PHPFHIR_DATE_FORMAT_YEAR = 'Y'; const PHPFHIR_DATE_FORMAT_YEAR_MONTH = 'Y-m'; const PHPFHIR_DATE_FORMAT_YEAR_MONTH_DAY = 'Y-m-d'; diff --git a/files/funcs.php b/files/funcs.php index 0c354db8..aa9c22d8 100644 --- a/files/funcs.php +++ b/files/funcs.php @@ -16,8 +16,6 @@ * limitations under the License. */ -use DCarbone\PHPFHIR\Config\VersionConfig; - /** * require_with is used to ensure a clean context per required template file. * @@ -38,14 +36,67 @@ function require_with(string $requiredFile, array $vars): mixed ) ); } - if (!isset($config) || !($config instanceof VersionConfig)) { - throw new \LogicException(sprintf( - 'Refusing to require "%s" as you didn\'t provide \'config\' => $config(%s)', - $requiredFile, - VersionConfig::class, - )); - } // unset vars defined by this func unset($vars, $num); return require $requiredFile; } + +/** + * Makes array var exporting less terrible. + * + * @param mixed $var root var + * @param int $indent current indent level, only used during array exporting + * @param bool $indentFirst if true, indents the first line of the array + * @param int $indentSize number of spaces to output per indent level + * @return string + */ +function pretty_var_export(mixed $var, int $indent = 0, bool $indentFirst = false, int $indentSize = 4): string +{ + if (!is_array($var)) { + return var_export($var, true); + } + + if ([] === $var) { + return '[]'; + } + + $out = sprintf("%s[", str_repeat(' ', $indentFirst ? $indent * $indentSize : 0)); + foreach ($var as $k => $v) { + $literal = false; + $indentFirst = is_int($k); + // TODO: if it works, is it really a shit idea? Probably. + if ('libxmlOptMask' === $k) { + $k = 'libxmlOpts'; + $literal = true; + } else if ('xhtmlLibxmlOptMask' === $k) { + $k = 'xhtmlLibxmlOpts'; + $literal = true; + } + $out = sprintf("%s\n%s%s => %s,", + $out, + str_repeat(' ', ($indent + 1) * $indentSize), + var_export($k, true), + $literal ? $v : pretty_var_export($v, $indent + 1, $indentFirst, $indentSize), + ); + } + return sprintf("%s\n%s]", $out, str_repeat(' ', $indent * $indentSize)); +} + +/** + * Sloppy little function to ensure filenames are consistent or whatever + * + * @param string $bit + * @return string + */ +function classFilenameFormat(string $bit): string +{ + return match ($bit) { + 'api' => 'API', + 'fhir' => 'FHIR', + 'xhtml' => 'XHTML', + 'xml' => 'XML', + 'http' => 'HTTP', + 'curl' => 'CURL', + default => ucfirst($bit), + }; +} diff --git a/output/HL7/.gitignore b/output/.gitignore similarity index 100% rename from output/HL7/.gitignore rename to output/.gitignore diff --git a/output/tmp/.gitignore b/output/tmp/.gitignore deleted file mode 100644 index c96a04f0..00000000 --- a/output/tmp/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml index f6a5e458..baf546e5 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,60 +1,27 @@ - + - - ./output/HL7/FHIR/DSTU1/PHPFHIRTests/PHPFHIRConstantsTest.php - ./output/HL7/FHIR/DSTU1/PHPFHIRTests/PHPFHIRTypeMapTest.php - ./output/HL7/FHIR/DSTU1/PHPFHIRTests/PHPFHIRConfigtest.php + + ./output/DCarbone/PHPFHIRGenerated/Tests - - ./output/HL7/FHIR/DSTU1/PHPFHIRTests/Unit + + ./output/DCarbone/PHPFHIRGenerated/Versions/DSTU2/Tests - - ./output/HL7/FHIR/DSTU2/PHPFHIRTests/PHPFHIRConstantsTest.php - ./output/HL7/FHIR/DSTU2/PHPFHIRTests/PHPFHIRTypeMapTest.php - ./output/HL7/FHIR/DSTU2/PHPFHIRTests/PHPFHIRConfigtest.php + + ./output/DCarbone/PHPFHIRGenerated/Versions/STU3/Tests - - ./output/HL7/FHIR/DSTU2/PHPFHIRTests/Unit + + ./output/DCarbone/PHPFHIRGenerated/Versions/R4/Tests - - ./output/HL7/FHIR/DSTU2/PHPFHIRTests/Integration - - - ./output/HL7/FHIR/STU3/PHPFHIRTests/PHPFHIRConstantsTest.php - ./output/HL7/FHIR/STU3/PHPFHIRTests/PHPFHIRTypeMapTest.php - ./output/HL7/FHIR/STU3/PHPFHIRTests/PHPFHIRConfigtest.php - - - ./output/HL7/FHIR/STU3/PHPFHIRTests/Unit - - - ./output/HL7/FHIR/STU3/PHPFHIRTests/Integration - - - ./output/HL7/FHIR/R4/PHPFHIRTests/PHPFHIRConstantsTest.php - ./output/HL7/FHIR/R4/PHPFHIRTests/PHPFHIRTypeMapTest.php - ./output/HL7/FHIR/R4/PHPFHIRTests/PHPFHIRConfigtest.php - - - ./output/HL7/FHIR/R4/PHPFHIRTests/Unit - - - ./output/HL7/FHIR/R4/PHPFHIRTests/Integration - - - ./output/HL7/FHIR/R5/PHPFHIRTests/PHPFHIRConstantsTest.php - ./output/HL7/FHIR/R5/PHPFHIRTests/PHPFHIRTypeMapTest.php - ./output/HL7/FHIR/R5/PHPFHIRTests/PHPFHIRConfigtest.php - - - ./output/HL7/FHIR/R5/PHPFHIRTests/Unit - - - ./output/HL7/FHIR/R5/PHPFHIRTests/Integration + + ./output/DCarbone/PHPFHIRGenerated/Versions/R5/Tests diff --git a/phpunit/Core.xml b/phpunit/Core.xml new file mode 100644 index 00000000..5589aaae --- /dev/null +++ b/phpunit/Core.xml @@ -0,0 +1,25 @@ + + + + + + + + ../output/DCarbone/PHPFHIRGenerated/Tests + + + + + ./src + + + diff --git a/phpunit/DSTU1.xml b/phpunit/DSTU1.xml index efa36b8d..71205f67 100644 --- a/phpunit/DSTU1.xml +++ b/phpunit/DSTU1.xml @@ -1,21 +1,25 @@ - - - - - - - ../output/HL7/FHIR/DSTU1/PHPFHIRTests/PHPFHIRConstantsTest.php - ../output/HL7/FHIR/DSTU1/PHPFHIRTests/PHPFHIRTypeMapTest.php - ../output/HL7/FHIR/DSTU1/PHPFHIRTests/PHPFHIRConfigTest.php - - - ../output/HL7/FHIR/DSTU1/PHPFHIRTests/Unit - - - - - ./src - - + + + + + + + ../output/DCarbone/PHPFHIRGenerated/Versions/DSTU1/Tests + + + + + ./src + + diff --git a/phpunit/DSTU2.xml b/phpunit/DSTU2.xml index bd41dfbd..bde12798 100644 --- a/phpunit/DSTU2.xml +++ b/phpunit/DSTU2.xml @@ -1,24 +1,26 @@ - - - - - - - ../output/HL7/FHIR/DSTU2/PHPFHIRTests/PHPFHIRConstantsTest.php - ../output/HL7/FHIR/DSTU2/PHPFHIRTests/PHPFHIRTypeMapTest.php - ../output/HL7/FHIR/DSTU2/PHPFHIRTests/PHPFHIRConfigTest.php - - - ../output/HL7/FHIR/DSTU2/PHPFHIRTests/Unit - - - ../output/HL7/FHIR/DSTU2/PHPFHIRTests/Integration - - - - - ../src - - + + + + + + + + ../output/DCarbone/PHPFHIRGenerated/Versions/DSTU2/Tests + + + + + ../src + + diff --git a/phpunit/R4.xml b/phpunit/R4.xml index 55e664eb..d6a81381 100644 --- a/phpunit/R4.xml +++ b/phpunit/R4.xml @@ -1,24 +1,26 @@ - - - - - - - ../output/HL7/FHIR/R4/PHPFHIRTests/PHPFHIRConstantsTest.php - ../output/HL7/FHIR/R4/PHPFHIRTests/PHPFHIRTypeMapTest.php - ../output/HL7/FHIR/R4/PHPFHIRTests/PHPFHIRConfigTest.php - - - ../output/HL7/FHIR/R4/PHPFHIRTests/Unit - - - ../output/HL7/FHIR/R4/PHPFHIRTests/Integration - - - - - ../src - - + + + + + + + + ../output/DCarbone/PHPFHIRGenerated/Versions/R4/Tests + + + + + ../src + + diff --git a/phpunit/R4B.xml b/phpunit/R4B.xml new file mode 100644 index 00000000..3f32cfeb --- /dev/null +++ b/phpunit/R4B.xml @@ -0,0 +1,26 @@ + + + + + + + + + ../output/DCarbone/PHPFHIRGenerated/Versions/R4B/Tests + + + + + ../src + + + diff --git a/phpunit/R5.xml b/phpunit/R5.xml index a794fe1e..dd294fb3 100644 --- a/phpunit/R5.xml +++ b/phpunit/R5.xml @@ -1,24 +1,26 @@ - - - - - - - ../output/HL7/FHIR/R5/PHPFHIRTests/PHPFHIRConstantsTest.php - ../output/HL7/FHIR/R5/PHPFHIRTests/PHPFHIRTypeMapTest.php - ../output/HL7/FHIR/R5/PHPFHIRTests/PHPFHIRConfigTest.php - - - ../output/HL7/FHIR/R5/PHPFHIRTests/Unit - - - ../output/HL7/FHIR/R5/PHPFHIRTests/Integration - - - - - ../src - - + + + + + + + + ../output/DCarbone/PHPFHIRGenerated/Versions/R5/Tests + + + + + ../src + + diff --git a/phpunit/STU3.xml b/phpunit/STU3.xml index 1b25cbb4..27ce8260 100644 --- a/phpunit/STU3.xml +++ b/phpunit/STU3.xml @@ -1,24 +1,26 @@ - - - - - - - ../output/HL7/FHIR/STU3/PHPFHIRTests/PHPFHIRConstantsTest.php - ../output/HL7/FHIR/STU3/PHPFHIRTests/PHPFHIRTypeMapTest.php - ../output/HL7/FHIR/STU3/PHPFHIRTests/PHPFHIRConfigTest.php - - - ../output/HL7/FHIR/STU3/PHPFHIRTests/Unit - - - ../output/HL7/FHIR/STU3/PHPFHIRTests/Integration - - - - - ../src - - + + + + + + + + ../output/DCarbone/PHPFHIRGenerated/Versions/STU3/Tests + + + + + ../src + + diff --git a/phpunit/bootstrap.php b/phpunit/bootstrap.php new file mode 100644 index 00000000..6011743c --- /dev/null +++ b/phpunit/bootstrap.php @@ -0,0 +1,51 @@ +config = $config; - $this->definition = $definition; $this->log = $config->getLogger(); } - - /** - * @return \DCarbone\PHPFHIR\Definition - */ - public function getDefinition(): Definition - { - $log = $this->config->getLogger(); - - if (!$this->definition->isDefined()) { - $log->startBreak('XSD Parsing'); - $this->definition->buildDefinition(); - $log->endBreak('XSD Parsing'); - } - - return $this->definition; - } - /** * Generate FHIR object classes based on XSD + * + * @param bool $coreFiles If true, will generate core PHPFHIR classes, interfaces, traits, and enums. + * @param null|array $versionNames Array of version names to limit generation to. If null, all configured versions will be generated. * @throws \ErrorException + * @throws \Exception */ - public function render(): void - { - $this->prerender(); - - $this->writeCoreTypeFiles(); - - $this->writeFhirTypeFiles(); - - if (!$this->config->isSkipTests()) { - $this->writeFhirTestFiles(); - } - } - - /** - * Generate FHIR classes only. - * @throws \ErrorException - */ - public function writeFhirTypeFiles(): void + public function render(bool $coreFiles = true, null|array $versionNames = null): void { // register custom error handler to force explosions. set_error_handler(function ($errNum, $errStr, $errFile, $errLine) { throw new \ErrorException($errStr, $errNum, 1, $errFile, $errLine); }); - $log = $this->config->getLogger(); - - $this->prerender(); - - $definition = $this->getDefinition(); - - $types = $definition->getTypes(); - - $log->startBreak('FHIR Class Generation'); - foreach ($types->getIterator() as $type) { - $log->debug("Generating class for type {$type}..."); + // write php-fhir core files + if ($coreFiles) { + $this->writeCoreFiles( + $this->config->getCoreFiles(), + ['config' => $this->config] + ); + } - // TODO(@dcarbone): revisit with template system refactor - if (PHPFHIR_XHTML_TYPE_NAME === $type->getFHIRName()) { - $classDefinition = Templates::renderXhtmlTypeClass($this->config, $types, $type); - } else { - $classDefinition = Templates::renderFhirTypeClass($this->config, $types, $type); - } - $filepath = FileUtils::buildTypeFilePath($this->config, $type); - if (!file_put_contents($filepath, $classDefinition)) { - throw new \RuntimeException( - sprintf( - 'Unable to write Type %s class definition to file %s', - $filepath, - $type - ) - ); - } + // if null, default to all versions. + if (null === $versionNames) { + $versionNames = $this->config->listVersions(); } - $log->endBreak('FHIR Class Generation'); - restore_error_handler(); + // write fhir version files + $this->writeFHIRVersionFiles(...$versionNames); + + // write fhir version test classes + $this->writeFHIRVersionTestFiles(...$versionNames); } /** - * Generate Test classes only. Tests will not pass if FHIR classes have not been built. + * Generate FHIR version files. + * + * @throws \Exception */ - public function writeFhirTestFiles(): void + public function writeFHIRVersionFiles(string ...$versionNames): void { $log = $this->config->getLogger(); - $this->prerender(); + foreach ($versionNames as $versionName) { + $version = $this->config->getVersion($versionName); - $definition = $this->getDefinition(); - $types = $definition->getTypes(); + $log->startBreak(sprintf('FHIR Version %s Code Generation', $version->getName())); - $log->startBreak('Test Class Generation'); + // write version fhir type files + $definition = $version->getDefinition(); - $testTypes = [TestType::UNIT]; - if (null !== $this->config->getTestEndpoint()) { - $testTypes[] = TestType::INTEGRATION; - $testTypes[] = TestType::VALIDATION; - } - foreach ($types->getIterator() as $type) { - - // skip "abstract" types - if ($type->isAbstract()) { - continue; + if (!$definition->isDefined()) { + $log->startBreak('XSD Parsing'); + $definition->buildDefinition(); + $log->endBreak('XSD Parsing'); } - foreach ($testTypes as $testType) { - // only render integration and validation tests if this is a "resource" type - if (!$type->isResourceType() && $testType->isOneOf(TestType::INTEGRATION, TestType::VALIDATION)) { - continue; - } + $types = $definition->getTypes(); + + // write version core files + $this->writeCoreFiles( + $version->getCoreFiles(), + [ + 'version' => $version, + 'types' => $definition->getTypes(), + ] + ); - $log->debug("Generated {$testType->value} test class for type {$type}..."); - $classDefinition = Templates::renderFhirTypeClassTest($this->config, $types, $type, $testType); - $filepath = FileUtils::buildTypeTestFilePath($this->config, $type, $testType); - if (false === file_put_contents($filepath, $classDefinition)) { - throw new RuntimeException( + foreach ($types->getGenerator() as $type) { + /** @var \DCarbone\PHPFHIR\Version\Definition\Type $type */ + $log->debug("Generating class for type {$type}..."); + + // TODO(@dcarbone): revisit with template system refactor + if (PHPFHIR_XHTML_TYPE_NAME === $type->getFHIRName()) { + $classDefinition = Templates::renderVersionXHTMLTypeClass($version, $types, $type); + } else { + $classDefinition = Templates::renderVersionTypeClass($version, $types, $type); + } + $filepath = FileUtils::buildTypeFilePath($version, $type); + if (!file_put_contents($filepath, $classDefinition)) { + throw new \RuntimeException( sprintf( 'Unable to write Type %s class definition to file %s', $filepath, @@ -179,95 +133,89 @@ public function writeFhirTestFiles(): void ); } } + $log->endBreak(sprintf('FHIR Version %s Code Generation', $version->getName())); } - - $log->endBreak('Test Class Generation'); + restore_error_handler(); } /** - * Commands to run prior to class generation + * Generate Test classes only. Tests will not pass if FHIR classes have not been built. + * + * @throws \Exception */ - protected function prerender(): void + public function writeFHIRVersionTestFiles(string ...$versionNames): void { - // Initialize some classes and things. - if (!$this->preGenerationCompleted) { - $this->log->startBreak('Prerender'); - $this->log->info('Compiling Copyrights...'); - CopyrightUtils::compileCopyrights($this->config); - $this->log->endBreak('Prerender'); - $this->preGenerationCompleted = true; - } - } + $log = $this->config->getLogger(); - /** - * @return \RecursiveIteratorIterator - */ - protected function getCoreTypeFileIterator(): \RecursiveIteratorIterator - { - return new \RecursiveIteratorIterator( - new \RecursiveDirectoryIterator( - PHPFHIR_TEMPLATE_CORE_DIR, - \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS - ), - ); + foreach ($versionNames as $versionName) { + $version = $this->config->getVersion($versionName); + + $log->startBreak(sprintf('FHIR Version %s Test Generation', $version->getName())); + + $definition = $version->getDefinition(); + + if (!$definition->isDefined()) { + $log->startBreak('XSD Parsing'); + $definition->buildDefinition(); + $log->endBreak('XSD Parsing'); + } + + $types = $definition->getTypes(); + + $log->startBreak('Test Class Generation'); + + $testTypes = [ + TestTypeEnum::UNIT, + TestTypeEnum::INTEGRATION, +// TestTypeEnum::VALIDATION, + ]; + foreach ($types->getGenerator() as $type) { + if ($type->isAbstract()) { + continue; + } + + foreach ($testTypes as $testType) { + // only render integration and validation tests if this is a "resource" type + if (!$type->isResourceType() && $testType->isOneOf(TestTypeEnum::INTEGRATION, TestTypeEnum::VALIDATION)) { + continue; + } + + $log->debug("Generated {$testType->value} test class for type {$type}..."); + $classDefinition = Templates::renderVersionTypeClassTest($version, $types, $type, $testType); + $filepath = FileUtils::buildTypeTestFilePath($version, $type, $testType); + if (false === file_put_contents($filepath, $classDefinition)) { + throw new \RuntimeException( + sprintf( + 'Unable to write Type %s class definition to file %s', + $filepath, + $type + ) + ); + } + } + } + $log->endBreak(sprintf('FHIR Version %s Test Generation', $version->getName())); + } } /** - * TODO(@dcarbone): refactor generation system, too sloppy right now. - * * Renders core PHP FHIR type classes, interfaces, traits, and enums. * + * @param \DCarbone\PHPFHIR\CoreFiles $coreFiles + * @param array $templateArgs * @return void */ - protected function writeCoreTypeFiles(): void + public function writeCoreFiles(CoreFiles $coreFiles, array $templateArgs): void { $this->log->startBreak('Core Files'); - // localize types - $types = $this->getDefinition()->getTypes(); - // render each core file - foreach($this->getCoreTypeFileIterator() as $fpath => $fi) { - /** @var $fi \SplFileInfo */ - - // get filename - $fname = basename($fpath); - // store "type" - $ftype = substr($fname, 0, strpos($fname, '_')); - // trim "type" and ".php" - $fname = strstr(substr($fname, strpos($fname,'_') + 1), '.', true); - // classname suffix - $suffix = ucfirst($ftype); - - // define "default" namespace - $ns = $this->config->getFullyQualifiedName(true); - - if ('class' === $ftype) { - // 'class' types do have suffix - $suffix = ''; - } else if ('test' === $ftype) { - // test classes have different namespace - $ns = $this->config->getFullyQualifiedTestsName(TestType::BASE, true); - // trim subtype - $fname = substr($fname, strpos($fname, '_') + 1); - } - - // construct class filename - $cname = sprintf( - 'PHPFHIR%s%s', - implode('', array_map('ucfirst', explode('_', $fname))), - $suffix - ); - - // write file to disk + foreach ($coreFiles->getIterator() as $coreFile) { + /** @var \DCarbone\PHPFHIR\CoreFile $coreFile */ $this->writeFile( - FileUtils::buildGenericFilePath( - $this->config, - $ns, - $cname, - ), - Templates::renderCoreType($fpath, $this->config, $types) + $coreFile->getFilepath(), + Templates::renderCoreTemplate($coreFile->getTemplateFile(), $templateArgs) ); } @@ -283,7 +231,7 @@ private function writeFile(string $filePath, string $fileContents): void $this->log->info(sprintf('Writing %s...', $filePath)); $b = file_put_contents($filePath, $fileContents); if (false === $b) { - throw new RuntimeException( + throw new \RuntimeException( sprintf( 'Unable to write "%s"', $filePath diff --git a/src/Builder/TypeBuilder.php b/src/Builder/TypeBuilder.php index dd9eeeeb..082a9156 100644 --- a/src/Builder/TypeBuilder.php +++ b/src/Builder/TypeBuilder.php @@ -18,47 +18,48 @@ * limitations under the License. */ -use DCarbone\PHPFHIR\Config\VersionConfig; -use DCarbone\PHPFHIR\Definition\Property; -use DCarbone\PHPFHIR\Definition\Type; +use DCarbone\PHPFHIR\Config; +use DCarbone\PHPFHIR\Version\Definition\Property; +use DCarbone\PHPFHIR\Version\Definition\Type; +use DCarbone\PHPFHIR\Version; use SimpleXMLElement; -/** - * Class TypeBuilder - * @package DCarbone\PHPFHIR\Definition\Builder - */ abstract class TypeBuilder { /** - * @param \DCarbone\PHPFHIR\Config\VersionConfig $config + * @param \DCarbone\PHPFHIR\Config $config + * @param \DCarbone\PHPFHIR\Version $version * @param string $fhirName * @param \SimpleXMLElement $sxe * @param string $sourceFilename - * @return \DCarbone\PHPFHIR\Definition\Type + * @return \DCarbone\PHPFHIR\Version\Definition\Type */ private static function buildDefaultType( - VersionConfig $config, + Config $config, + Version $version, string $fhirName, SimpleXMLElement $sxe, string $sourceFilename ): Type { - return new Type($config, $fhirName, $sxe, $sourceFilename); + return new Type($config, $version, $fhirName, $sxe, $sourceFilename); } /** - * @param \DCarbone\PHPFHIR\Config\VersionConfig $config + * @param \DCarbone\PHPFHIR\Config $config + * @param \DCarbone\PHPFHIR\Version $version * @param string $fhirName * @param \SimpleXMLElement $sxe * @param string $sourceFilename - * @return \DCarbone\PHPFHIR\Definition\Type + * @return \DCarbone\PHPFHIR\Version\Definition\Type */ private static function buildPrimitiveType( - VersionConfig $config, + Config $config, + Version $version, string $fhirName, SimpleXMLElement $sxe, string $sourceFilename ): Type { - $type = self::buildDefaultType($config, $fhirName, $sxe, $sourceFilename); + $type = self::buildDefaultType($config, $version, $fhirName, $sxe, $sourceFilename); $value = new Property($type, $sxe, $sourceFilename); $value->setName(PHPFHIR_VALUE_PROPERTY_NAME); $type->getLocalProperties()->addProperty($value); @@ -66,17 +67,18 @@ private static function buildPrimitiveType( } /** - * @param \DCarbone\PHPFHIR\Config\VersionConfig $config + * @param \DCarbone\PHPFHIR\Config $config + * @param \DCarbone\PHPFHIR\Version $version * @param string $fhirName * @param \SimpleXMLElement $sxe * @param string $sourceFilename - * @return \DCarbone\PHPFHIR\Definition\Type + * @return \DCarbone\PHPFHIR\Version\Definition\Type */ - public static function build(VersionConfig $config, string $fhirName, SimpleXMLElement $sxe, string $sourceFilename): Type + public static function build(Config $config, Version $version, string $fhirName, SimpleXMLElement $sxe, string $sourceFilename): Type { if (str_contains($fhirName, PHPFHIR_PRIMITIVE_SUFFIX) || str_contains($fhirName, PHPFHIR_LIST_SUFFIX)) { - return self::buildPrimitiveType($config, $fhirName, $sxe, $sourceFilename); + return self::buildPrimitiveType($config, $version, $fhirName, $sxe, $sourceFilename); } - return self::buildDefaultType($config, $fhirName, $sxe, $sourceFilename); + return self::buildDefaultType($config, $version, $fhirName, $sxe, $sourceFilename); } } \ No newline at end of file diff --git a/src/Config.php b/src/Config.php index 2878b37f..c0bd3689 100644 --- a/src/Config.php +++ b/src/Config.php @@ -18,8 +18,9 @@ * limitations under the License. */ -use DCarbone\PHPFHIR\Config\Version; -use DCarbone\PHPFHIR\Config\VersionConfig; +use DCarbone\PHPFHIR\Enum\TestTypeEnum; +use DCarbone\PHPFHIR\Utilities\NameUtils; +use Psr\Log\LoggerAwareInterface; use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; @@ -27,196 +28,248 @@ * Class Config * @package DCarbone\PHPFHIR */ -class Config +class Config implements LoggerAwareInterface { - public const KEY_SCHEMA_PATH = 'schemaPath'; - public const KEY_CLASSES_PATH = 'classesPath'; - public const KEY_VERSIONS = 'versions'; - public const KEY_SILENT = 'silent'; - public const KEY_SKIP_TESTS = 'skipTests'; - public const KEY_LIBXML_OPTS = 'libxmlOpts'; - /** @var \DCarbone\PHPFHIR\Logger */ - protected Logger $_log; + private Logger $_log; + + /** @var string */ + private string $_schemaPath; /** @var string */ - private string $schemaPath; + private string $_outputPath; /** @var string */ - private string $classesPath; + private string $_rootNamespace; - /** @var \DCarbone\PHPFHIR\Config\VersionConfig[] */ - private array $versions = []; + /** @var \DCarbone\PHPFHIR\Version[] */ + private array $_versions = []; /** @var bool */ - private bool $silent = false; - /** @var bool */ - private bool $skipTests = false; - /** @var int|null */ - private ?int $libxmlOpts; + private bool $_silent = false; + /** @var null|int */ + private null|int $_libxmlOpts; - /** - * @param \Psr\Log\LoggerInterface $logger - */ - public function setLogger(LoggerInterface $logger): void - { - $this->_log = new Logger($logger); - } + /** @var string */ + private string $_standardDate; + + /** @var array */ + private array $_phpFHIRCopyright; + /** @var string */ + private string $_basePHPFHIRCopyrightComment; + + /** @var \DCarbone\PHPFHIR\CoreFiles */ + private CoreFiles $_coreFiles; + + /** @var array */ + private array $_versionsToGenerate; /** * Config constructor. - * @param array $conf + * @param array $params * @param \Psr\Log\LoggerInterface|null $logger */ - public function __construct(array $conf = [], LoggerInterface $logger = null) + public function __construct(array $params = [], null|LoggerInterface $logger = null) { - if (!isset($conf[self::KEY_SCHEMA_PATH])) { - throw new \DomainException('Required configuration key "' . self::KEY_SCHEMA_PATH . '" missing'); + foreach (ConfigKeyEnum::required() as $key) { + if (!isset($params[$key->value])) { + throw new \DomainException(sprintf('Missing required configuration key "%s"', $key->value)); + } + $this->{"set$key->value"}($params[$key->value]); } - if (!isset($conf[self::KEY_CLASSES_PATH])) { - throw new \DomainException('Required configuration key "' . self::KEY_CLASSES_PATH . '" missing'); + + foreach (ConfigKeyEnum::optional() as $key) { + if (isset($params[$key->value])) { + $this->{"set$key->value"}($params[$key->value]); + } } - if (!isset($conf[self::KEY_VERSIONS]) || !is_array($conf[self::KEY_VERSIONS]) || 0 == count( - $conf[self::KEY_VERSIONS] - )) { - throw new \DomainException( - 'Configuration key "' . self::KEY_VERSIONS . '" must be an array with at least 1 configured version.' - ); + + if (null !== $logger && !$this->isSilent()) { + $this->setLogger(new Logger($logger)); + } else { + $this->setLogger(new NullLogger()); } - $this->setSchemaPath($conf[self::KEY_SCHEMA_PATH]); - $this->setClassesPath($conf[self::KEY_CLASSES_PATH]); - $this->setVersions($conf[self::KEY_VERSIONS]); - $this->setSilent(isset($conf[self::KEY_SILENT]) && (bool)$conf[self::KEY_SILENT]); - $this->setSkipTests($conf[self::KEY_SKIP_TESTS] ?? false); - $this->setLibxmlOpts($conf[self::KEY_LIBXML_OPTS] ?? null); - if ($logger && !$this->isSilent()) { - $this->_log = new Logger($logger); + + $this->_standardDate = date('F jS, Y H:iO'); + + $this->_phpFHIRCopyright = [ + 'This class was generated with the PHPFHIR library (https://github.com/dcarbone/php-fhir) using', + 'class definitions from HL7 FHIR (https://www.hl7.org/fhir/)', + '', + sprintf('Class creation date: %s', $this->_standardDate), + '', + 'PHPFHIR Copyright:', + '', + sprintf('Copyright 2016-%d Daniel Carbone (daniel.p.carbone@gmail.com)', date('Y')), + '', + 'Licensed under the Apache License, Version 2.0 (the "License");', + 'you may not use this file except in compliance with the License.', + 'You may obtain a copy of the License at', + '', + ' http://www.apache.org/licenses/LICENSE-2.0', + '', + 'Unless required by applicable law or agreed to in writing, software', + 'distributed under the License is distributed on an "AS IS" BASIS,', + 'WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.', + 'See the License for the specific language governing permissions and', + 'limitations under the License.', + '', + ]; + + $this->_basePHPFHIRCopyrightComment = sprintf( + "/*!\n * %s\n */", + implode("\n * ", $this->_phpFHIRCopyright) + ); + + $this->_coreFiles = new CoreFiles( + $this->getOutputPath(), + PHPFHIR_TEMPLATE_CORE_DIR, + $this->getFullyQualifiedName(true), + $this->getFullyQualifiedTestsName(TestTypeEnum::BASE, true) + ); + } + + /** + * @param \Psr\Log\LoggerInterface $logger + * @return void + */ + public function setLogger(LoggerInterface $logger): void + { + if ($logger instanceof Logger) { + $this->_log = $logger; } else { - $this->_log = new Logger(new NullLogger()); + $this->_log = new Logger($logger); } } /** - * @return bool + * @return string */ - public function isSilent(): bool + public function getSchemaPath(): string { - return $this->silent; + return $this->_schemaPath; } /** - * @param bool $silent - * @return static + * @param string $schemaPath + * @return $this */ - public function setSilent(bool $silent): self + public function setSchemaPath(string $schemaPath): self { - $this->silent = $silent; + $this->_schemaPath = $schemaPath; return $this; } /** - * @return bool + * @return string */ - public function isSkipTests(): bool + public function getRootNamespace(): string { - return $this->skipTests; + return $this->_rootNamespace; } /** - * @param bool $skipTests - * @return static + * @param string $rootNamespace + * @return self */ - public function setSkipTests(bool $skipTests): self + public function setRootNamespace(string $rootNamespace): self { - $this->skipTests = $skipTests; + $rootNamespace = trim($rootNamespace, PHPFHIR_NAMESPACE_TRIM_CUTSET); + if ('' === $rootNamespace) { + throw new \InvalidArgumentException('Root namespace must not be empty'); + } + + if (!NameUtils::isValidNSName($rootNamespace)) { + throw new \InvalidArgumentException( + sprintf( + 'Root namespace "%s" is not a valid PHP namespace.', + $rootNamespace + ) + ); + } + + $this->_rootNamespace = $rootNamespace; return $this; } /** - * @return int|null + * @return bool */ - public function getLibxmlOpts(): ?int + public function isSilent(): bool { - return $this->libxmlOpts; + return $this->_silent; } /** - * @param int|null $libxmlOpts + * @param bool $silent * @return static */ - public function setLibxmlOpts(?int $libxmlOpts): self + public function setSilent(bool $silent): self { - $this->libxmlOpts = $libxmlOpts; + $this->_silent = $silent; return $this; } /** - * @return \DCarbone\PHPFHIR\Logger + * @return null|int */ - public function getLogger(): Logger + public function getLibxmlOpts(): null|int { - return $this->_log; + return $this->_libxmlOpts; } /** - * @return string + * @param null|int $libxmlOpts + * @return static */ - public function getSchemaPath(): string + public function setLibxmlOpts(?int $libxmlOpts): self { - return $this->schemaPath; + $this->_libxmlOpts = $libxmlOpts; + return $this; } /** - * @param string $schemaPath - * @return $this + * @return \DCarbone\PHPFHIR\Logger */ - public function setSchemaPath(string $schemaPath): self + public function getLogger(): Logger { - // Bunch'o validation - if (false === is_dir($schemaPath)) { - throw new \RuntimeException('Unable to locate XSD dir "' . $schemaPath . '"'); - } - if (false === is_readable($schemaPath)) { - throw new \RuntimeException('This process does not have read access to directory "' . $schemaPath . '"'); - } - $this->schemaPath = rtrim($schemaPath, "/\\"); - return $this; + return $this->_log; } /** * @return string */ - public function getClassesPath(): string + public function getOutputPath(): string { - return $this->classesPath; + return $this->_outputPath; } /** - * @param string $classesPath + * @param string $outputPath * @return $this */ - public function setClassesPath(string $classesPath): self + public function setOutputPath(string $outputPath): self { - if (!is_dir($classesPath)) { - throw new \RuntimeException('Unable to locate output dir "' . $classesPath . '"'); + if (!is_dir($outputPath)) { + throw new \RuntimeException('Unable to locate output dir "' . $outputPath . '"'); } - if (!is_writable($classesPath)) { + if (!is_writable($outputPath)) { throw new \RuntimeException( sprintf( 'Specified output path "%s" is not writable by this process.', - $classesPath + $outputPath ) ); } - if (!is_readable($classesPath)) { + if (!is_readable($outputPath)) { throw new \RuntimeException( sprintf( 'Specified output path "%s" is not readable by this process.', - $classesPath + $outputPath ) ); } - $this->classesPath = $classesPath; + $this->_outputPath = $outputPath; return $this; } @@ -226,19 +279,21 @@ public function setClassesPath(string $classesPath): self */ public function setVersions(array $versions): self { - $this->versions = []; - foreach ($versions as $name => $version) { - $this->versions[$name] = ($version instanceof VersionConfig) ? $version : new VersionConfig($this, new Version($name, $version)); + $this->_versions = []; + foreach ($versions as $name => $data) { + $this->_versions[$name] = ($data instanceof Version) ? $data : new Version($this, $name, $data); } return $this; } /** - * @return \DCarbone\PHPFHIR\Config\VersionConfig[] + * @return \DCarbone\PHPFHIR\Version[] */ - public function getVersions(): array + public function getVersionsIterator(): iterable { - return $this->versions; + foreach ($this->_versions as $v) { + yield $v; + } } /** @@ -247,24 +302,24 @@ public function getVersions(): array */ public function hasVersion(string $version): bool { - return isset($this->versions[$version]); + return isset($this->_versions[$version]); } /** * @param string $version - * @return \DCarbone\PHPFHIR\Config\VersionConfig + * @return \DCarbone\PHPFHIR\Version */ - public function getVersion(string $version): VersionConfig + public function getVersion(string $version): Version { if (!$this->hasVersion($version)) { - throw new \OutOfBoundsException( - 'No version with name "' . $version . '" has been configured. Available: ["' . implode( - '", "', - array_keys($this->versions) - ) . '"]' + throw new \OutOfBoundsException(sprintf( + 'No version with name "%s" has been configured. Available: ["%s"]', + $version, + implode('", "', array_keys($this->_versions)), + ) ); } - return $this->versions[$version]; + return $this->_versions[$version]; } /** @@ -272,6 +327,65 @@ public function getVersion(string $version): VersionConfig */ public function listVersions(): array { - return array_keys($this->versions); + return array_keys($this->_versions); + } + + /** + * @return \DCarbone\PHPFHIR\CoreFiles + */ + public function getCoreFiles(): CoreFiles + { + return $this->_coreFiles; + } + + /** + * @param bool $leadingSlash + * @param string ...$bits + * @return string + */ + public function getFullyQualifiedName(bool $leadingSlash, string...$bits): string + { + $ns = $leadingSlash ? "\\$this->_rootNamespace" : $this->_rootNamespace; + $bits = array_filter($bits); + if ([] === $bits) { + return $ns; + } + return sprintf('%s\\%s', $ns, implode('\\', $bits)); + } + + /** + * @param \DCarbone\PHPFHIR\Enum\TestTypeEnum $testType + * @param bool $leadingSlash + * @param string ...$bits + * @return string + */ + public function getFullyQualifiedTestsName(TestTypeEnum $testType, bool $leadingSlash, string...$bits): string + { + return $this->getFullyQualifiedName($leadingSlash, $testType->namespaceSlug(), ...$bits); + } + + /** + * @return string + */ + public function getStandardDate(): string + { + return $this->_standardDate; + } + + /** + * @return array + */ + public function getPHPFHIRCopyright(): array + { + return $this->_phpFHIRCopyright; + } + + /** + * @param bool $trailingNewline + * @return string + */ + public function getBasePHPFHIRCopyrightComment(bool $trailingNewline): string + { + return $this->_basePHPFHIRCopyrightComment . ($trailingNewline ? "\n" : ''); } } diff --git a/src/Config/Version.php b/src/Config/Version.php deleted file mode 100644 index 1e55c6d0..00000000 --- a/src/Config/Version.php +++ /dev/null @@ -1,151 +0,0 @@ -name = $name; - - if (!isset($conf[self::KEY_URL])) { - throw new DomainException(sprintf('Version %s is missing required config key ', self::KEY_URL)); - } - $this->setUrl($conf[self::KEY_URL]); - - if (isset($conf[self::KEY_NAMESPACE])) { - $this->setNamespace($conf[self::KEY_NAMESPACE]); - } - - if (isset($conf[self::KEY_TEST_ENDPOINT])) { - $this->setTestEndpoint($conf[self::KEY_TEST_ENDPOINT]); - } - } - - /** - * @return string - */ - public function getName(): string - { - return $this->name; - } - - /** - * @return string - */ - public function getUrl(): string - { - return $this->url; - } - - /** - * @param string $url - * @return \DCarbone\PHPFHIR\Config\Version - */ - public function setUrl(string $url): Version - { - $this->url = $url; - return $this; - } - - /** - * @param bool $leadingSlash - * @return string - */ - public function getNamespace(bool $leadingSlash): string - { - return $leadingSlash ? "\\{$this->namespace}" : $this->namespace; - } - - /** - * @param string|null $namespace - * @return \DCarbone\PHPFHIR\Config\Version - */ - public function setNamespace(?string $namespace): Version - { - if (null === $namespace) { - $this->namespace = ''; - return $this; - } - // handle no or empty namespace - $namespace = trim($namespace, PHPFHIR_NAMESPACE_TRIM_CUTSET); - if ('' === $namespace) { - $this->namespace = ''; - return $this; - } - - if (false === NameUtils::isValidNSName($namespace)) { - throw new InvalidArgumentException( - sprintf( - 'Version "%s" namespace "%s" is not a valid PHP namespace.', - $this->name, - $this->namespace - ) - ); - } - - $this->namespace = $namespace; - return $this; - } - - /** - * @return string|null - */ - public function getTestEndpoint(): ?string - { - return $this->testEndpoint ?? null; - } - - /** - * @param string $testEndpoint - * @return \DCarbone\PHPFHIR\Config\Version - */ - public function setTestEndpoint(string $testEndpoint): Version - { - $this->testEndpoint = $testEndpoint; - return $this; - } -} \ No newline at end of file diff --git a/src/Config/VersionConfig.php b/src/Config/VersionConfig.php deleted file mode 100644 index 8779d127..00000000 --- a/src/Config/VersionConfig.php +++ /dev/null @@ -1,159 +0,0 @@ -config = $config; - $this->version = $version; - } - - /** - * @return \DCarbone\PHPFHIR\Logger - */ - public function getLogger(): Logger - { - return $this->config->getLogger(); - } - - /** - * @return string - */ - public function getSchemaPath(): string - { - return "{$this->config->getSchemaPath()}/{$this->version->getName()}"; - } - - /** - * @return string - */ - public function getClassesPath(): string - { - return $this->config->getClassesPath(); - } - - /** - * @return string - */ - public function getUrl(): string - { - return $this->version->getUrl(); - } - - /** - * @param bool $leadingSlash - * @param string ...$bits - * @return string - */ - public function getFullyQualifiedName(bool $leadingSlash, string... $bits): string - { - $ns = $this->version->getNamespace($leadingSlash); - $bits = array_filter($bits); - if ([] === $bits) { - return $ns; - } - return sprintf('%s\\%s', $ns, implode('\\' , $bits)); - } - - /** - * @return bool - */ - public function isSkipTests(): bool - { - return $this->config->isSkipTests(); - } - - /** - * @return int|null - */ - public function getLibxmlOpts(): ?int - { - return $this->config->getLibxmlOpts(); - } - - /** - * @param \DCarbone\PHPFHIR\Enum\TestType $testType - * @param bool $leadingSlash - * @param string ...$bits - * @return string - */ - public function getFullyQualifiedTestsName(TestType $testType, bool $leadingSlash, string... $bits): string - { - return $this->getFullyQualifiedName($leadingSlash, $testType->namespaceSlug(), ...$bits); - } - - /** - * @return string|null - */ - public function getTestEndpoint(): ?string - { - return $this->version->getTestEndpoint(); - } - - /** - * @return \DCarbone\PHPFHIR\Config - */ - public function getConfig(): Config - { - return $this->config; - } - - /** - * @return \DCarbone\PHPFHIR\Config\Version - */ - public function getVersion(): Version - { - return $this->version; - } - - /** - * @return \DCarbone\PHPFHIR\Definition - */ - public function getDefinition(): Definition - { - if (!isset($this->definition)) { - $this->definition = new Definition($this); - } - return $this->definition;; - } -} \ No newline at end of file diff --git a/src/ConfigKeyEnum.php b/src/ConfigKeyEnum.php new file mode 100644 index 00000000..d9a39a89 --- /dev/null +++ b/src/ConfigKeyEnum.php @@ -0,0 +1,57 @@ +_templateFile = $templateFile; + + // get filename + $this->_filename = basename($templateFile); + // store "type" + $this->_type = substr($this->_filename, 0, strpos($this->_filename, '_')); + // trim "type" and ".php" + $this->_filename = strstr(substr($this->_filename, strpos($this->_filename, '_') + 1), '.', true); + // classname suffix + $suffix = ucfirst($this->_type); + + // define "default" namespace + $this->_namespace = ltrim($baseNS, '\\'); + + if ('class' === $this->_type) { + // 'class' types do have suffix + $suffix = ''; + $this->_isAutoloader = str_starts_with($this->_filename, 'autoloader'); + } else if ('test' === $this->_type) { + // mark this as a test file + $this->_isTest = true; + // test classes have different namespace + $this->_namespace = $testNS; + // trim subtype + $this->_filename = substr($this->_filename, strpos($this->_filename, '_') + 1); + } + + // construct class filename + $this->_classname = sprintf( + '%s%s', + implode('', array_map('classFilenameFormat', explode('_', $this->_filename))), + $suffix + ); + + // build full filepath + $this->_filepath = FileUtils::buildCoreFilePath( + $outDir, + $this->_namespace, + $this->_classname, + ); + } + + /** + * @return string + */ + public function getTemplateFile(): string + { + return $this->_templateFile; + } + + /** + * @return string + */ + public function getType(): string + { + return $this->_type; + } + + /** + * @return string + */ + public function getFilepath(): string + { + return $this->_filepath; + } + + /** + * @return string + */ + public function getFilename(): string + { + return $this->_filename; + } + + /** + * @return string + */ + public function getNamespace(): string + { + return $this->_namespace; + } + + /** + * @return string + */ + public function getClassname(): string + { + return $this->_classname; + } + + public function getFullyQualifiedName(bool $leadingSlash): string + { + if ('' === $this->_namespace) { + $ns = $this->_classname; + } else { + $ns = sprintf('%s\\%s', $this->_namespace, $this->_classname); + } + return $leadingSlash ? sprintf('\\%s', $ns) : $ns; + } + + /** + * @return bool + */ + public function isTest(): bool + { + return $this->_isTest; + } + + /** + * @return bool + */ + public function isAutoloader(): bool + { + return $this->_isAutoloader; + } +} \ No newline at end of file diff --git a/src/CoreFiles.php b/src/CoreFiles.php new file mode 100644 index 00000000..6f878ac4 --- /dev/null +++ b/src/CoreFiles.php @@ -0,0 +1,103 @@ +_outputDir = $outputDir; + $this->_templateDir = $templateDir; + + foreach ($this->getTemplateFileIterator() as $fpath => $fi) { + /** @var $fi \SplFileInfo */ + $this->_files[] = new CoreFile($fpath, $outputDir, $baseNS, $testNS); + } + } + + /** + * @return string + */ + public function getOutputDir(): string + { + return $this->_outputDir; + } + + /** + * @return string + */ + public function getTemplateDir(): string + { + return $this->_templateDir; + } + + /** + * @return \RecursiveIteratorIterator + */ + public function getTemplateFileIterator(): \RecursiveIteratorIterator + { + return new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator( + $this->_templateDir, + \FilesystemIterator::CURRENT_AS_FILEINFO | + \FilesystemIterator::SKIP_DOTS, + ), + ); + } + + /** + * @return \DCarbone\PHPFHIR\CoreFile[] + */ + public function getIterator(): \SplFixedArray + { + $files = $this->_files; + usort($files, function(CoreFile $a, CoreFile $b): int { + return strnatcasecmp($a->getClassname(), $b->getClassname()); + }); + return \SplFixedArray::fromArray($files, false); + } + + public function getAutoloadersIterator(): \SplFixedArray + { + $autoloaders = []; + foreach ($this->_files as $file) { + if ($file->isAutoloader()) { + $autoloaders[] = $file; + } + } + usort($autoloaders, function(CoreFile $a, CoreFile $b): int { + return strnatcasecmp($a->getClassname(), $b->getClassname()); + }); + return \SplFixedArray::fromArray($autoloaders, false); + } +} \ No newline at end of file diff --git a/src/Enum/AttributeName.php b/src/Enum/AttributeNameEnum.php similarity index 84% rename from src/Enum/AttributeName.php rename to src/Enum/AttributeNameEnum.php index a0d33f99..e3d7ae2d 100644 --- a/src/Enum/AttributeName.php +++ b/src/Enum/AttributeNameEnum.php @@ -18,11 +18,7 @@ * limitations under the License. */ -/** - * Class AttributeNameEnum - * @package DCarbone\PHPFHIR\Enum - */ -enum AttributeName : string +enum AttributeNameEnum : string { case NAME = 'name'; case VALUE = 'value'; @@ -38,10 +34,10 @@ enum AttributeName : string case NAMESPACE = 'namespace'; /** - * @param \DCarbone\PHPFHIR\Enum\AttributeName|string ...$other + * @param \DCarbone\PHPFHIR\Enum\AttributeNameEnum|string ...$other * @return bool */ - public function isOneOf(AttributeName|string ...$other): bool + public function isOneOf(AttributeNameEnum|string ...$other): bool { return in_array($this, $other, true) || in_array($this->value, $other, true); } diff --git a/src/Enum/ElementName.php b/src/Enum/ElementNameEnum.php similarity index 90% rename from src/Enum/ElementName.php rename to src/Enum/ElementNameEnum.php index 3a343bba..28d46314 100644 --- a/src/Enum/ElementName.php +++ b/src/Enum/ElementNameEnum.php @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -enum ElementName : string +enum ElementNameEnum : string { case _INCLUDE = 'include'; case IMPORT = 'import'; @@ -47,10 +47,10 @@ enum ElementName : string case ANY = 'any'; /** - * @param \DCarbone\PHPFHIR\Enum\ElementName|string ...$other + * @param \DCarbone\PHPFHIR\Enum\ElementNameEnum|string ...$other * @return bool */ - public function isOneOf(ElementName|string ...$other): bool + public function isOneOf(ElementNameEnum|string ...$other): bool { return in_array($this, $other, true) || in_array($this->value, $other, true); } diff --git a/src/Enum/PrimitiveType.php b/src/Enum/PrimitiveTypeEnum.php similarity index 63% rename from src/Enum/PrimitiveType.php rename to src/Enum/PrimitiveTypeEnum.php index efc91c01..ab3549e4 100644 --- a/src/Enum/PrimitiveType.php +++ b/src/Enum/PrimitiveTypeEnum.php @@ -17,7 +17,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -enum PrimitiveType:string + +enum PrimitiveTypeEnum: string { case STRING = 'string'; case BOOLEAN = 'boolean'; @@ -42,7 +43,8 @@ enum PrimitiveType:string case ID = 'id'; case UUID = 'uuid'; - case BASE_64_BINARY = 'base64Binary'; + case BASE64_BINARY = 'base64Binary'; + case XS_BASE64_BINARY = 'xs:base64Binary'; case MARKDOWN = 'markdown'; case SAMPLE_DATA_TYPE = 'SampledDataDataType'; @@ -53,34 +55,34 @@ public function getPHPValueTypes(): string { // leaving as switch for readability purposes. switch ($this) { - case PrimitiveType::STRING: - case PrimitiveType::BOOLEAN: - case PrimitiveType::INTEGER: + case PrimitiveTypeEnum::STRING: + case PrimitiveTypeEnum::BOOLEAN: + case PrimitiveTypeEnum::INTEGER: return $this->value; - case PrimitiveType::DECIMAL: + case PrimitiveTypeEnum::DECIMAL: return 'double'; - case PrimitiveType::POSITIVE_INTEGER: - case PrimitiveType::NEGATIVE_INTEGER: - case PrimitiveType::INTEGER64: + case PrimitiveTypeEnum::POSITIVE_INTEGER: + case PrimitiveTypeEnum::NEGATIVE_INTEGER: + case PrimitiveTypeEnum::INTEGER64: return 'integer'; - case PrimitiveType::DATE: - case PrimitiveType::DATETIME: - case PrimitiveType::TIME: - case PrimitiveType::INSTANT: - case PrimitiveType::CODE: - case PrimitiveType::OID: - case PrimitiveType::CANONICAL: - case PrimitiveType::URI: - case PrimitiveType::URL: - case PrimitiveType::ID: - case PrimitiveType::UUID: - case PrimitiveType::SAMPLE_DATA_TYPE: - case PrimitiveType::BASE_64_BINARY: // TODO: add content decoding? - case PrimitiveType::MARKDOWN: // TODO: markdown lib, maybe? - case PrimitiveType::UNSIGNED_INTEGER: // TODO: utilize big number lib, maybe? + case PrimitiveTypeEnum::DATE: + case PrimitiveTypeEnum::DATETIME: + case PrimitiveTypeEnum::TIME: + case PrimitiveTypeEnum::INSTANT: + case PrimitiveTypeEnum::CODE: + case PrimitiveTypeEnum::OID: + case PrimitiveTypeEnum::CANONICAL: + case PrimitiveTypeEnum::URI: + case PrimitiveTypeEnum::URL: + case PrimitiveTypeEnum::ID: + case PrimitiveTypeEnum::UUID: + case PrimitiveTypeEnum::SAMPLE_DATA_TYPE: + case PrimitiveTypeEnum::BASE64_BINARY: // TODO: add content decoding? + case PrimitiveTypeEnum::MARKDOWN: // TODO: markdown lib, maybe? + case PrimitiveTypeEnum::UNSIGNED_INTEGER: // TODO: utilize big number lib, maybe? return 'string'; default: @@ -115,28 +117,28 @@ public function getPHPReceiveValueTypeHints(): array switch ($this) { // Date types may always accept a \DateTimeInterface instance - case PrimitiveType::DATE: - case PrimitiveType::DATETIME: - case PrimitiveType::INSTANT: - case PrimitiveType::TIME: + case PrimitiveTypeEnum::DATE: + case PrimitiveTypeEnum::DATETIME: + case PrimitiveTypeEnum::INSTANT: + case PrimitiveTypeEnum::TIME: $hintTypes[] = '\\DateTimeInterface'; break; // floats may stem from integers - case PrimitiveType::DECIMAL: + case PrimitiveTypeEnum::DECIMAL: $hintTypes[] = 'int'; break; // integers may stem from floats - case PrimitiveType::INTEGER: - case PrimitiveType::INTEGER64: - case PrimitiveType::POSITIVE_INTEGER: - case PrimitiveType::NEGATIVE_INTEGER: + case PrimitiveTypeEnum::INTEGER: + case PrimitiveTypeEnum::INTEGER64: + case PrimitiveTypeEnum::POSITIVE_INTEGER: + case PrimitiveTypeEnum::NEGATIVE_INTEGER: $hintTypes[] = 'float'; break; // unsigned integers may stem from integers or floats - case PrimitiveType::UNSIGNED_INTEGER: + case PrimitiveTypeEnum::UNSIGNED_INTEGER: array_push($hintTypes, 'int', 'float'); break; } @@ -145,10 +147,10 @@ public function getPHPReceiveValueTypeHints(): array } /** - * @param \DCarbone\PHPFHIR\Enum\PrimitiveType|string ...$other + * @param \DCarbone\PHPFHIR\Enum\PrimitiveTypeEnum|string ...$other * @return bool */ - public function isOneOf(PrimitiveType|string ...$other): bool + public function isOneOf(PrimitiveTypeEnum|string ...$other): bool { return in_array($this, $other, true) || in_array($this->value, $other, true); } diff --git a/src/Enum/PropertyUse.php b/src/Enum/PropertyUseEnum.php similarity index 80% rename from src/Enum/PropertyUse.php rename to src/Enum/PropertyUseEnum.php index 96c8c085..c7ad6a4a 100644 --- a/src/Enum/PropertyUse.php +++ b/src/Enum/PropertyUseEnum.php @@ -18,21 +18,17 @@ * limitations under the License. */ -/** - * Class PropertyUseEnum - * @package DCarbone\PHPFHIR\Enum - */ -enum PropertyUse: string +enum PropertyUseEnum: string { case PROHIBITED = 'prohibited'; case OPTIONAL = 'optional'; case REQUIRED = 'required'; /** - * @param \DCarbone\PHPFHIR\Enum\PropertyUse|string ...$other + * @param \DCarbone\PHPFHIR\Enum\PropertyUseEnum|string ...$other * @return bool */ - public function isOneOf(PropertyUse|string ...$other): bool + public function isOneOf(PropertyUseEnum|string ...$other): bool { return in_array($this, $other, true) || in_array($this->value, $other, true); } diff --git a/src/Enum/TestType.php b/src/Enum/TestTypeEnum.php similarity index 87% rename from src/Enum/TestType.php rename to src/Enum/TestTypeEnum.php index 636d76a2..36a16a58 100644 --- a/src/Enum/TestType.php +++ b/src/Enum/TestTypeEnum.php @@ -18,9 +18,9 @@ * limitations under the License. */ -enum TestType: string +enum TestTypeEnum: string { - case BASE= 'base'; + case BASE = 'base'; case UNIT = 'unit'; case INTEGRATION = 'integration'; case VALIDATION = 'validation'; @@ -36,10 +36,10 @@ public function namespaceSlug(): string } /** - * @param \DCarbone\PHPFHIR\Enum\TestType|string ...$other + * @param \DCarbone\PHPFHIR\Enum\TestTypeEnum|string ...$other * @return bool */ - public function isOneOf(TestType|string ...$other): bool + public function isOneOf(TestTypeEnum|string ...$other): bool { return in_array($this, $other, true) || in_array($this->value, $other, true); } diff --git a/src/Enum/TypeKind.php b/src/Enum/TypeKind.php deleted file mode 100644 index f2e943db..00000000 --- a/src/Enum/TypeKind.php +++ /dev/null @@ -1,157 +0,0 @@ - [ - self::BINARY, - self::ELEMENT, - self::RESOURCE_INLINE, - ], - - 'DSTU2' => [ - self::ELEMENT, - self::RESOURCE, - ], - 'STU3' => [ - self::ELEMENT, - self::RESOURCE, - ], - 'R4' => [ - self::ELEMENT, - self::RESOURCE, - ], - - 'R5' => [ - self::BASE, - ], - ]; - - private const VERSION_CONTAINER_KIND_MAP = [ - 'DSTU1' => self::RESOURCE_INLINE, - 'DSTU2' => self::RESOURCE_CONTAINER, - 'STU3' => self::RESOURCE_CONTAINER, - 'R4' => self::RESOURCE_CONTAINER, - 'R5' => self::RESOURCE_CONTAINER, - ]; - - /** - * Returns the list of known "root" types for the given FHIR spec version - * - * @param string $version - * @return \DCarbone\PHPFHIR\Enum\TypeKind[] - */ - public static function versionRootTypes(string $version): array - { - return self::VERSION_ROOT_KIND_MAP[$version]; - } - - /** - * Returns the TypeKind for the provided FHIR version - * - * @param string $version - * @return \DCarbone\PHPFHIR\Enum\TypeKind - */ - public static function versionContainerType(string $version): TypeKind - { - return self::VERSION_CONTAINER_KIND_MAP[$version]; - } - - /** - * Returns true if the provided FHIR type name is a "root" type from which other types extend. - * - * @param string $version - * @param string $fhirName - * @return bool - */ - public static function isRootTypeName(string $version, string $fhirName): bool - { - return in_array($fhirName, self::_rootTypesStrings($version), true); - } - - /** - * Returns true if the provided FHIR type name is the "container" type for the provided version. - * - * @param string $version - * @param string $fhirName - * @return bool - */ - public static function isContainerTypeName(string $version, string $fhirName): bool - { - return self::_containerTypeString($version) === $fhirName; - } - - /** - * @param \DCarbone\PHPFHIR\Enum\TypeKind|string ...$other - * @return bool - */ - public function isOneOf(TypeKind|string ...$other): bool - { - return in_array($this, $other, true) || in_array($this->value, $other, true); - } - - /** - * Returns true if this kind is the "container" kind for the provided FHIR version. - * - * @param string $version - * @return bool - */ - public function isContainer(string $version): bool - { - return $this === self::VERSION_CONTAINER_KIND_MAP[$version]; - } - - private static function _rootTypesStrings(string $version): array - { - return array_map(function (TypeKind $tk): string { return $tk->value; }, self::VERSION_ROOT_KIND_MAP[$version]); - } - - private static function _containerTypeString(string $version): string - { - return self::VERSION_CONTAINER_KIND_MAP[$version]->value; - } -} \ No newline at end of file diff --git a/src/Enum/TypeKindEnum.php b/src/Enum/TypeKindEnum.php new file mode 100644 index 00000000..8ca62faa --- /dev/null +++ b/src/Enum/TypeKindEnum.php @@ -0,0 +1,92 @@ +getSourceMetadata()->isDSTU1()) { + return $fhirName === self::_DSTU1_CONTAINER_TYPE->value; + } + return $fhirName === self::_CONTAINER_TYPE->value; + } + + /** + * @param \DCarbone\PHPFHIR\Enum\TypeKindEnum|string ...$other + * @return bool + */ + public function isOneOf(TypeKindEnum|string ...$other): bool + { + return in_array($this, $other, true) || in_array($this->value, $other, true); + } + + /** + * Returns true if this kind is the "container" kind for the provided FHIR version. + * + * @param \DCarbone\PHPFHIR\Version $version + * @return bool + */ + public function isContainer(Version $version): bool + { + if ($version->getSourceMetadata()->isDSTU1()) { + return $this === self::_DSTU1_CONTAINER_TYPE; + } + return $this === self::_CONTAINER_TYPE; + } +} \ No newline at end of file diff --git a/src/Render/Templates.php b/src/Render/Templates.php index 8fa703de..44cadb2c 100644 --- a/src/Render/Templates.php +++ b/src/Render/Templates.php @@ -18,10 +18,11 @@ * limitations under the License. */ -use DCarbone\PHPFHIR\Config\VersionConfig; -use DCarbone\PHPFHIR\Definition\Type; -use DCarbone\PHPFHIR\Definition\Types; -use DCarbone\PHPFHIR\Enum\TestType; +use DCarbone\PHPFHIR\Config; +use DCarbone\PHPFHIR\Version; +use DCarbone\PHPFHIR\Version\Definition\Type; +use DCarbone\PHPFHIR\Version\Definition\Types; +use DCarbone\PHPFHIR\Enum\TestTypeEnum; /** * Class TemplateBuilder @@ -31,46 +32,46 @@ abstract class Templates { /** * @param string $coreFilename - * @param \DCarbone\PHPFHIR\Config\VersionConfig $config - * @param \DCarbone\PHPFHIR\Definition\Types $types + * @param array $templateArgs * @return string */ - public static function renderCoreType(string $coreFilename, VersionConfig $config, Types $types): string + public static function renderCoreTemplate(string $coreFilename, array $templateArgs): string { + extract($templateArgs); return require $coreFilename; } /** - * @param \DCarbone\PHPFHIR\Config\VersionConfig $config - * @param \DCarbone\PHPFHIR\Definition\Types $types - * @param \DCarbone\PHPFHIR\Definition\Type $type + * @param \DCarbone\PHPFHIR\Version $version + * @param \DCarbone\PHPFHIR\Version\Definition\Types $types + * @param \DCarbone\PHPFHIR\Version\Definition\Type $type * @return string */ - public static function renderXhtmlTypeClass(VersionConfig $config, Types $types, Type $type): string + public static function renderVersionXHTMLTypeClass(Version $version, Types $types, Type $type): string { - return require PHPFHIR_TEMPLATE_TYPES_DIR . DIRECTORY_SEPARATOR . 'class_xhtml.php'; + return require PHPFHIR_TEMPLATE_VERSION_TYPES_DIR . DIRECTORY_SEPARATOR . 'class_xhtml.php'; } /** - * @param \DCarbone\PHPFHIR\Config\VersionConfig $config - * @param \DCarbone\PHPFHIR\Definition\Types $types - * @param \DCarbone\PHPFHIR\Definition\Type $type + * @param \DCarbone\PHPFHIR\Version $version + * @param \DCarbone\PHPFHIR\Version\Definition\Types $types + * @param \DCarbone\PHPFHIR\Version\Definition\Type $type * @return string */ - public static function renderFhirTypeClass(VersionConfig $config, Types $types, Type $type): string + public static function renderVersionTypeClass(Version $version, Types $types, Type $type): string { - return require PHPFHIR_TEMPLATE_TYPES_DIR . DIRECTORY_SEPARATOR . 'class_default.php'; + return require PHPFHIR_TEMPLATE_VERSION_TYPES_DIR . DIRECTORY_SEPARATOR . 'class_default.php'; } /** - * @param \DCarbone\PHPFHIR\Config\VersionConfig $config - * @param \DCarbone\PHPFHIR\Definition\Types $types - * @param \DCarbone\PHPFHIR\Definition\Type $type - * @param \DCarbone\PHPFHIR\Enum\TestType $testType + * @param \DCarbone\PHPFHIR\Version $version + * @param \DCarbone\PHPFHIR\Version\Definition\Types $types + * @param \DCarbone\PHPFHIR\Version\Definition\Type $type + * @param \DCarbone\PHPFHIR\Enum\TestTypeEnum $testType * @return string */ - public static function renderFhirTypeClassTest(VersionConfig $config, Types $types, Type $type, TestType $testType): string + public static function renderVersionTypeClassTest(Version $version, Types $types, Type $type, TestTypeEnum $testType): string { - return require PHPFHIR_TEMPLATE_TYPE_TESTS_DIR . DIRECTORY_SEPARATOR . $testType->value . DIRECTORY_SEPARATOR .'class.php'; + return require PHPFHIR_TEMPLATE_VERSION_TYPE_TESTS_DIR . DIRECTORY_SEPARATOR . $testType->value . DIRECTORY_SEPARATOR . 'class.php'; } } \ No newline at end of file diff --git a/src/Utilities/CopyrightUtils.php b/src/Utilities/CopyrightUtils.php deleted file mode 100644 index 732a859e..00000000 --- a/src/Utilities/CopyrightUtils.php +++ /dev/null @@ -1,277 +0,0 @@ -getSchemaPath()); - - $config->getLogger()->debug(sprintf('Extracting FHIR copyright from "%s"...', $fhirBase)); - - self::$_fhirCopyright = []; - $fh = fopen($fhirBase, 'rb'); - if ($fh) { - $inComment = false; - while ($line = fgets($fh)) { - $line = rtrim($line); - - if ('-->' === $line) { - break; - } - - if ($inComment) { - // needed as sometimes their comment generation breaks... - $line = str_replace(['/*', '*/'], '', $line); - - $line = html_entity_decode($line); - self::$_fhirCopyright[] = $line; - $line = ltrim($line); - if (str_starts_with($line, 'Generated on ')) { - [$generated, $version] = explode('for FHIR', $line); - - $generated = trim(str_replace('Generated on', '', $generated)); - if ('' === $generated) { - throw new \DomainException( - sprintf( - 'Unable to parse FHIR source generation date from line: %s', - $line - ) - ); - } else { - self::$_fhirGenerationDate = $generated; - } - - $version = trim($version); - if (str_starts_with($version, 'v')) { - self::$_fhirVersion = $version; - } else { - throw new \LogicException( - sprintf( - 'Unable to determine FHIR version from: %s', - $line - ) - ); - } - } - } elseif ('' === $line) { + break; + } + + if ($inComment) { + // needed as sometimes their comment generation breaks... + $line = str_replace(['/*', '*/'], '', $line); + + $line = html_entity_decode($line); + $this->_fhirCopyright[] = $line; + $line = ltrim($line); + if (str_starts_with($line, 'Generated on ')) { + [$generated, $version] = explode('for FHIR', $line); + + $generated = trim(str_replace('Generated on', '', $generated)); + if ('' === $generated) { + throw new \DomainException( + sprintf( + 'Unable to parse FHIR source generation date from line: %s', + $line + ) + ); + } else { + $this->_fhirGenerationDate = $generated; + } + + $version = trim($version); + if (str_starts_with($version, 'v')) { + $this->_fhirVersion = $version; + } else { + throw new \LogicException( + sprintf( + 'Unable to determine FHIR version from: %s', + $line + ) + ); + } + } + } elseif ('