Passed
Push — main ( 6fd69f...00f1df )
by Jean-Christophe
02:34
created

JSX::nodeToJs()   A

Complexity

Conditions 6
Paths 4

Size

Total Lines 22
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 6

Importance

Changes 6
Bugs 1 Features 0
Metric Value
eloc 15
c 6
b 1
f 0
dl 0
loc 22
ccs 15
cts 15
cp 1
rs 9.2222
cc 6
nc 4
nop 2
crap 6
1
<?php
2
namespace PHPMV\utils;
3
4
use PHPMV\js\JavascriptUtils;
5
use PHPMV\react\ReactJS;
6
7
/**
8
 * PHPMV\utils$JSX
9
 * This class is part of Ubiquity
10
 *
11
 * @author jc
12
 * @version 1.0.0
13
 *
14
 */
15
class JSX {
16
17
	public static $reactCreateElement = 'React.createElement';
18
19
	private static $jsDetect = [
20
		'onBlur' => 0,
21
		'onChange' => 0,
22
		'onDblclick' => 0,
23
		'onClick' => 0,
24
		'onSubmit' => 0,
25
		'value' => 0,
26
		'items' => 0
27
	];
28
29 2
	private static function getName(string $name, ReactJS $react): string {
30 2
		return $react->components[$name] ?? '"' . $name . '"';
31
	}
32
33
	private static $attributes = [
34
		'classname' => 'className',
35
		'onblur' => 'onBlur',
36
		'onclick' => 'onClick',
37
		'onchange' => 'onChange',
38
		'onsubmit' => 'onSubmit'
39
	];
40
41 2
	private static function cleanJSONFunctions(string $json): string {
42 2
		return \str_replace([
43 2
			'"!!%',
44
			'%!!"'
45 2
		], '', $json);
46
	}
47
48 1
	private static function hasBraces(string $str): bool {
49 1
		return (\substr($str, 0, 1) === '{' && \substr($str, - 1) === '}');
50
	}
51
52 2
	private static function nodeToJs(\DOMNode $root, ?ReactJS $react): string {
53 2
		$attributes = [];
54 2
		$name = $root->nodeName;
55
56 2
		if ($root->hasAttributes()) {
57 1
			$attrs = $root->attributes;
58
59 1
			foreach ($attrs as $i => $attr) {
60 1
				$attrName = self::$attributes[$attr->name] ?? $attr->name;
61 1
				$attrValue = $attr->value;
62 1
				if (isset(self::$jsDetect[$attrName])) {
63 1
					if (self::hasBraces($attrValue)) {
64 1
						$attrValue = \substr($attrValue, 1, - 1);
65
					}
66 1
					$attributes[$attrName] = '!!%' . $attrValue . '%!!';
67
				} else {
68 1
					$attributes[$attrName] = $attrValue;
69
				}
70
			}
71
		}
72 2
		$childrenStr = self::getChildrenStr($root, $react);
73 2
		return self::$reactCreateElement . "(" . ((isset($react)) ? self::getName($name, $react) : $name) . "," . self::cleanJSONFunctions(JavascriptUtils::toJSON($attributes)) . "$childrenStr)";
74
	}
75
76 2
	private static function getChildrenStr(\DOMNode $root, ?ReactJS $react): string {
77 2
		$children = [];
78
79 2
		$childNodes = $root->childNodes;
80 2
		$open = null;
81 2
		for ($i = 0; $i < $childNodes->length; $i ++) {
82 1
			$child = $childNodes->item($i);
83 1
			if ($child->nodeType == XML_TEXT_NODE) {
84 1
				$v = \trim($child->nodeValue);
85 1
				if ($v != null) {
86 1
					self::parseTextNode($v, $children, $open);
87
				}
88
			} else {
89 1
				if ($open != '') {
90
					$open .= self::nodeToJs($child, $react);
91
				} else {
92 1
					$children[] = self::nodeToJs($child, $react);
93
				}
94
			}
95
		}
96 2
		return (count($children) > 0) ? (',' . implode(',', $children)) : '';
97
	}
98
99 1
	private static function parseTextNode(string $v, array &$children, ?string &$open) {
100 1
		$parts = \preg_split('@(\{.*?\})@', $v, null, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
101 1
		if (\count($parts) > 0) {
0 ignored issues
show
Bug introduced by
It seems like $parts can also be of type false; however, parameter $var of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

101
		if (\count(/** @scrutinizer ignore-type */ $parts) > 0) {
Loading history...
102 1
			foreach ($parts as $ev) {
103 1
				if (self::hasBraces($ev)) {
104 1
					$children[] = \substr($ev, 1, - 1);
105 1
				} elseif (\substr($ev, 0, 1) === '{') {
106
					$open = \substr($ev, 1);
107 1
				} elseif ($open != '' && \substr($ev, - 1) === '}') {
108
					$children[] = $open . \substr($ev, 0, - 1);
109
					$open = '';
110 1
				} elseif (\trim($ev) != null) {
111
					$children[] = '"' . $ev . '"';
112
				}
113
			}
114
		} else {
115
			$children[] = "`$v`";
116
		}
117 1
	}
118
119 2
	public static function toJs(string $html, ?ReactJS $react = null): string {
120 2
		\libxml_use_internal_errors(true);
121 2
		$dom = new \DOMDocument('1.0', 'UTF-8');
122 2
		$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
123 2
		return self::nodeToJs($dom->documentElement, $react);
124
	}
125
}
126