Skip to content

Commit 8a91b28

Browse files
committed
FormatterXml added
1 parent 7dee1a8 commit 8a91b28

File tree

5 files changed

+206
-5
lines changed

5 files changed

+206
-5
lines changed

FormatterXml.php

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<?php
2+
/**
3+
* @link http://www.yiiframework.com/
4+
* @copyright Copyright (c) 2008 Yii Software LLC
5+
* @license http://www.yiiframework.com/license/
6+
*/
7+
8+
namespace yii\httpclient;
9+
10+
use DOMDocument;
11+
use DOMElement;
12+
use DOMText;
13+
use SimpleXMLElement;
14+
use yii\base\Arrayable;
15+
use yii\base\Object;
16+
use Yii;
17+
use yii\helpers\StringHelper;
18+
19+
/**
20+
* FormatterXml formats HTTP message as XML.
21+
*
22+
* @author Paul Klimov <klimov.paul@gmail.com>
23+
* @since 2.0
24+
*/
25+
class FormatterXml extends Object implements FormatterInterface
26+
{
27+
/**
28+
* @var string the Content-Type header for the response
29+
*/
30+
public $contentType = 'application/xml';
31+
/**
32+
* @var string the XML version
33+
*/
34+
public $version = '1.0';
35+
/**
36+
* @var string the XML encoding. If not set, it will use the value of [[\yii\base\Application::charset]].
37+
*/
38+
public $encoding;
39+
/**
40+
* @var string the name of the root element.
41+
*/
42+
public $rootTag = 'request';
43+
44+
45+
/**
46+
* @inheritdoc
47+
*/
48+
public function format(Request $request)
49+
{
50+
$contentType = $this->contentType;
51+
$charset = $this->encoding === null ? Yii::$app->charset : $this->encoding;
52+
if (stripos($contentType, 'charset') === false) {
53+
$contentType .= '; charset=' . $charset;
54+
}
55+
$request->getHeaders()->set('Content-Type', $contentType);
56+
57+
$data = $request->getData();
58+
if ($data !== null) {
59+
if ($data instanceof DOMDocument) {
60+
$content = $data->saveXML();
61+
} elseif ($data instanceof SimpleXMLElement) {
62+
$content = $data->saveXML();
63+
} else {
64+
$dom = new DOMDocument($this->version, $charset);
65+
$root = new DOMElement($this->rootTag);
66+
$dom->appendChild($root);
67+
$this->buildXml($root, $data);
68+
$content = $dom->saveXML();
69+
}
70+
$request->setContent($content);
71+
}
72+
73+
return $request;
74+
}
75+
76+
/**
77+
* @param DOMElement $element
78+
* @param mixed $data
79+
*/
80+
protected function buildXml($element, $data)
81+
{
82+
if (is_object($data)) {
83+
$child = new DOMElement(StringHelper::basename(get_class($data)));
84+
$element->appendChild($child);
85+
if ($data instanceof Arrayable) {
86+
$this->buildXml($child, $data->toArray());
87+
} else {
88+
$array = [];
89+
foreach ($data as $name => $value) {
90+
$array[$name] = $value;
91+
}
92+
$this->buildXml($child, $array);
93+
}
94+
} elseif (is_array($data)) {
95+
foreach ($data as $name => $value) {
96+
if (is_int($name) && is_object($value)) {
97+
$this->buildXml($element, $value);
98+
} elseif (is_array($value) || is_object($value)) {
99+
$child = new DOMElement(is_int($name) ? $this->itemTag : $name);
100+
$element->appendChild($child);
101+
$this->buildXml($child, $value);
102+
} else {
103+
$child = new DOMElement(is_int($name) ? $this->itemTag : $name);
104+
$element->appendChild($child);
105+
$child->appendChild(new DOMText((string) $value));
106+
}
107+
}
108+
} else {
109+
$element->appendChild(new DOMText((string) $data));
110+
}
111+
}
112+
}

Message.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
* @property HeaderCollection|array $headers message headers list.
2222
* @property CookieCollection|Cookie[]|array $cookies message cookies list.
2323
* @property string $content message raw content.
24-
* @property array $data message content data.
24+
* @property mixed $data message content data.
2525
* @property string $format message content format.
2626
*
2727
* @author Paul Klimov <klimov.paul@gmail.com>
@@ -47,7 +47,7 @@ class Message extends Object
4747
*/
4848
private $_content;
4949
/**
50-
* @var array content data
50+
* @var mixed content data
5151
*/
5252
private $_data;
5353
/**
@@ -198,7 +198,7 @@ public function getContent()
198198

199199
/**
200200
* Sets the data fields, which composes message content.
201-
* @param array $data content data fields.
201+
* @param mixed $data content data fields.
202202
* @return $this self reference.
203203
*/
204204
public function setData($data)
@@ -209,7 +209,7 @@ public function setData($data)
209209

210210
/**
211211
* Returns the data fields, parsed from raw content.
212-
* @return array|null content data fields.
212+
* @return mixed content data fields.
213213
*/
214214
public function getData()
215215
{

tests/ClientTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public function dataProviderDefaultFormatters()
4545
[Client::FORMAT_JSON, FormatterJson::className()],
4646
[Client::FORMAT_URLENCODED, FormatterUrlEncoded::className()],
4747
[Client::FORMAT_RAW_URLENCODED, FormatterUrlEncoded::className()],
48-
//[Client::FORMAT_XML, FormatterXml::className()],
48+
[Client::FORMAT_XML, FormatterXml::className()],
4949
];
5050
}
5151

tests/FormatterXmlTest.php

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
namespace yiiunit\extensions\httpclient;
4+
5+
use DOMDocument;
6+
use DOMElement;
7+
use yii\httpclient\FormatterXml;
8+
use yii\httpclient\Request;
9+
10+
class FormatterXmlTest extends TestCase
11+
{
12+
protected function setUp()
13+
{
14+
$this->mockApplication();
15+
}
16+
17+
// Tests :
18+
19+
public function testFormat()
20+
{
21+
$request = new Request();
22+
$data = [
23+
'name1' => 'value1',
24+
'name2' => 'value2',
25+
];
26+
$request->setData($data);
27+
28+
$formatter = new FormatterXml();
29+
$formatter->format($request);
30+
$expectedContent = <<<XML
31+
<?xml version="1.0" encoding="UTF-8"?>
32+
<request><name1>value1</name1><name2>value2</name2></request>
33+
XML;
34+
$this->assertEqualsWithoutLE($expectedContent, $request->getContent());
35+
$this->assertEquals('application/xml; charset=UTF-8', $request->getHeaders()->get('Content-Type'));
36+
}
37+
38+
/**
39+
* @depends testFormat
40+
*/
41+
public function testFormatFromDom()
42+
{
43+
$request = new Request();
44+
$data = new DOMDocument('1.0', 'UTF-8');
45+
$root = new DOMElement('root');
46+
$data->appendChild($root);
47+
$request->setData($data);
48+
49+
$formatter = new FormatterXml();
50+
$formatter->format($request);
51+
$expectedContent = <<<XML
52+
<?xml version="1.0" encoding="UTF-8"?>
53+
<root/>
54+
XML;
55+
$this->assertEqualsWithoutLE($expectedContent, $request->getContent());
56+
}
57+
58+
/**
59+
* @depends testFormat
60+
*/
61+
public function testFormatFromSimpleXml()
62+
{
63+
$request = new Request();
64+
65+
$xml = <<<XML
66+
<?xml version="1.0" encoding="UTF-8"?>
67+
<request><name1>value1</name1><name2>value2</name2></request>
68+
XML;
69+
$simpleXmlElement = simplexml_load_string($xml);
70+
$request->setData($simpleXmlElement);
71+
72+
$formatter = new FormatterXml();
73+
$formatter->format($request);
74+
$this->assertEqualsWithoutLE($xml, $request->getContent());
75+
}
76+
}

tests/TestCase.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,17 @@ protected function destroyApplication()
6060
Yii::$app = null;
6161
Yii::$container = new Container();
6262
}
63+
64+
/**
65+
* Asserting two strings equality ignoring line endings
66+
*
67+
* @param string $expected
68+
* @param string $actual
69+
*/
70+
public function assertEqualsWithoutLE($expected, $actual)
71+
{
72+
$expected = str_replace(["\r", "\n"], '', $expected);
73+
$actual = str_replace(["\r", "\n"], '', $actual);
74+
$this->assertEquals($expected, $actual);
75+
}
6376
}

0 commit comments

Comments
 (0)