Skip to content

Commit 9aa4d7b

Browse files
committed
Moved XmlBuilder from codeception/codeception
1 parent fe5fd43 commit 9aa4d7b

File tree

3 files changed

+234
-0
lines changed

3 files changed

+234
-0
lines changed

src/Codeception/Util/Soap.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Codeception\Util;
6+
7+
/**
8+
* This class is left for BC compatibility.
9+
* Most of its contents moved to parent
10+
*
11+
* Class Soap
12+
* @package Codeception\Util
13+
*/
14+
class Soap extends Xml
15+
{
16+
public static function request(): XmlBuilder
17+
{
18+
return new XmlBuilder();
19+
}
20+
21+
public static function response(): XmlBuilder
22+
{
23+
return new XmlBuilder();
24+
}
25+
}

src/Codeception/Util/Xml.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Codeception\Util;
6+
7+
use DOMDocument;
8+
use DOMElement;
9+
use DOMNode;
10+
use function is_array;
11+
12+
class Xml
13+
{
14+
public static function arrayToXml(DOMDocument $xml, DOMNode $domNode, array $array = []): DOMDocument
15+
{
16+
foreach ($array as $el => $val) {
17+
if (is_array($val)) {
18+
self::arrayToXml($xml, $domNode->$el, $val);
19+
} else {
20+
$domNode->appendChild($xml->createElement($el, $val));
21+
}
22+
}
23+
return $xml;
24+
}
25+
26+
public static function toXml(DOMDocument|DOMElement|XmlBuilder|string|null $xml): DOMDocument
27+
{
28+
if ($xml instanceof XmlBuilder) {
29+
return $xml->getDom();
30+
}
31+
if ($xml instanceof DOMDocument) {
32+
return $xml;
33+
}
34+
$dom = new DOMDocument();
35+
$dom->preserveWhiteSpace = false;
36+
if ($xml instanceof DOMNode) {
37+
$xml = $dom->importNode($xml, true);
38+
$dom->appendChild($xml);
39+
return $dom;
40+
}
41+
42+
if (is_array($xml)) {
43+
return self::arrayToXml($dom, $dom, $xml);
44+
}
45+
if (!empty($xml)) {
46+
$dom->loadXML($xml);
47+
}
48+
return $dom;
49+
}
50+
51+
public static function build(): XmlBuilder
52+
{
53+
return new XmlBuilder();
54+
}
55+
}
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Codeception\Util;
6+
7+
use DOMDocument;
8+
use DOMElement;
9+
use Exception;
10+
11+
/**
12+
* That's a pretty simple yet powerful class to build XML structures in jQuery-like style.
13+
* With no XML line actually written!
14+
* Uses DOM extension to manipulate XML data.
15+
*
16+
* ```php
17+
* <?php
18+
* $xml = new \Codeception\Util\XmlBuilder();
19+
* $xml->users
20+
* ->user
21+
* ->val(1)
22+
* ->email
23+
* ->val('[email protected]')
24+
* ->attr('valid','true')
25+
* ->parent()
26+
* ->cart
27+
* ->attr('empty','false')
28+
* ->items
29+
* ->item
30+
* ->val('useful item');
31+
* ->parents('user')
32+
* ->active
33+
* ->val(1);
34+
* echo $xml;
35+
* ```
36+
*
37+
* This will produce this XML
38+
*
39+
* ```xml
40+
* <?xml version="1.0"?>
41+
* <users>
42+
* <user>
43+
* 1
44+
* <email valid="true">[email protected]</email>
45+
* <cart empty="false">
46+
* <items>
47+
* <item>useful item</item>
48+
* </items>
49+
* </cart>
50+
* <active>1</active>
51+
* </user>
52+
* </users>
53+
* ```
54+
*
55+
* ### Usage
56+
*
57+
* Builder uses chained calls. So each call to builder returns a builder object.
58+
* Except for `getDom` and `__toString` methods.
59+
*
60+
* * `$xml->node` - create new xml node and go inside of it.
61+
* * `$xml->node->val('value')` - sets the inner value of node
62+
* * `$xml->attr('name','value')` - set the attribute of node
63+
* * `$xml->parent()` - go back to parent node.
64+
* * `$xml->parents('user')` - go back through all parents to `user` node.
65+
*
66+
* Export:
67+
*
68+
* * `$xml->getDom` - get a DOMDocument object
69+
* * `$xml->__toString` - get a string representation of XML.
70+
*
71+
* [Source code](https://github.com/Codeception/Codeception/blob/5.0/src/Codeception/Util/XmlBuilder.php)
72+
*/
73+
class XmlBuilder
74+
{
75+
protected DOMDocument $dom;
76+
77+
protected DOMElement|DOMDocument $currentNode;
78+
79+
public function __construct()
80+
{
81+
$this->dom = new DOMDocument();
82+
$this->currentNode = $this->dom;
83+
}
84+
85+
/**
86+
* Appends child node
87+
*/
88+
public function __get(string $tag): XmlBuilder
89+
{
90+
$domElement = $this->dom->createElement($tag);
91+
$this->currentNode->appendChild($domElement);
92+
$this->currentNode = $domElement;
93+
return $this;
94+
}
95+
96+
public function val($val): self
97+
{
98+
$this->currentNode->nodeValue = $val;
99+
return $this;
100+
}
101+
102+
/**
103+
* Sets attribute for current node
104+
*/
105+
public function attr(string $attr, string $val): self
106+
{
107+
$this->currentNode->setAttribute($attr, $val);
108+
return $this;
109+
}
110+
111+
/**
112+
* Traverses to parent
113+
*/
114+
public function parent(): self
115+
{
116+
$this->currentNode = $this->currentNode->parentNode;
117+
return $this;
118+
}
119+
120+
/**
121+
* Traverses to parent with $name
122+
*
123+
* @throws Exception
124+
*/
125+
public function parents(string $tag): self
126+
{
127+
$traverseNode = $this->currentNode;
128+
$elFound = false;
129+
while ($traverseNode->parentNode) {
130+
$traverseNode = $traverseNode->parentNode;
131+
if ($traverseNode->tagName === $tag) {
132+
$this->currentNode = $traverseNode;
133+
$elFound = true;
134+
break;
135+
}
136+
}
137+
138+
if (!$elFound) {
139+
throw new Exception("Parent {$tag} not found in XML");
140+
}
141+
142+
return $this;
143+
}
144+
145+
public function __toString(): string
146+
{
147+
return $this->dom->saveXML();
148+
}
149+
150+
public function getDom(): DOMDocument
151+
{
152+
return $this->dom;
153+
}
154+
}

0 commit comments

Comments
 (0)