JSONx   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 108
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 108
ccs 52
cts 52
cp 1
rs 10
c 1
b 0
f 0
wmc 20
lcom 1
cbo 4

4 Methods

Rating   Name   Duplication   Size   Complexity  
A getSupported() 0 3 1
A load() 0 12 4
A loadFragment() 0 17 4
C transferNode() 0 39 11
1
<?php
2
/**
3
 * A loader that converts JSONx into JsonDOM
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 {
10
11
  use FluentDOM\DOM\Document;
12
  use FluentDOM\DOM\DocumentFragment;
13
  use FluentDOM\DOM\Element;
14
  use FluentDOM\Loadable;
15
  use FluentDOM\Utility\QualifiedName;
16
17
  /**
18
   * A lazy load group for php class loaders
19
   *
20
   * This defines loaders for PHP classes like SimpleXML
21
   */
22
  class JSONx implements Loadable {
23
24
    use Supports\Libxml;
25
26
    const XMLNS_JSONX = 'http://www.ibm.com/xmlns/prod/2009/jsonx';
27
    const XMLNS_JSONDOM = 'urn:carica-json-dom.2013';
28
    const DEFAULT_QNAME = '_';
29
30
    /**
31
     * @return string[]
32
     */
33 12
    public function getSupported(): array {
34 12
      return ['jsonx', 'application/xml+jsonx'];
35
    }
36
37
    /**
38
     * @see Loadable::load
39
     * @param string $source
40
     * @param string $contentType
41
     * @param array|\Traversable|Options $options
42
     * @return Document|Result|NULL
43
     * @throws \LogicException
44
     */
45 12
    public function load($source, string $contentType, $options = []) {
46 12
      if (NULL !== $source && $this->supports($contentType)) {
47 11
        $document = $this->loadXmlDocument($source, $options);
48 11
        $target = new Document();
49 11
        $target->registerNamespace('json', self::XMLNS_JSONDOM);
50 11
        if (isset($document->documentElement)) {
51 11
          $this->transferNode($document->documentElement, $target);
52
        }
53 11
        return $target;
54
      }
55 1
      return NULL;
56
    }
57
58
    /**
59
     * @see Loadable::loadFragment
60
     *
61
     * @param string $source
62
     * @param string $contentType
63
     * @param array|\Traversable|Options $options
64
     * @return DocumentFragment|NULL
65
     * @throws \LogicException
66
     */
67 2
    public function loadFragment($source, string $contentType, $options = []) {
68 2
      if (NULL !== $source && $this->supports($contentType)) {
69 1
        $document = new Document();
70 1
        $document->preserveWhiteSpace = FALSE;
71 1
        $document->registerNamespace('jx', self::XMLNS_JSONX);
72 1
        $sourceFragment = $document->createDocumentFragment();
73 1
        $sourceFragment->appendXml($source);
74 1
        $target = new Document();
75 1
        $target->registerNamespace('json', self::XMLNS_JSONDOM);
76 1
        $targetFragment = $target->createDocumentFragment();
77 1
        foreach ($sourceFragment->childNodes as $node) {
78 1
          $this->transferNode($node, $targetFragment);
79
        }
80 1
        return $targetFragment;
81
      }
82 1
      return NULL;
83
    }
84
85
    /**
86
     * @param \DOMNode|Element $node
87
     * @param \DOMNode|Document|Element $target
88
     * @throws \LogicException
89
     */
90 12
    private function transferNode(\DOMNode $node, \DOMNode $target) {
91 12
      if ($node->namespaceURI === self::XMLNS_JSONX) {
92 12
        if ($target instanceOf Document) {
93 11
          $normalizedName = $name = 'json:json';
94
        } else {
95 12
          $name = $node->getAttribute('name');
96 12
          $normalizedName = QualifiedName::normalizeString($name, self::DEFAULT_QNAME);
97
        }
98 12
        $type = $node->localName;
99 12
        $newNode = $target->appendElement($normalizedName);
100 12
        if ($name !== $normalizedName && $name !== '') {
101 1
          $newNode->setAttribute('json:name', $name);
102
        }
103
        switch ($type) {
104 12
        case 'object' :
105 11
          if ($node('count(*) > 0')) {
106 11
            foreach ($node('*') as $childNode) {
107
              /** @var Element $childNode */
108 11
              $this->transferNode($childNode, $newNode);
109
            }
110 11
            return;
111
          }
112 1
          break;
113 11
        case 'array' :
114 3
          foreach ($node('*') as $childNode) {
115
            /** @var Element $childNode */
116 3
            $this->transferNode($childNode, $newNode);
117
          }
118 3
          break;
119 11
        case 'string' :
120 7
          $newNode->append((string)$node);
121 7
          return;
122
        default :
123 5
          $newNode->append((string)$node);
124 5
          break;
125
        }
126 8
        $newNode->setAttribute('json:type', $type);
127
      }
128 8
    }
129
  }
130
}