Passed
Push — master ( 4f7e5e...eeb5c0 )
by Thomas
04:51
created

BadgerFish::transferTo()   B

Complexity

Conditions 7
Paths 12

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 7

Importance

Changes 0
Metric Value
cc 7
eloc 13
nc 12
nop 2
dl 0
loc 20
ccs 13
cts 13
cp 1
crap 7
rs 8.2222
c 0
b 0
f 0
1
<?php
2
/**
3
 * Load a DOM document from a json string or file
4
 *
5
 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
6
 * @copyright Copyright (c) 2009-2017 FluentDOM Contributors
7
 */
8
9
namespace FluentDOM\Loader\Json {
10
11
  use FluentDOM\DOM\Document;
12
  use FluentDOM\DOM\Element;
13
  use FluentDOM\Loadable;
14
  use FluentDOM\Loader\Supports;
15
16
  /**
17
   * Load a DOM document from a json string or file
18
   */
19
  class BadgerFish implements Loadable {
20
21
    use Supports\Json;
22
23
    /**
24
     * @return string[]
25
     */
26 9
    public function getSupported(): array {
27 9
      return ['badgerfish', 'application/badgerfish', 'application/badgerfish+json'];
28
    }
29
30
    /**
31
     * @param \DOMNode|Element $node
32
     * @param mixed $json
33
     * @throws \LogicException
34
     */
35 8
    protected function transferTo(\DOMNode $node, $json) {
36
      /** @var Document $document */
37 8
      $document = $node->ownerDocument ?: $node;
38 8
      if ($json instanceof \stdClass) {
39 8
        foreach ($json as $name => $data) {
40 8
          if ($name === '@xmlns') {
41 3
            $this->transferNamespacesTo($node, $data);
42 8
          } elseif ($name === '$') {
43
            // text content
44 8
            $node->appendChild(
45 8
              $document->createTextNode($this->getValueAsString($data))
46
            );
47 8
          } elseif (0 === strpos($name, '@')) {
48 1
            $this->transferAttributeTo($node, $name, $data);
49
          } else {
50 8
            $this->transferChildTo($node, $name, $data);
51
          }
52
        }
53
      }
54 8
    }
55
56
    /**
57
     * Get the property name for a namespace prefix
58
     *
59
     * @param string $prefix
60
     * @return string
61
     */
62 8
    protected function getNamespacePropertyName(string $prefix): string {
63 8
      return empty($prefix) ? '$' : $prefix;
64
    }
65
66
    /**
67
     * @param Element $node
68
     * @param \stdClass $data
69
     */
70 3
    protected function transferNamespacesTo(Element $node, $data) {
71 3
      foreach ($data as $key => $namespaceURI) {
72 3
        $prefix = $key === '$' ? NULL : $key;
73 3
        if ((string)$node->lookupNamespaceUri($prefix) !== $namespaceURI) {
74 2
          $node->setAttribute(
75 2
            empty($prefix) ? 'xmlns' : 'xmlns:' . $prefix,
76 2
            $namespaceURI
77
          );
78
        }
79
      }
80 3
    }
81
82
    /**
83
     * @param Element $node
84
     * @param string $name
85
     * @param string|number|bool|NULL $data
86
     * @throws \LogicException
87
     */
88 1
    protected function transferAttributeTo(Element $node, string $name, $data) {
89
      /** @var Document $document */
90 1
      $document = $node->ownerDocument ?: $node;
91 1
      $name = (string)substr($name, 1);
92 1
      $namespaceURI = (string)$this->getNamespaceForNode($name, new \stdClass(), $node);
93 1
      $attribute = '' !== $namespaceURI
94
        ? $document->createAttribute($name)
95 1
        : $document->createAttributeNS($namespaceURI, $name);
96 1
      $attribute->value = $this->getValueAsString($data);
97 1
      $node->setAttributeNode($attribute);
98 1
    }
99
100
    /**
101
     * @param \DOMNode $node
102
     * @param string $name
103
     * @param mixed $data
104
     * @return array
105
     * @throws \LogicException
106
     */
107 8
    protected function transferChildTo(\DOMNode $node, string $name, $data) {
108
      /** @var Document $document */
109 8
      $document = $node->ownerDocument ?: $node;
110 8
      $namespaceURI = $this->getNamespaceForNode(
111 8
        $name,
112 8
        $data->{'@xmlns'} ?? new \stdClass(),
113 8
        $document
114
      );
115 8
      if (!is_array($data)) {
116 8
        $data = [$data];
117
      }
118 8
      foreach ($data as $dataChild) {
119
        /** @noinspection IsEmptyFunctionUsageInspection */
120 8
        $child = $node->appendChild(
121 8
          empty($namespaceURI) ? $document->createElement($name) : $document->createElementNS($namespaceURI, $name)
122
        );
123 8
        $this->transferTo($child, $dataChild);
124
      }
125 8
      return $data;
126
    }
127
  }
128
}