Completed
Push — cache-closure ( 7d9053...380edd )
by Dmitry
35:54
created

XmlResponseFormatter   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 121
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 24
c 2
b 0
f 0
lcom 1
cbo 5
dl 0
loc 121
ccs 56
cts 56
cp 1
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
B format() 0 19 5
C buildXml() 0 38 16
A formatScalarValue() 0 12 3
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\web;
9
10
use DOMDocument;
11
use DOMElement;
12
use DOMText;
13
use yii\base\Arrayable;
14
use yii\base\Component;
15
use yii\helpers\StringHelper;
16
17
/**
18
 * XmlResponseFormatter formats the given data into an XML response content.
19
 *
20
 * It is used by [[Response]] to format response data.
21
 *
22
 * @author Qiang Xue <[email protected]>
23
 * @since 2.0
24
 */
25
class XmlResponseFormatter extends Component implements ResponseFormatterInterface
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 [[Response::charset]].
37
     */
38
    public $encoding;
39
    /**
40
     * @var string the name of the root element. If set to false, null or is empty then no root tag should be added.
41
     */
42
    public $rootTag = 'response';
43
    /**
44
     * @var string the name of the elements that represent the array elements with numeric keys.
45
     */
46
    public $itemTag = 'item';
47
    /**
48
     * @var bool whether to interpret objects implementing the [[\Traversable]] interface as arrays.
49
     * Defaults to `true`.
50
     * @since 2.0.7
51
     */
52
    public $useTraversableAsArray = true;
53
    /**
54
     * @var bool if object tags should be added
55
     * @since 2.0.11
56
     */
57
    public $useObjectTags = true;
58
59
    /**
60
     * Formats the specified response.
61
     * @param Response $response the response to be formatted.
62
     */
63 19
    public function format($response)
64
    {
65 19
        $charset = $this->encoding === null ? $response->charset : $this->encoding;
66 19
        if (stripos($this->contentType, 'charset') === false) {
67 19
            $this->contentType .= '; charset=' . $charset;
68 19
        }
69 19
        $response->getHeaders()->set('Content-Type', $this->contentType);
70 19
        if ($response->data !== null) {
71 18
            $dom = new DOMDocument($this->version, $charset);
72 18
            if (!empty($this->rootTag)) {
73 17
                $root = new DOMElement($this->rootTag);
74 17
                $dom->appendChild($root);
75 17
                $this->buildXml($root, $response->data);
76 17
            } else {
77 1
                $this->buildXml($dom, $response->data);
0 ignored issues
show
Documentation introduced by
$dom is of type object<DOMDocument>, but the function expects a object<DOMElement>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
78
            }
79 18
            $response->content = $dom->saveXML();
80 18
        }
81 19
    }
82
83
    /**
84
     * @param DOMElement $element
85
     * @param mixed $data
86
     */
87 18
    protected function buildXml($element, $data)
88
    {
89 18
        if (is_array($data) ||
90 13
            ($data instanceof \Traversable && $this->useTraversableAsArray && !$data instanceof Arrayable)
91 18
        ) {
92 11
            foreach ($data as $name => $value) {
93 10
                if (is_int($name) && is_object($value)) {
94 3
                    $this->buildXml($element, $value);
95 10
                } elseif (is_array($value) || is_object($value)) {
96 3
                    $child = new DOMElement(is_int($name) ? $this->itemTag : $name);
97 3
                    $element->appendChild($child);
98 3
                    $this->buildXml($child, $value);
99 3
                } else {
100 10
                    $child = new DOMElement(is_int($name) ? $this->itemTag : $name);
101 10
                    $element->appendChild($child);
102 10
                    $child->appendChild(new DOMText($this->formatScalarValue($value)));
103
                }
104 11
            }
105 18
        } elseif (is_object($data)) {
106 6
            if ($this->useObjectTags) {
107 5
                $child = new DOMElement(StringHelper::basename(get_class($data)));
108 5
                $element->appendChild($child);    
109 5
            } else {
110 1
                $child = $element;
111
            }
112 6
            if ($data instanceof Arrayable) {
113 1
                $this->buildXml($child, $data->toArray());
114 1
            } else {
115 5
                $array = [];
116 5
                foreach ($data as $name => $value) {
117 5
                    $array[$name] = $value;
118 5
                }
119 5
                $this->buildXml($child, $array);
120
            }
121 6
        } else {
122 7
            $element->appendChild(new DOMText($this->formatScalarValue($data)));
123
        }
124 18
    }
125
126
    /**
127
     * Formats scalar value to use in XML text node
128
     *
129
     * @param int|string|bool $value
130
     * @return string
131
     * @since 2.0.11
132
     */
133 17
    protected function formatScalarValue($value)
134
    {
135 17
        if ($value === true) {
136 2
            return 'true';
137
        }
138
139 16
        if ($value === false) {
140 2
            return 'false';
141
        }
142
143 15
        return (string) $value;
144
    }
145
}
146