Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Track XML serialization locations #111

Merged
merged 9 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ jobs:
with:
php-version: ${{ matrix.php-version }}
extensions: libxml simplexml json zip
# https://github.com/mheap/phpunit-github-actions-printer/blob/master/.github/workflows/ci.yml#L32
ini-values: precision=20

- name: 'Install jq'
uses: dcarbone/install-jq-action@v2
Expand Down
77 changes: 10 additions & 67 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,79 +75,22 @@ There are 2 important things to note with this section:

### Generation Example

```php
require __DIR__.'/vendor/autoload.php';

$schemaPath = 'schema/path';
You can view an example config array here: [bin/config.php](./bin/config.php).

```php
// first, build new configuration class
$config = new \DCarbone\PHPFHIR\Config([
// The path to look look for and optionally download source XSD files to
'schemaPath' => __DIR__ . '/../input',

// The path to place generated type class files
'classesPath' => __DIR__ . '/../output',

// If true, will use a noop null logger
'silent' => false,

// If true, will skip generation of test classes
'skipTests' => false,

// 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' => [
'DSTU1' => [
// Source URL
'url' => 'https://hl7.org/fhir/DSTU1/fhir-all-xsd.zip',
// Namespace to prefix the generated classes with
'namespace' => '\\HL7\\FHIR\\DSTU1',
],
'DSTU2' => [
'url' => 'https://hl7.org/fhir/DSTU2/fhir-all-xsd.zip',
'namespace' => '\\HL7\\FHIR\\DSTU2',
'testEndpoint' => 'https://hapi.fhir.org/baseDstu2',
],
'STU3' => [
'url' => 'https://hl7.org/fhir/STU3/fhir-all-xsd.zip',
'namespace' => '\\HL7\\FHIR\\STU3',
'testEndpoint' => 'https://hapi.fhir.org/baseDstu3',
],
'R4' => [
'url' => 'https://www.hl7.org/fhir/R4/fhir-all-xsd.zip',
'namespace' => '\\HL7\\FHIR\\R4',
'testEndpoint' => 'https://hapi.fhir.org/baseR4',
],
'R5' => [
'url' => 'https://hl7.org/fhir/R5/fhir-all-xsd.zip',
'namespace' => '\\HL7\\FHIR\\R5',
'testEndpoint' => 'https://hapi.fhir.org/baseR5',
]
],
]);
$config = new \DCarbone\PHPFHIR\Config(require 'config.php');

// next, build definition class
$version_config = new \DCarbone\PHPFHIR\Config\VersionConfig($config, $config->getVersion('R5'));
$definition = new \DCarbone\PHPFHIR\Definition($version_config);
$definition->buildDefinition();

$builder = new \DCarbone\PHPFHIR\Builder($config, $definition);
$builder->render();
// next, iterate through all configured versions and render code:
foreach ($config->getVersions() as $versionConfig) {
$versionConfig->getDefinition()->getBuilder()->render();
}
```

Using the above code will generate class files under the included [output](./output) directory, under the namespace
` HL7\\FHIR\\{version} `

If you wish the files to be placed under a different directory, pass the path in as the 2nd argument in the
generator constructor.

If you wish the classes to have a different base namespace, pass the desired NS name in as the 3rd argument in the
generator constructor.

## Data Querying

There are a plethora of good HTTP clients you can use to get data out of a FHIR server, so I leave that up to you.
Currently only a very simple client intended for debugging use is generated. A future goal is to generate a more
fully-featured client.

## Response Parsing

Expand All @@ -166,7 +109,7 @@ require 'path to PHPFHIRResponseParserConfig.php';
require 'path to PHPFHIRResponseParser.php';

// build config
$config = new \YourConfiguredNamespace\PHPFHIRResponseParserConfig([
$config = new \YourConfiguredNamespace\PHPFHIRConfig([
'registerAutoloader' => true, // use if you are not using Composer
'libxmlOpts' => LIBXML_NONET | LIBXML_BIGLINES | LIBXML_PARSEHUGE | LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD | LIBXML_NOXMLDECL // choose different libxml arguments if you want, ymmv.
'rootXmlns' => 'https://hl7.org/fhir', // a specific root xmlns to use, if the source does not return one
Expand Down
8 changes: 5 additions & 3 deletions bin/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
*/
return [
// The path to look look for and optionally download source XSD files to
'schemaPath' => __DIR__ . '/../input/',
'schemaPath' => __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'input/',

// The path to place generated type class files
'classesPath' => __DIR__ . '/../output/',
'classesPath' => __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'output/',

// If true, will use a noop null logger
'silent' => false,
Expand All @@ -32,7 +32,7 @@
'skipTests' => false,

// If you wish to specify alternative libxml opts, do so here.
'libxmlOpts' => LIBXML_NONET | LIBXML_PARSEHUGE | LIBXML_COMPACT,
'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
Expand All @@ -43,6 +43,8 @@
'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' => '',
],
'DSTU2' => [
'url' => 'https://hl7.org/fhir/DSTU2/fhir-all-xsd.zip',
Expand Down
11 changes: 5 additions & 6 deletions bin/generate.php
Original file line number Diff line number Diff line change
Expand Up @@ -380,12 +380,11 @@ function is_dir_empty(string $dir): bool
);

foreach ($versions_to_generate as $version) {
$build_config = new Config\VersionConfig($config, $config->getVersion($version));

$url = $build_config->getUrl();
$version_config = $config->getVersion($version);
$url = $version_config->getUrl();

// build vars
$namespace = $build_config->getFullyQualifiedName(true);
$namespace = $version_config->getFullyQualifiedName(true);
$version = trim($version);
$schema_dir = $config->getSchemaPath() . DIRECTORY_SEPARATOR . $version;

Expand Down Expand Up @@ -507,10 +506,10 @@ function is_dir_empty(string $dir): bool
PHP_EOL
);

$definition = new Definition($build_config);
$definition = new Definition($version_config);
$definition->buildDefinition();

$builder = new Builder($build_config, $definition);
$builder = new Builder($version_config, $definition);
if ($only_library) {
$builder->writeFhirTypeFiles();
} elseif ($only_tests) {
Expand Down
1 change: 1 addition & 0 deletions files/constants.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
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_VALIDATION_ENUM = 'enum';
Expand Down
12 changes: 7 additions & 5 deletions src/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*/

use DCarbone\PHPFHIR\Config\Version;
use DCarbone\PHPFHIR\Config\VersionConfig;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;

Expand All @@ -43,7 +44,8 @@ class Config

/** @var string */
private string $classesPath = PHPFHIR_DEFAULT_OUTPUT_DIR;
/** @var \DCarbone\PHPFHIR\Config\Version[] */

/** @var \DCarbone\PHPFHIR\Config\VersionConfig[] */
private array $versions = [];

/** @var bool */
Expand Down Expand Up @@ -226,13 +228,13 @@ public function setVersions(array $versions): self
{
$this->versions = [];
foreach ($versions as $name => $version) {
$this->versions[$name] = ($version instanceof Version) ? $version : new Version($name, $version);
$this->versions[$name] = ($version instanceof VersionConfig) ? $version : new VersionConfig($this, new Version($name, $version));
}
return $this;
}

/**
* @return \DCarbone\PHPFHIR\Config\Version[]
* @return \DCarbone\PHPFHIR\Config\VersionConfig[]
*/
public function getVersions(): array
{
Expand All @@ -250,9 +252,9 @@ public function hasVersion(string $version): bool

/**
* @param string $version
* @return \DCarbone\PHPFHIR\Config\Version
* @return \DCarbone\PHPFHIR\Config\VersionConfig
*/
public function getVersion(string $version): Version
public function getVersion(string $version): VersionConfig
{
if (!$this->hasVersion($version)) {
throw new \OutOfBoundsException(
Expand Down
15 changes: 15 additions & 0 deletions src/Config/VersionConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*/

use DCarbone\PHPFHIR\Config;
use DCarbone\PHPFHIR\Definition;
use DCarbone\PHPFHIR\Enum\TestType;
use DCarbone\PHPFHIR\Logger;

Expand All @@ -33,6 +34,9 @@ class VersionConfig
/** @var \DCarbone\PHPFHIR\Config\Version */
private Version $version;

/** @var \DCarbone\PHPFHIR\Definition */
private Definition $definition;

/**
* BuildConfig constructor.
* @param \DCarbone\PHPFHIR\Config $config
Expand Down Expand Up @@ -141,4 +145,15 @@ 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;;
}
}
16 changes: 15 additions & 1 deletion src/Definition.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ class Definition
private VersionConfig $config;

/** @var \DCarbone\PHPFHIR\Definition\Types|null */
private ?Types $types = null;
private null|Types $types = null;

/** @var \DCarbone\PHPFHIR\Builder */
private Builder $builder;

/**
* Definition constructor.
Expand Down Expand Up @@ -132,4 +135,15 @@ public function isDefined(): bool
{
return null !== $this->getTypes();
}

/**
* @return \DCarbone\PHPFHIR\Builder
*/
public function getBuilder(): Builder
{
if (!isset($this->builder)) {
$this->builder = new Builder($this->getConfig(), $this);
}
return $this->builder;
}
}
28 changes: 24 additions & 4 deletions src/Definition/Properties.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

use Countable;
use DCarbone\PHPFHIR\Config\VersionConfig;
use DCarbone\PHPFHIR\Enum\TypeKind;
use InvalidArgumentException;
use SplFixedArray;

Expand Down Expand Up @@ -162,7 +163,7 @@ public function hasProperty(string $name): bool
*/
public function allPropertiesIterator(): iterable
{
return SplFixedArray::fromArray($this->properties, false);
return SplFixedArray::fromArray($this->properties, preserveKeys: false);
}

/**
Expand All @@ -173,7 +174,7 @@ public function allPropertiesIterator(): iterable
public function allSortedPropertiesIterator(): iterable
{
$this->_buildLocalCaches();
return SplFixedArray::fromArray($this->_sortedProperties, false);
return SplFixedArray::fromArray($this->_sortedProperties, preserveKeys: false);
}

/**
Expand All @@ -184,7 +185,7 @@ public function allSortedPropertiesIterator(): iterable
public function localPropertiesIterator(): iterable
{
$this->_buildLocalCaches();
return SplFixedArray::fromArray($this->_localProperties, false);
return SplFixedArray::fromArray($this->_localProperties, preserveKeys: false);
}

/**
Expand All @@ -195,7 +196,26 @@ public function localPropertiesIterator(): iterable
public function localSortedPropertiesIterator(): iterable
{
$this->_buildLocalCaches();
return SplFixedArray::fromArray($this->_localSortedProperties, false);
return SplFixedArray::fromArray($this->_localSortedProperties, preserveKeys: false);
}

/**
* @param \DCarbone\PHPFHIR\Enum\TypeKind|null ...$kinds
* @return \DCarbone\PHPFHIR\Definition\Property[]
*/
public function localPropertiesOfTypeKinds(bool $includeCollections, null|TypeKind... $kinds): iterable
{
$out = [];
foreach ($this->localPropertiesIterator() as $property) {
if (!$includeCollections && $property->isCollection()) {
continue;
}
$pt = $property->getValueFHIRType();
if (in_array($pt?->getKind(), $kinds, true)) {
$out[] = $property;
}
}
return SplFixedArray::fromArray($out, preserveKeys: false);
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/Definition/TypeImports.php
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ private function buildImports(): void
$this->addImport(PHPFHIR_CLASSNAME_CONFIG, $configNS);
$this->addImport(PHPFHIR_CLASSNAME_XML_WRITER, $configNS);
$this->addImport(PHPFHIR_ENUM_CONFIG_KEY, $configNS);
$this->addImport(PHPFHIR_ENUM_XML_LOCATION_ENUM, $configNS);
}

// if this type is in a nested namespace, there are a few base interfaces, classes, and traits
Expand Down
4 changes: 4 additions & 0 deletions template/core/classes/class_autoloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@
if (!enum_exists('<?php echo $config->getFullyQualifiedName(true, PHPFHIR_ENUM_API_FORMAT); ?>', false)) {
require __DIR__ . DIRECTORY_SEPARATOR . '<?php echo PHPFHIR_ENUM_API_FORMAT; ?>.php';
}
if (!enum_exists('<?php echo $config->getFullyQualifiedName(true, PHPFHIR_ENUM_XML_LOCATION_ENUM); ?>', false)) {
require __DIR__ . DIRECTORY_SEPARATOR . '<?php echo PHPFHIR_ENUM_XML_LOCATION_ENUM; ?>.php';
}


// parser classes
if (!class_exists('<?php echo $config->getFullyQualifiedName(true, PHPFHIR_CLASSNAME_TYPEMAP); ?>', false)) {
Expand Down
14 changes: 14 additions & 0 deletions template/core/classes/class_xml_writer.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,20 @@ public function writeAttribute(string $name, string $value): bool
&& $this->endAttribute();
}

/**
* Write a complete element with a text value
*
* @param string $name Element name
* @param string $value Element text value
* @return bool
*/
public function writeSimpleElement(string $name, string $value): bool
{
return $this->startElement($name)
&& $this->text($value)
&& $this->endElement();
}

/**
* @return bool
*/
Expand Down
Loading