diff --git a/src/EnvReader/XmlConfig.php b/src/EnvReader/XmlConfig.php index 4166d46..23b9165 100644 --- a/src/EnvReader/XmlConfig.php +++ b/src/EnvReader/XmlConfig.php @@ -3,9 +3,11 @@ namespace jrosset\EnvReader; use Exception; -use jrosset\ArrayClasses\InsensitiveCaseArrayClass; -use SimpleXMLElement; +use jrosset\EnvReader\XmlStructure\IXmlStructure; +/** + * A XML file configuration class + */ abstract class XmlConfig extends GenericConfig implements IExternalConfigFile { use TMultiLevelProperties; @@ -13,11 +15,13 @@ abstract class XmlConfig extends GenericConfig implements IExternalConfigFile { * @inheritDoc */ protected function readConfig (): void { + //region ContrĂ´le fichier existant $configFile = $this->getConfigFilePath(); if (!file_exists($configFile)) { throw new Exception('Unable to find configuration file "' . $configFile . '"'); } - + //endregion + //region Chargement fichier et traitement erreurs if (($xml = simplexml_load_file($configFile)) === false) { $errors = []; foreach (libxml_get_errors() as $error) { @@ -41,15 +45,16 @@ abstract class XmlConfig extends GenericConfig implements IExternalConfigFile { throw new Exception('Unable to read configuration file "' . $configFile . '": ' . PHP_EOL . implode(PHP_EOL, $errors)); } - $this->properties = $this->parseXml($xml); + //endregion + + //region Parsage XML + $this->properties = $this->getConfigStructure()->parseXml($xml); + //endregion } /** - * Parse an XML node to properties - * - * @param SimpleXMLElement $xmlNode The INI level - * @param InsensitiveCaseArrayClass $properties [OUT] The out properties list + * Obtient la structure de la configuration * - * @return void + * @return IXmlStructure La structure de la configuration */ - protected abstract function parseXml (SimpleXMLElement $xmlNode): InsensitiveCaseArrayClass; + protected abstract function getConfigStructure (): IXmlStructure; } \ No newline at end of file diff --git a/src/EnvReader/XmlStructure/AttributeListXmlStructure.php b/src/EnvReader/XmlStructure/AttributeListXmlStructure.php new file mode 100644 index 0000000..ec4f0c3 --- /dev/null +++ b/src/EnvReader/XmlStructure/AttributeListXmlStructure.php @@ -0,0 +1,75 @@ +allowed = []; + $this->mapping = new InsensitiveCaseArrayClass(); + } + + /** + * Add a new allowed attribute name + * + * @param string $attributeName The new allowed attribute name + * @param string|null $propertyName The corresponding property name. Null if identical to attribute name + * + * @return $this + */ + public function addAllowed (string $attributeName, ?string $propertyName = null): self { + $this->allowed[] = mb_strtolower($attributeName); + if ($propertyName !== null) { + $this->addMapping($attributeName, $propertyName); + } + return $this; + } + /** + * Add a new mapping + * + * @param string $attributeName The new attribute name + * @param string $propertyName The corresponding property name + * + * @return $this + */ + public function addMapping (string $attributeName, string $propertyName): self { + $this->mapping->set($attributeName, $propertyName); + return $this; + } + + /** + * @inheritDoc + */ + public function parseXml (SimpleXMLElement $xmlNode): InsensitiveCaseArrayClass { + $properties = new InsensitiveCaseArrayClass(); + if (($attributes = $xmlNode->attributes()) === null) { + return $properties; + } + + $allowAll = count($this->allowed) === 0; + foreach ($attributes as $attributeName => $attributeValue) { + if (!$allowAll && !in_array(mb_strtolower($attributeName), $this->allowed)) { + continue; + } + $properties->set($this->mapping->get($attributeName, false) ?? $attributeName, (string)$attributeValue); + } + return $properties; + } +} \ No newline at end of file diff --git a/src/EnvReader/XmlStructure/AttributeSingleXmlStructure.php b/src/EnvReader/XmlStructure/AttributeSingleXmlStructure.php new file mode 100644 index 0000000..4050289 --- /dev/null +++ b/src/EnvReader/XmlStructure/AttributeSingleXmlStructure.php @@ -0,0 +1,31 @@ +attributeName = $attributeName; + } + + /** + * @inheritDoc + */ + public function parseXml (SimpleXMLElement $xmlNode): string { + return (string)$xmlNode[$this->attributeName]; + } +} \ No newline at end of file diff --git a/src/EnvReader/XmlStructure/ChildrenXmlStructure.php b/src/EnvReader/XmlStructure/ChildrenXmlStructure.php new file mode 100644 index 0000000..b081d53 --- /dev/null +++ b/src/EnvReader/XmlStructure/ChildrenXmlStructure.php @@ -0,0 +1,87 @@ +attributesStructure = null; + $this->childrenNodes = new ArrayClass(); + $this->mapping = new ArrayClass(); + } + + /** + * Set the attribute structure + * + * @param AttributeListXmlStructure|null $attributesStructure The new attribute structure. Null if none + * + * @return $this + */ + public function setAttributesStructure (?AttributeListXmlStructure $attributesStructure = null): self { + $this->attributesStructure = $attributesStructure; + return $this; + } + /** + * Add a child node + * + * @param string $childNodeName The child node's name + * @param IXmlStructure $childNodeStructure The child node's structure + * @param string|null $propertyName The corresponding property name. Null if identical to child node's name + * + * @return $this + */ + public function addChildNode (string $childNodeName, IXmlStructure $childNodeStructure, ?string $propertyName = null): self { + $this->childrenNodes->set($childNodeName, $childNodeStructure); + if ($propertyName !== null) { + $this->mapping->set($childNodeName, $propertyName); + } + return $this; + } + + /** + * @inheritDoc + */ + public function parseXml (SimpleXMLElement $xmlNode): InsensitiveCaseArrayClass { + if ($this->attributesStructure === null) { + $properties = new InsensitiveCaseArrayClass(); + } + else { + $properties = $this->attributesStructure->parseXml($xmlNode); + } + + /** @var IXmlStructure $childNodeStructure */ + foreach ($this->childrenNodes as $childNodeName => $childNodeStructure) { + if (!isset($xmlNode->$childNodeName)) { + continue; + } + $properties->set( + $this->mapping->get($childNodeName, false) ?? $childNodeName, + $childNodeStructure->parseXml($xmlNode->$childNodeName) + ); + } + + return $properties; + } +} \ No newline at end of file diff --git a/src/EnvReader/XmlStructure/IXmlStructure.php b/src/EnvReader/XmlStructure/IXmlStructure.php new file mode 100644 index 0000000..776db9d --- /dev/null +++ b/src/EnvReader/XmlStructure/IXmlStructure.php @@ -0,0 +1,19 @@ +childNodeName = $childNodeName; + $this->childNodeStructure = $childNodeStructure; + } + + /** + * @inheritDoc + */ + public function parseXml (SimpleXMLElement $xmlNode): InsensitiveCaseArrayClass { + $properties = new InsensitiveCaseArrayClass(); + if (!isset($xmlNode->{$this->childNodeName})) { + return $properties; + } + + foreach ($xmlNode->{$this->childNodeName} as $childNode) { + $childProperties = $this->childNodeStructure->parseXml($childNode); + $properties->push($childProperties); + } + return $properties; + } +} \ No newline at end of file diff --git a/src/EnvReader/XmlStructure/TextXmlStructure.php b/src/EnvReader/XmlStructure/TextXmlStructure.php new file mode 100644 index 0000000..73760da --- /dev/null +++ b/src/EnvReader/XmlStructure/TextXmlStructure.php @@ -0,0 +1,17 @@ +