Skip to content

Instantly share code, notes, and snippets.

@pounard
Created August 7, 2024 09:53
Show Gist options
  • Save pounard/af17744b80734fafa11a3c909fefbbfe to your computer and use it in GitHub Desktop.
Save pounard/af17744b80734fafa11a3c909fefbbfe to your computer and use it in GitHub Desktop.
Quick & ugly PHP array to XML converter
<?php
declare(strict_types=1);
/**
* Crache du XML, yay.
*/
class XmlRequestWriter
{
/**
* Write request.
*/
public function writeRequest(array $data, array $options = []): string
{
$options = $options + $this->getDefaultOptions();
return $this->doWrite($data, $options);
}
/**
* Escape en mode bourrin pour du XML.
*/
protected function escape(string $value): string
{
return \htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
}
protected function doWrite(array $data, array $options): string
{
return $this->doWriteTagList($data, $options);
}
/**
* {@inheritdoc}
*/
protected function writeString(string $value, array $options): string
{
return $this->escape($value);
}
/**
* Write tag list.
*/
protected function doWriteTagList(array $data, array $options, array $attributes = [])
{
$ret = '';
foreach ($data as $index => $value) {
$ret .= $this->doWriteTag($index, $value, $options, $attributes);
}
return $ret;
}
/**
* Write a single tag.
*/
private function doWriteTag(string $tagName, mixed $data, array $options, array $attributes = [])
{
$attrString = '';
if ($attributes) {
foreach ($attributes as $key => $value) {
$attrString .= ' ' . $this->escape($key) . '="' . $this->escape($value) . '"';
}
}
$escapedTagName = $this->escape($tagName);
if (null === $data) {
return '<' . $escapedTagName . $attrString . '/>';
}
if (\is_array($data)) {
return '<' . $escapedTagName . $attrString . '>' . $this->doWriteTagList($data, $options) . '</' . $escapedTagName . '>';
}
return '<' . $escapedTagName . $attrString . '>' . $this->writeValue($data, $options) . '</' . $escapedTagName . '>';
}
protected function getDefaultOptions(): array
{
return [
'date_format' => \DateTime::ISO8601,
];
}
/**
* Convert non array value to string or castable to string.
*/
protected function writeValue($value, array $options): string
{
if (\is_array($value)) {
throw new InvalidArgumentException("La valeur ne devrait pas être un tableau ici.");
}
if (null === $value) {
return $this->writeNull($value, $options);
}
if (\is_string($value)) {
return $this->writeString($value, $options);
}
if (\is_bool($value)) {
return $this->writeBool($value, $options);
}
if (\is_float($value)) {
return $this->writeFloat($value, $options);
}
if (\is_int($value)) {
return $this->writeInt($value, $options);
}
if ($value instanceof \DateTimeInterface) {
return $this->writeDate($value, $options);
}
if (\is_object($value)) {
return $this->writeObject($value, $options);
}
throw new InvalidArgumentException(\sprintf("'%s': le type ne peut pas être sérialisé.", \get_debug_type($value)));
}
/**
* Write date.
*/
protected function writeNull($value, array $options): string
{
return 'null';
}
/**
* Write object.
*/
protected function writeObject(object $value, array $options): string
{
if (\method_exists($value, '__toString')) {
return (string) $value;
}
throw new InvalidArgumentException(\sprintf("'%s': le type ne peut pas être sérialisé.", \get_debug_type($value)));
}
/**
* Write date.
*/
protected function writeDate(\DateTimeInterface $value, array $options): string
{
return $value->format($options['date_format'] ?? \DateTime::ISO8601);
}
/**
* Write boolean.
*/
protected function writeInt(int $value, array $options): string
{
return (string) $value;
}
/**
* Write float.
*/
protected function writeFloat(float $value, array $options): string
{
return (string) $value;
}
/**
* Write boolean.
*/
protected function writeBool(bool $value, array $options): string
{
return $value ? 'true' : 'false';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment