Done XML formatter

modifié:         core/lib/Thelia/Core/FileFormat/Formatting/Formatter/XMLFormatter.php
	modifié:         core/lib/Thelia/Tests/FileFormat/Formatting/Formatter/XMLFormatterTest.php
This commit is contained in:
Benjamin Perche
2014-07-18 12:32:36 +02:00
parent 32d8d2051d
commit 00ba277daa
2 changed files with 181 additions and 47 deletions

View File

@@ -11,6 +11,7 @@
/*************************************************************************************/ /*************************************************************************************/
namespace Thelia\Core\FileFormat\Formatting\Formatter; namespace Thelia\Core\FileFormat\Formatting\Formatter;
use Symfony\Component\DependencyInjection\SimpleXMLElement;
use Thelia\Core\FileFormat\Formatter\Exception\BadFormattedStringException; use Thelia\Core\FileFormat\Formatter\Exception\BadFormattedStringException;
use Thelia\Core\FileFormat\Formatting\AbstractFormatter; use Thelia\Core\FileFormat\Formatting\AbstractFormatter;
use Thelia\Core\FileFormat\Formatting\FormatterData; use Thelia\Core\FileFormat\Formatting\FormatterData;
@@ -24,8 +25,8 @@ use Thelia\Core\FileFormat\FormatType;
class XMLFormatter extends AbstractFormatter class XMLFormatter extends AbstractFormatter
{ {
public $root = "data"; public $root = "data";
public $nodeName = "node";
public $rowName = "row"; public $rowName = "row";
public $nodeName = "entry";
/** /**
* @return string * @return string
@@ -83,7 +84,7 @@ class XMLFormatter extends AbstractFormatter
foreach ($arrayData as $key=>$entry) { foreach ($arrayData as $key=>$entry) {
if (is_array($entry)) { if (is_array($entry)) {
$node = $container->appendChild(new \DOMElement($this->nodeName)); $node = $container->appendChild(new \DOMElement($this->rowName));
$this->recursiveBuild($entry, $node); $this->recursiveBuild($entry, $node);
} else { } else {
$node = new \DOMElement($this->nodeName); $node = new \DOMElement($this->nodeName);
@@ -109,7 +110,7 @@ class XMLFormatter extends AbstractFormatter
$newNode = $node->appendChild(new \DOMElement($key)); $newNode = $node->appendChild(new \DOMElement($key));
$this->recursiveBuild($entry, $newNode); $this->recursiveBuild($entry, $newNode);
} else { } else {
$inputNode = new \DOMElement($this->rowName); $inputNode = new \DOMElement($this->nodeName);
$node->appendChild($inputNode); $node->appendChild($inputNode);
/** @var \DOMElement $lastChild */ /** @var \DOMElement $lastChild */
@@ -128,9 +129,58 @@ class XMLFormatter extends AbstractFormatter
* a FormatterData object. * a FormatterData object.
*/ */
public function decode($rawData) public function decode($rawData)
{
$raw = $this->rawDecode($rawData);
return (new FormatterData())->setData($this->recursiveDecode($raw));
}
public function recursiveDecode(array &$data, array &$parent = null)
{
$row = [];
foreach ($data as $name => &$child) {
if (is_array($child)) {
$data = $this->recursiveDecode($child, $data);
}
if ($name === "name" || $name === "value") {
$row[$name] = $this->getValue($name, $data);
}
if (count($row) == 2) {
reset($parent);
if (is_int($key = key($parent))) {
$parent[$row["name"]] = $row["value"];
unset($parent[$key]);
} else {
$data[$row["name"]] = $row["value"];
}
$row=[];
}
}
return $parent === null ? $data : $parent;
}
public function getValue($name, array &$data) {
$value = $data[$name];
unset ($data[$name]);
return $value;
}
/**
* @param $rawData
* @return array
* @throws \Thelia\Core\FileFormat\Formatter\Exception\BadFormattedStringException
*/
public function rawDecode($rawData)
{ {
try { try {
$xml = new \SimpleXMLElement($rawData); $xml = new SimpleXMLElement($rawData);
} catch (\Exception $e) { } catch (\Exception $e) {
$errorMessage = $this->translator->trans( $errorMessage = $this->translator->trans(
"You tried to load a bad formatted XML" "You tried to load a bad formatted XML"
@@ -145,16 +195,40 @@ class XMLFormatter extends AbstractFormatter
); );
} }
$array = json_decode(json_encode($xml),true); $array = [];
if (isset($array[$this->nodeName])) { foreach ($xml->children() as $child) {
$array += $array[$this->nodeName]; $this->recursiveRawDecode($array, $child);
unset($array[$this->nodeName]);
} }
$data = new FormatterData(); return $array;
}
return $data->setData($array); protected function recursiveRawDecode(array &$data, \SimpleXMLElement $node)
{
if ($node->count()) {
if (!array_key_exists($node->getName(), $data)) {
$data[$node->getName()] = [];
}
$row = &$data[$node->getName()];
foreach ($node->children() as $child) {
$this->recursiveRawDecode($row, $child);
}
} else {
$newRow = array();
/** @var SimpleXMLElement $attribute */
foreach ($node->attributes() as $attribute) {
$newRow[$attribute->getName()] = $node->getAttributeAsPhp($attribute->getName());
}
if ($node->getName() === $this->nodeName) {
$data[] = $newRow;
} else {
$data[$node->getName()] = $newRow;
}
}
} }
public function getHandledType() public function getHandledType()

View File

@@ -62,8 +62,15 @@ class XMLFormatterTest extends \PHPUnit_Framework_TestCase
); );
$dom = new \DOMDocument("1.0"); $dom = new \DOMDocument("1.0");
$dom->appendChild(new \DOMElement("data"))
->appendChild(new \DOMElement("foo", "bar")); /** @var \DOMElement $node */
$node =$dom->appendChild(new \DOMElement($this->formatter->root))
->appendChild(new \DOMElement($this->formatter->nodeName));
$node->setAttribute("name", "foo");
$node->setAttribute("value", "bar");
$dom->preserveWhiteSpace = false; $dom->preserveWhiteSpace = false;
$dom->formatOutput = true; $dom->formatOutput = true;
@@ -76,7 +83,6 @@ class XMLFormatterTest extends \PHPUnit_Framework_TestCase
public function testComplexEncode() public function testComplexEncode()
{ {
$data = new FormatterData(); $data = new FormatterData();
$this->formatter->nodeName = "baz";
$data->setData( $data->setData(
[ [
@@ -97,18 +103,29 @@ class XMLFormatterTest extends \PHPUnit_Framework_TestCase
); );
$dom = new \DOMDocument("1.0"); $dom = new \DOMDocument("1.0");
$base = $dom->appendChild(new \DOMElement("data")); $base = $dom->appendChild(new \DOMElement($this->formatter->root));
$base->appendChild(new \DOMElement("foo", "bar")); /** @var \DOMElement $node */
$node = $base->appendChild(new \DOMElement($this->formatter->nodeName));
$node->setAttribute("name", "foo");
$node->setAttribute("value", "bar");
$baz = $base->appendChild(new \DOMElement("baz")); $baz = $base->appendChild(new \DOMElement($this->formatter->rowName));
$baz->appendChild(new \DOMElement("name", "banana")); $node = $baz->appendChild(new \DOMElement($this->formatter->nodeName));
$baz->appendChild(new \DOMElement("type", "fruit")); $node->setAttribute("name", "name");
$node->setAttribute("value", "banana");
$node = $baz->appendChild(new \DOMElement($this->formatter->nodeName));
$node->setAttribute("name", "type");
$node->setAttribute("value", "fruit");
$baz = $base->appendChild(new \DOMElement("baz")); $baz = $base->appendChild(new \DOMElement($this->formatter->rowName));
$orange = $baz->appendChild(new \DOMElement("orange")); $orange = $baz->appendChild(new \DOMElement("orange"));
$orange->appendChild(new \DOMElement("type","fruit")); $node = $orange->appendChild(new \DOMElement($this->formatter->nodeName));
$node->setAttribute("name","type");
$node->setAttribute("value","fruit");
$banana = $baz->appendChild(new \DOMElement("banana")); $banana = $baz->appendChild(new \DOMElement("banana"));
$banana->appendChild(new \DOMElement("like", "Yes")); $node = $banana->appendChild(new \DOMElement($this->formatter->nodeName));
$node->setAttribute("name", "like");
$node->setAttribute("value", "Yes");
$dom->preserveWhiteSpace = false; $dom->preserveWhiteSpace = false;
$dom->formatOutput = true; $dom->formatOutput = true;
@@ -122,8 +139,12 @@ class XMLFormatterTest extends \PHPUnit_Framework_TestCase
public function testSimpleDecode() public function testSimpleDecode()
{ {
$dom = new \DOMDocument("1.0"); $dom = new \DOMDocument("1.0");
$dom->appendChild(new \DOMElement("data")) $node =$dom->appendChild(new \DOMElement($this->formatter->root))
->appendChild(new \DOMElement("foo", "bar")); ->appendChild(new \DOMElement($this->formatter->nodeName));
$node->setAttribute("name", "foo");
$node->setAttribute("value", "bar");
$dom->preserveWhiteSpace = false; $dom->preserveWhiteSpace = false;
$dom->formatOutput = true; $dom->formatOutput = true;
@@ -131,46 +152,85 @@ class XMLFormatterTest extends \PHPUnit_Framework_TestCase
$data = $this->formatter->decode($raw); $data = $this->formatter->decode($raw);
var_dump($data->getData());
$this->assertEquals(["foo" => "bar"], $data->getData()); $this->assertEquals(["foo" => "bar"], $data->getData());
} }
public function testComplexDecode() public function testComplexDecode()
{ {
$expectedData = $expectedData =
[ [
[
"name" => "foo",
"value" => "bar",
],
"row" => [
[
"name" => "fruit",
"value" => "banana",
],
[
"name" => "type",
"value" => "fruit",
],
"orange"=> [
[
"name" => "type",
"value" => "fruit",
]
],
"banana"=> [
[
"name" => "like",
"value" => "Yes",
]
]
]
];
$dom = new \DOMDocument("1.0");
$base = $dom->appendChild(new \DOMElement($this->formatter->root));
/** @var \DOMElement $node */
$node = $base->appendChild(new \DOMElement($this->formatter->nodeName));
$node->setAttribute("name", "foo");
$node->setAttribute("value", "bar");
$baz = $base->appendChild(new \DOMElement($this->formatter->rowName));
$node = $baz->appendChild(new \DOMElement($this->formatter->nodeName));
$node->setAttribute("name", "fruit");
$node->setAttribute("value", "banana");
$node = $baz->appendChild(new \DOMElement($this->formatter->nodeName));
$node->setAttribute("name", "type");
$node->setAttribute("value", "fruit");
$baz = $base->appendChild(new \DOMElement($this->formatter->rowName));
$orange = $baz->appendChild(new \DOMElement("orange"));
$node = $orange->appendChild(new \DOMElement($this->formatter->nodeName));
$node->setAttribute("name","type");
$node->setAttribute("value","fruit");
$banana = $baz->appendChild(new \DOMElement("banana"));
$node = $banana->appendChild(new \DOMElement($this->formatter->nodeName));
$node->setAttribute("name", "like");
$node->setAttribute("value", "Yes");
$data = $this->formatter->rawDecode($dom->saveXML());
$this->assertEquals($expectedData, $data);
$expectedData = [
"foo" => "bar", "foo" => "bar",
[ "row" => [
"name" => "banana", "fruit" => "banana",
"type" => "fruit", "type" => "fruit",
],
[
"orange"=>[ "orange"=>[
"type" => "fruit" "type" => "fruit"
], ],
"banana"=>[ "banana"=>[
"like" => "Yes" "like" => "Yes"
] ]
] ],
]; ];
$dom = new \DOMDocument("1.0");
$base = $dom->appendChild(new \DOMElement("data"));
$base->appendChild(new \DOMElement("foo", "bar"));
$baz = $base->appendChild(new \DOMElement("baz"));
$baz->appendChild(new \DOMElement("name", "banana"));
$baz->appendChild(new \DOMElement("type", "fruit"));
$baz = $base->appendChild(new \DOMElement("baz"));
$orange = $baz->appendChild(new \DOMElement("orange"));
$orange->appendChild(new \DOMElement("type","fruit"));
$banana = $baz->appendChild(new \DOMElement("banana"));
$banana->appendChild(new \DOMElement("like", "Yes"));
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$this->formatter->nodeName = "baz";
$data = $this->formatter->decode($dom->saveXML()); $data = $this->formatter->decode($dom->saveXML());
$this->assertEquals($expectedData, $data->getData()); $this->assertEquals($expectedData, $data->getData());