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 | 'defaultValue' => 0, |
||
28 | 'dangerouslySetInnerHTML' => 0 |
||
29 | ]; |
||
30 | |||
31 | 5 | private static function getName(string $name, ReactJS $react): string { |
|
32 | 5 | return $react->components[$name] ?? '"' . $name . '"'; |
|
33 | } |
||
34 | |||
35 | private static $attributes = [ |
||
36 | 'classname' => 'className', |
||
37 | 'onblur' => 'onBlur', |
||
38 | 'onclick' => 'onClick', |
||
39 | 'onchange' => 'onChange', |
||
40 | 'onsubmit' => 'onSubmit', |
||
41 | 'defaultvalue' => 'defaultValue', |
||
42 | 'dangerouslysetinnerhtml' => 'dangerouslySetInnerHTML', |
||
43 | 'htmlfor' => 'htmlFor' |
||
44 | ]; |
||
45 | |||
46 | 5 | private static function cleanJSONFunctions(string $json): string { |
|
47 | 5 | return \str_replace([ |
|
48 | 5 | '"!!%', |
|
49 | '%!!"' |
||
50 | 5 | ], '', $json); |
|
51 | } |
||
52 | |||
53 | 4 | private static function hasBraces(string $str): bool { |
|
54 | 4 | return (\substr($str, 0, 1) === '{' && \substr($str, - 1) === '}'); |
|
55 | } |
||
56 | |||
57 | 5 | private static function nodeToJs(\DOMNode $root, ?ReactJS $react): string { |
|
58 | 5 | $attributes = []; |
|
59 | 5 | $name = $root->nodeName; |
|
60 | |||
61 | 5 | if ($root->hasAttributes()) { |
|
62 | 4 | $attrs = $root->attributes; |
|
63 | |||
64 | 4 | foreach ($attrs as $i => $attr) { |
|
65 | 4 | $attrName = self::$attributes[$attr->name] ?? $attr->name; |
|
66 | 4 | $attrValue = $attr->value; |
|
67 | 4 | if (isset(self::$jsDetect[$attrName])) { |
|
68 | 3 | if (self::hasBraces($attrValue)) { |
|
69 | 3 | $attrValue = \substr($attrValue, 1, - 1); |
|
70 | } |
||
71 | 3 | $attributes[$attrName] = '!!%' . $attrValue . '%!!'; |
|
72 | } else { |
||
73 | 4 | $attributes[$attrName] = $attrValue; |
|
74 | } |
||
75 | } |
||
76 | } |
||
77 | 5 | $childrenStr = self::getChildrenStr($root, $react); |
|
78 | 5 | return self::$reactCreateElement . "(" . ((isset($react)) ? self::getName($name, $react) : $name) . "," . self::cleanJSONFunctions(JavascriptUtils::toJSON($attributes)) . "$childrenStr)"; |
|
79 | } |
||
80 | |||
81 | 5 | private static function getChildrenStr(\DOMNode $root, ?ReactJS $react): string { |
|
82 | 5 | $children = []; |
|
83 | |||
84 | 5 | $childNodes = $root->childNodes; |
|
85 | 5 | $open = null; |
|
86 | 5 | for ($i = 0; $i < $childNodes->length; $i ++) { |
|
87 | 4 | $child = $childNodes->item($i); |
|
88 | 4 | if ($child->nodeType == XML_TEXT_NODE) { |
|
89 | 4 | $v = \trim($child->nodeValue); |
|
90 | 4 | if ($v != null) { |
|
91 | 4 | self::parseTextNode($v, $children, $open); |
|
92 | } |
||
93 | } else { |
||
94 | 3 | if ($open != '') { |
|
95 | 1 | $open .= self::nodeToJs($child, $react); |
|
96 | } else { |
||
97 | 3 | $children[] = self::nodeToJs($child, $react); |
|
98 | } |
||
99 | } |
||
100 | } |
||
101 | 5 | return (count($children) > 0) ? (',' . implode(',', $children)) : ''; |
|
102 | } |
||
103 | |||
104 | 4 | private static function parseTextNode(string $v, array &$children, ?string &$open) { |
|
105 | 4 | $parts = \preg_split('@(\{.*?\})@', $v, null, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); |
|
106 | 4 | if ($parts && \count($parts) > 0) { |
|
107 | 4 | foreach ($parts as $ev) { |
|
108 | 4 | if (self::hasBraces($ev)) { |
|
109 | 3 | $children[] = \substr($ev, 1, - 1); |
|
110 | 4 | } elseif (\substr($ev, 0, 1) === '{') { |
|
111 | 1 | $open = \substr($ev, 1); |
|
112 | 4 | } elseif ($open != '' && \substr($ev, - 1) === '}') { |
|
113 | 1 | $children[] = $open . \substr($ev, 0, - 1); |
|
114 | 1 | $open = ''; |
|
115 | 4 | } elseif (\trim($ev) != null) { |
|
116 | 3 | $children[] = '"' . $ev . '"'; |
|
117 | } |
||
118 | } |
||
119 | } else { |
||
120 | $children[] = "`$v`"; |
||
121 | } |
||
122 | 4 | } |
|
123 | |||
124 | 5 | public static function toJs(string $html, ?ReactJS $react = null): string { |
|
125 | 5 | \libxml_use_internal_errors(true); |
|
126 | 5 | $dom = new \DOMDocument('1.0', 'UTF-8'); |
|
127 | 5 | $dom->loadHTML(\mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); |
|
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
128 | 5 | return self::nodeToJs($dom->documentElement, $react); |
|
129 | } |
||
130 | } |
||
131 |