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

Using XMLParser for writing and XMLReader for Xhtml types #108

Merged
merged 12 commits into from
May 2, 2024
30 changes: 15 additions & 15 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,19 @@ jobs:
version: '${{ matrix.fhir-version }}'


load-fhir-validator:
runs-on: ubuntu-22.04
name: 'Download FHIR Validator'
steps:
- uses: actions/checkout@v4

- uses: ./.github/actions/load-fhir-validator
# load-fhir-validator:
# runs-on: ubuntu-22.04
# name: 'Download FHIR Validator'
# steps:
# - uses: actions/checkout@v4
#
# - uses: ./.github/actions/load-fhir-validator

run:
runs-on: ubuntu-22.04
needs:
- load-fhir-source
- load-fhir-validator
# - load-fhir-validator
strategy:
fail-fast: false
matrix:
Expand All @@ -77,8 +77,8 @@ jobs:
with:
version: '${{ matrix.fhir-version }}'

- name: 'Install FHIR validator'
uses: ./.github/actions/load-fhir-validator
# - name: 'Install FHIR validator'
# uses: ./.github/actions/load-fhir-validator

- name: 'Install PHP'
uses: shivammathur/setup-php@v2
Expand Down Expand Up @@ -123,11 +123,11 @@ jobs:
run: |
./bin/generate.sh --useExisting --versions '${{ matrix.fhir-version }}'

- name: 'Install Java'
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: 18
# - name: 'Install Java'
# uses: actions/setup-java@v4
# with:
# distribution: 'zulu'
# java-version: 18

- name: 'Run tests'
# language=sh
Expand Down
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,9 @@ require 'path to PHPFHIRResponseParser.php';
// build config
$config = new \YourConfiguredNamespace\PHPFHIRResponseParserConfig([
'registerAutoloader' => true, // use if you are not using Composer
'libxmlOpts' => LIBXML_COMPACT | LIBXML_NSCLEAN // choose different libxml arguments if you want, ymmv.
'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
'overrideSourceXmlns' => true, // set this to true if you want the 'rootXmlns' value you defined to override any value seen from source
]);

// build parser
Expand All @@ -190,14 +192,19 @@ $json = json_encode($object);
## XML Serialization

```php
// To get an instance of \DOMElement...
$element = $object->xmlSerialize();
// To get an instance of \XMLWriter...
$xw = $object->xmlSerialize(null, $yourConfigInstance);

// to get as XML string...
$xml = $element->ownerDocument->saveXML($element);
$xml = $xw->outputMemory(true);

// you can alternatively have the output written directly to a file:
$xw = new \YourConfiguredNamespace\PHPFHIRXmlWriter();
$xw->openUri('file:///some/directory/fhir-resource.xml');
$object->xmlSerialize($xw, $yourConfigInstance);
```

XML Serialization utilizes [DOM](https://www.php.net/manual/en/book.dom.php).
XML Serialization utilizes [XMLWriter](https://www.php.net/manual/en/book.xmlwriter.php).

# Testing

Expand Down
3 changes: 2 additions & 1 deletion bin/generate.php
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,8 @@ function is_dir_empty(string $dir): bool

$url = $build_config->getUrl();

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

Expand Down
6 changes: 4 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,16 @@
],
"require": {
"php": "^8.1",
"ext-simplexml": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-dom": "*",
"ext-simplexml": "*",
"psr/log": "^3.0"
},
"require-dev": {
"ext-curl": "*",
"ext-dom": "*",
"ext-xmlreader": "*",
"ext-xmlwriter": "*",
"phpunit/phpunit": "^10.5 || ^11.0",
"monolog/monolog": "^3.2.0"
},
Expand Down
6 changes: 2 additions & 4 deletions files/constants.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,10 @@
const PHPFHIR_CLASSNAME_TYPEMAP = 'PHPFHIRTypeMap';
const PHPFHIR_CLASSNAME_DEBUG_CLIENT = 'PHPFHIRDebugClient';
const PHPFHIR_CLASSNAME_DEBUG_CLIENT_RESPONSE = 'PHPFHIRDebugClientResponse';
const PHPFHIR_CLASSNAME_XML_WRITER = 'PHPFHIRXmlWriter';

// Core interface names
const PHPFHIR_INTERFACE_TYPE = 'PHPFHIRTypeInterface';
const PHPFHIR_INTERFACE_XML_SERIALIZABLE = 'PHPFHIRXmlSerializableInterface';
const PHPFHIR_INTERFACE_XML_SERIALIZALE_CONFIG = 'PHPFHIRXmlSerializableConfigInterface';
const PHPFHIR_INTERFACE_CONTAINED_TYPE = 'PHPFHIRContainedTypeInterface';
const PHPFHIR_INTERFACE_COMMENT_CONTAINER = 'PHPFHIRCommentContainerInterface';
const PHPFHIR_INTERFACE_PRIMITIVE_TYPE = 'PHPFHIRPrimitiveTypeInterface';
Expand All @@ -98,8 +97,7 @@
const PHPFHIR_TRAIT_COMMENT_CONTAINER = 'PHPFHIRCommentContainerTrait';
const PHPFHIR_TRAIT_VALIDATION_ASSERTIONS = 'PHPFHIRValidationAssertionsTrait';
const PHPFHIR_TRAIT_CHANGE_TRACKING = 'PHPFHIRChangeTrackingTrait';
const PHPFHIR_TRAIT_XMLNS = 'PHPFHIRXmlNamespaceTrait';
const PHPFHIR_TRAIT_XML_SERIALIZABLE_CONFIG = 'PHPFHIRXmlSerializableConfigTrait';
const PHPFHIR_TRAIT_SOURCE_XMLNS = 'PHPFHIRSourceXmlNamespaceTrait';

// Core enums
const PHPFHIR_ENUM_CONFIG_KEY = 'PHPFHIRConfigKeyEnum';
Expand Down
4 changes: 2 additions & 2 deletions src/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -241,14 +241,14 @@ protected function writeCoreTypeFiles(): void
$suffix = ucfirst($ftype);

// define "default" namespace
$ns = $this->config->getNamespace(true);
$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->getTestsNamespace(TestType::BASE, true);
$ns = $this->config->getFullyQualifiedTestsName(TestType::BASE, true);
// trim subtype
$fname = substr($fname, strpos($fname, '_') + 1);
}
Expand Down
22 changes: 11 additions & 11 deletions src/Config/VersionConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,17 @@ public function getUrl(): string

/**
* @param bool $leadingSlash
* @param string ...$bits
* @return string
*/
public function getNamespace(bool $leadingSlash): string
public function getFullyQualifiedName(bool $leadingSlash, string... $bits): string
{
return $this->version->getNamespace($leadingSlash);
$ns = $this->version->getNamespace($leadingSlash);
$bits = array_filter($bits);
if ([] === $bits) {
return $ns;
}
return sprintf('%s\\%s', $ns, implode('\\' , $bits));
}

/**
Expand All @@ -104,18 +110,12 @@ public function getLibxmlOpts(): ?int
/**
* @param \DCarbone\PHPFHIR\Enum\TestType $testType
* @param bool $leadingSlash
* @param string ...$bits
* @return string
*/
public function getTestsNamespace(TestType $testType, bool $leadingSlash): string
public function getFullyQualifiedTestsName(TestType $testType, bool $leadingSlash, string... $bits): string
{
$ns = $this->getNamespace(false);

if ('' === $ns) {
$ns = $testType->namespaceSlug();
} else {
$ns .= '\\' . $testType->namespaceSlug();
}
return $leadingSlash ? "\\{$ns}" : $ns;
return $this->getFullyQualifiedName($leadingSlash, $testType->namespaceSlug(), ...$bits);
}

/**
Expand Down
3 changes: 0 additions & 3 deletions src/Definition.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,6 @@ public function buildDefinition(): void
$log->info('Finding property types');
TypePropertyDecorator::findPropertyTypes($this->config, $this->types);

$log->info('Ensuring primitive type children have "value" property');
TypeDecorator::ensureValueOnPrimitiveChildTypes($this->config, $this->types);

$log->info('Finding overloaded properties in child types');
TypePropertyDecorator::findOverloadedProperties($this->config, $this->types);

Expand Down
46 changes: 6 additions & 40 deletions src/Definition/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -273,15 +273,7 @@ public function getClassName(): string
*/
public function getFullyQualifiedNamespace(bool $leadingSlash): string
{
$ns = $this->getConfig()->getNamespace(false);
$typeNS = $this->getTypeNamespace();
if ('' !== $typeNS) {
$ns = sprintf('%s\\%s', $ns, $typeNS);
}
return match ($leadingSlash) {
true => sprintf('\\%s', $ns),
false => $ns,
};
return $this->getConfig()->getFullyQualifiedName($leadingSlash, $this->getTypeNamespace());
}

/**
Expand All @@ -291,15 +283,7 @@ public function getFullyQualifiedNamespace(bool $leadingSlash): string
*/
public function getFullyQualifiedTestNamespace(TestType $testType, bool $leadingSlash): string
{
$ns = $this->getConfig()->getTestsNamespace($testType, false);
$typeNS = $this->getTypeNamespace();
if ('' !== $typeNS) {
$ns = sprintf('%s\\%s', $ns, $typeNS);
}
return match ($leadingSlash) {
true => sprintf('\\%s', $ns),
false => $ns,
};
return $this->getConfig()->getFullyQualifiedTestsName($testType, $leadingSlash,$this->getTypeNamespace());
}

/**
Expand All @@ -308,16 +292,7 @@ public function getFullyQualifiedTestNamespace(TestType $testType, bool $leading
*/
public function getFullyQualifiedClassName(bool $leadingSlash): string
{
$cn = $this->getFullyQualifiedNamespace(false);
if ('' === $cn) {
$cn = $this->getClassName();
} else {
$cn = sprintf('%s\\%s', $cn, $this->getClassName());
}
return match ($leadingSlash) {
true => sprintf('\\%s', $cn),
false => $cn,
};
return $this->getConfig()->getFullyQualifiedName($leadingSlash, $this->getTypeNamespace(), $this->getClassName());
}

/**
Expand All @@ -335,16 +310,7 @@ public function getTestClassName(): string
*/
public function getFullyQualifiedTestClassName($testType, bool $leadingSlash): string
{
$cn = $this->getFullyQualifiedTestNamespace($testType, false);
if ('' === $cn) {
$cn = $this->getTestClassName();
} else {
$cn = sprintf('%s\\%s', $cn, $this->getTestClassName());
}
return match ($leadingSlash) {
true => sprintf('\\%s', $cn),
false => $cn,
};
return $this->getConfig()->getFullyQualifiedTestsName($testType, $leadingSlash, $this->getTypeNamespace(), $this->getTestClassName());
}

/**
Expand Down Expand Up @@ -789,7 +755,7 @@ public function getDirectlyUsedTraits(): array
$traits,
PHPFHIR_TRAIT_VALIDATION_ASSERTIONS,
PHPFHIR_TRAIT_CHANGE_TRACKING,
PHPFHIR_TRAIT_XMLNS,
PHPFHIR_TRAIT_SOURCE_XMLNS,
);
}
} else if (!$parentType->hasLocalProperties()) {
Expand All @@ -799,7 +765,7 @@ public function getDirectlyUsedTraits(): array
$traits,
PHPFHIR_TRAIT_VALIDATION_ASSERTIONS,
PHPFHIR_TRAIT_CHANGE_TRACKING,
PHPFHIR_TRAIT_XMLNS,
PHPFHIR_TRAIT_SOURCE_XMLNS,
);
}

Expand Down
26 changes: 0 additions & 26 deletions src/Definition/TypeDecorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -204,32 +204,6 @@ public static function determinePrimitiveTypes(VersionConfig $config, Types $typ
}
}

/**
* @param \DCarbone\PHPFHIR\Config\VersionConfig $config
* @param \DCarbone\PHPFHIR\Definition\Types $types
*/
public static function ensureValueOnPrimitiveChildTypes(VersionConfig $config, Types $types): void
{
$logger = $config->getLogger();
foreach ($types->getIterator() as $type) {
if (!$type->hasPrimitiveParent() ||
null !== $type->getLocalProperties()->getProperty(PHPFHIR_VALUE_PROPERTY_NAME)) {
continue;
}
$logger->warning(
sprintf(
'Type "%s" extends primitive "%s" but is missing "%s" property. Adding...',
$type->getFHIRName(),
$type->getParentType()->getFHIRName(),
PHPFHIR_VALUE_PROPERTY_NAME
)
);
$property = new Property($type, $type->getSourceSXE(), $type->getSourceFilename());
$property->setName(PHPFHIR_VALUE_PROPERTY_NAME);
$type->getLocalProperties()->addProperty($property);
}
}

/**
* @param \DCarbone\PHPFHIR\Config\VersionConfig $config
* @param \DCarbone\PHPFHIR\Definition\Types $types
Expand Down
8 changes: 4 additions & 4 deletions src/Definition/TypeImports.php
Original file line number Diff line number Diff line change
Expand Up @@ -221,15 +221,15 @@ private function buildImports(): void
$this->addImport($this->type->getClassName(), $this->type->getFullyQualifiedNamespace(false));

$typeNS = $this->type->getFullyQualifiedNamespace(false);
$configNS = $this->type->getConfig()->getNamespace(false);
$configNS = $this->type->getConfig()->getFullyQualifiedName(false);

$sortedProperties = $this->type->getAllPropertiesIterator();

// always add xml serializable interface and root config to all non-abstract types
// non-abstract types must import config and xml writer
if (!$this->type->isAbstract()) {
$this->addImport(PHPFHIR_CLASSNAME_CONFIG, $configNS);
$this->addImport(PHPFHIR_INTERFACE_XML_SERIALIZABLE, $configNS);
$this->addImport(PHPFHIR_INTERFACE_XML_SERIALIZALE_CONFIG, $configNS);
$this->addImport(PHPFHIR_CLASSNAME_XML_WRITER, $configNS);
$this->addImport(PHPFHIR_ENUM_CONFIG_KEY, $configNS);
}

// if this type is in a nested namespace, there are a few base interfaces, classes, and traits
Expand Down
2 changes: 1 addition & 1 deletion src/Utilities/FileUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public static function buildAutoloaderRelativeFilepath(VersionConfig $config, Ty
{
return ltrim(
str_replace(
[$config->getNamespace(false), '\\'],
[$config->getFullyQualifiedName(false), '\\'],
['', '/'],
$type->getFullyQualifiedClassName(false)
),
Expand Down
2 changes: 1 addition & 1 deletion src/Utilities/TypeHintUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ public static function typeTypeDoc(VersionConfig $config, Type $type, bool $null
if ($tk->isOneOf(TypeKind::RESOURCE_INLINE, TypeKind::RESOURCE_CONTAINER)) {
array_push(
$types,
sprintf('\\%s\\', trim($config->getNamespace(true), '\\')),
sprintf('\\%s\\', trim($config->getFullyQualifiedName(true), '\\')),
PHPFHIR_INTERFACE_CONTAINED_TYPE,
);
} else {
Expand Down
Loading
Loading