PluginProbe ʕ •ᴥ•ʔ
Kubio AI Page Builder / 2.0.0
Kubio AI Page Builder v2.0.0
2.8.1 trunk 1.0.0 1.0.1 1.1.0 1.2.0 1.2.1 1.2.2 1.2.3 1.3.0 1.3.1 1.3.2 1.4.0 1.4.1 1.4.2 1.4.3 1.5.0 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.7.0 1.7.1 1.7.2 1.7.3 1.8.0 1.8.1 1.8.2 1.9.0 2.0.0 2.1.1 2.1.2 2.1.3 2.2.0 2.2.3 2.2.4 2.2.5 2.3.0 2.3.1 2.3.3 2.3.4 2.4.0 2.4.1 2.4.2 2.4.3 2.4.5 2.5.0 2.5.1 2.5.2 2.5.3 2.6.0 2.6.1 2.6.2 2.6.3 2.6.5 2.6.6 2.6.7 2.7.0 2.7.1 2.7.2 2.7.3 2.8.0
kubio / lib / src / Core / Element.php
kubio / lib / src / Core Last commit date
Background 2 years ago Blocks 3 years ago GlobalElements 3 years ago Layout 4 years ago License 2 years ago Separators 4 years ago StyleManager 2 years ago Styles 4 years ago Activation.php 2 years ago Backup.php 4 years ago CustomizerImporter.php 3 years ago Deactivation.php 4 years ago EditInKubioCustomizerPanel.php 4 years ago Element.php 2 years ago ElementBase.php 4 years ago Importer.php 2 years ago InnerBlocks.php 4 years ago LodashBasic.php 2 years ago Registry.php 3 years ago Utils.php 2 years ago
Element.php
371 lines
1 <?php
2
3 namespace Kubio\Core;
4
5 use function array_shift;
6 use function explode;
7 use function is_array;
8 use function is_string;
9 use function strpos;
10 #[\AllowDynamicProperties]
11 class Element extends ElementBase {
12
13 const DIV = 'div';
14 const SPAN = 'span';
15 const IMAGE = 'img';
16 const A = 'a';
17 const FRAGMENT = '<>';
18 const DASHED_ATTRIBUTES = array( 'data', 'aria' );
19 const DASHED_ATTRIBUTES_REGEX = '/^(data|aria)-/';
20 const ALLOWED_ATTRIBUTES = array(
21 'hidden',
22 'high',
23 'href',
24 'hreflang',
25 'http-equiv',
26 'icon',
27 'id',
28 'ismap',
29 'itemprop',
30 'keytype',
31 'kind',
32 'label',
33 'lang',
34 'language',
35 'list',
36 'loop',
37 'low',
38 'manifest',
39 'max',
40 'maxlength',
41 'media',
42 'method',
43 'min',
44 'multiple',
45 'name',
46 'novalidate',
47 'open',
48 'optimum',
49 'pattern',
50 'ping',
51 'placeholder',
52 'poster',
53 'preload',
54 'pubdate',
55 'radiogroup',
56 'readonly',
57 'rel',
58 'required',
59 'reversed',
60 'rows',
61 'rowspan',
62 'sandbox',
63 'spellcheck',
64 'scope',
65 'scoped',
66 'seamless',
67 'selected',
68 'shape',
69 'size',
70 'sizes',
71 'span',
72 'src',
73 'srcdoc',
74 'srclang',
75 'srcset',
76 'start',
77 'step',
78 'style',
79 'summary',
80 'tabindex',
81 'target',
82 'title',
83 'type',
84 'usemap',
85 'value',
86 'width',
87 'wrap',
88 'border',
89 'buffered',
90 'challenge',
91 'charset',
92 'checked',
93 'cite',
94 'class',
95 'code',
96 'codebase',
97 'color',
98 'cols',
99 'colspan',
100 'content',
101 'contenteditable',
102 'contextmenu',
103 'controls',
104 'coords',
105 'data',
106 'datetime',
107 'default',
108 'defer',
109 'dir',
110 'dirname',
111 'disabled',
112 'download',
113 'draggable',
114 'dropzone',
115 'enctype',
116 'for',
117 'form',
118 'formaction',
119 'headers',
120 'height',
121 'accept',
122 'accept-charset',
123 'accesskey',
124 'action',
125 'align',
126 'alt',
127 'async',
128 'autocomplete',
129 'autofocus',
130 'autoplay',
131 'autosave',
132 'bgcolor',
133 );
134
135 const SELF_CLOSING_TAGS = array(
136 'area',
137 'base',
138 'br',
139 'embed',
140 'hr',
141 // "iframe", - self closing iframe break chrome
142 'img',
143 'input',
144 'link',
145 'meta',
146 'param',
147 'source',
148 'track',
149
150 );
151
152 public static $allowedAttributesByName = true;
153 public $block;
154 protected $type;
155 protected $props;
156 protected $filters = null;
157 protected $children = array();
158 protected $innerHTML = '';
159 protected $shouldRender = true;
160
161
162 function __construct( $type, $props = array(), $children = array(), $block = null ) {
163 self::$allowedAttributesByName = array_fill_keys( self::ALLOWED_ATTRIBUTES, true );
164
165 $this->type = $type;
166
167 $this->children = $children;
168 $this->block = $block;
169
170 $this->resolveComputed( $props );
171
172 if ( isset( $props['innerHTML'] ) ) {
173 $this->innerHTML = $props['innerHTML'];
174 unset( $props['innerHTML'] );
175 }
176
177 if ( isset( $props['shouldRender'] ) ) {
178 $this->shouldRender = $props['shouldRender'];
179 unset( $props['shouldRender'] );
180 }
181
182 if ( ! empty( $props['filters'] ) ) {
183 $this->filters = $props['filters'];
184 unset( $props['filters'] );
185 }
186
187 if ( isset( $props['disableStyleClasses'] ) ) {
188 $this->disableStyleClasses = $props['disableStyleClasses'];
189 unset( $props['disableStyleClasses'] );
190 }
191
192 $this->props = $props;
193 }
194
195 function resolveComputed( &$props ) {
196 foreach ( $props as $name => $value ) {
197 if ( is_string( $value ) ) {
198 if ( strpos( $value, 'computed.' ) === 0 ) {
199 $props[ $name ] = $this->getComputed( $value );
200 }
201 }
202
203 if ( is_array( $value ) ) {
204 $this->resolveComputed( $value );
205 }
206 }
207 }
208
209 function getComputed( $path, $defaultValue = null ) {
210 $paths = explode( '.', $path );
211 array_shift( $paths );
212
213 return LodashBasic::get( $this->block->computed(), $paths, $defaultValue );
214 }
215
216 function getClassName() {
217 return $this->getProp( 'className', array() );
218 }
219
220 function getProp( $name, $default = null ) {
221 return LodashBasic::get( $this->props, $name, $default );
222 }
223
224 function extendProps( $extend ) {
225 $this->props = LodashBasic::merge( $extend, $this->props );
226 }
227
228 function setChildren( $children ) {
229 $this->children = $children;
230 }
231
232 function mergeProps( ...$arrays ) {
233 $result = array();
234 foreach ( $arrays as $props ) {
235 if ( $props ) {
236 foreach ( $props as $prop_name => $prop_value ) {
237 $result_value = LodashBasic::get( $result, $prop_name, array() );
238 if ( isset( $prop_value ) ) {
239 switch ( $prop_name ) {
240 case 'className':
241 $result[ $prop_name ] = LodashBasic::concat( $result_value, $prop_value );
242 break;
243 case 'style':
244 $result[ $prop_name ] = LodashBasic::merge( $result_value, $prop_value );
245 break;
246 default:
247 $result[ $prop_name ] = $prop_value;
248 }
249 }
250 }
251 }
252 }
253 $result['className'] = LodashBasic::identity( LodashBasic::uniq( $result['className'] ) );
254
255 return $result;
256 }
257
258 function __toString() {
259 if ( ! $this->shouldRender ) {
260 return '';
261 }
262
263 $output = '';
264 $tags = array();
265
266 $tag_name = tag_escape( $this->tagName() );
267
268 if ( $this->type !== self::FRAGMENT && in_array( $tag_name, self::SELF_CLOSING_TAGS ) ) {
269 $output = "<{$tag_name} {$this->getAttributesAsString()} />";
270 } else {
271 if ( $this->type !== self::FRAGMENT ) {
272 $tags[] = "<{$tag_name} {$this->getAttributesAsString()}>";
273 }
274
275 // check for non empty strings that return false on validation like. ex: '0'
276 $non_empty_string = is_string( $this->innerHTML ) && strlen( $this->innerHTML );
277 if ( $this->innerHTML || $non_empty_string ) {
278 $tags[] = $this->innerHTML;
279 } else {
280 foreach ( $this->children as $child ) {
281 if ( $child ) {
282 $tags[] = $child;
283 }
284 }
285 }
286
287 if ( $this->type !== self::FRAGMENT ) {
288 $tags[] = "</{$tag_name}>";
289 }
290
291 $output = implode( '', $tags );
292 }
293
294 if ( ! empty( $this->filters ) ) {
295 foreach ( $this->filters as $filter ) {
296 $output = apply_filters( $filter, $output );
297 }
298 }
299
300 return $output;
301 }
302
303 function tagName() {
304 return $this->type;
305 }
306
307 function getAttributesAsString() {
308 $attrs = array();
309 $props = $this->getProps();
310
311 foreach ( $props as $prop_name => $prop_value ) {
312 $attr_name = $prop_name;
313 $attr_value = $prop_value;
314 switch ( $prop_name ) {
315 case 'className':
316 $attr_name = 'class';
317 $attr_value = $this->classAttribute( $prop_value );
318 break;
319 case 'style':
320 $attr_value = $this->styleAttribute( $prop_value );
321 break;
322 }
323 if ( is_string( $attr_value ) ) {
324 if ( isset( self::$allowedAttributesByName[ $attr_name ] ) || preg_match( Element::DASHED_ATTRIBUTES_REGEX, $attr_name ) ) {
325 $attrs[] = $attr_name . '="' . esc_attr( $attr_value ) . '"';
326 }
327 }
328 }
329
330 return implode( ' ', $attrs );
331 }
332
333 function getProps() {
334 return $this->props;
335 }
336
337 function setProps( $props ) {
338 $this->props = $props;
339 }
340
341 function classAttribute( $classes ) {
342 $cls = array();
343 if ( is_string( $classes ) ) {
344 return $classes;
345 }
346 if ( is_array( $classes ) ) {
347 foreach ( $classes as $class_name => $class_value ) {
348 if ( ! is_numeric( $class_name ) ) {
349 if ( ! ! $class_value ) {
350 $cls[] = $class_name;
351 }
352 } else {
353 $cls[] = $class_value;
354 }
355 }
356 }
357
358 return implode( ' ', $cls );
359 }
360
361 function styleAttribute( $style ) {
362 $styles = array();
363 foreach ( $style as $s_name => $s_value ) {
364 $styles[] = LodashBasic::kebabCase( $s_name ) . ':' . $s_value;
365 }
366
367 return implode( ';', $styles );
368 }
369 }
370
371