-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTagParser.php
More file actions
117 lines (94 loc) · 2.25 KB
/
TagParser.php
File metadata and controls
117 lines (94 loc) · 2.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<?php
namespace App\Service;
class TagParser
{
public string $tagStartChar = '{{';
public string $tagEndChar = '}}';
public string $tagSep = '.';
public array $resource = [];
public function __construct( array|object $resource )
{
$this->resource = $resource;
}
public function hasTag( $value ): bool
{
if ( ! is_string( $value ) ) {
return false;
}
return str_contains( $value, $this->tagStartChar );
}
public function parseTagArray( array $array ): array
{
$parsed = [];
$count = count( $array );
$keys = array_keys( $array );
if ( ! $count || ! $keys ) {
return $array;
}
$i = 0;
do {
$key = $this->parseTagString( $keys[ $i ] );
$parsed[ $key ] = $array[ $keys[ $i ] ];
if ( is_array( $parsed[ $key ] ) ) {
$parsed[ $key ] = $this->parseTagArray( $parsed[ $key ] );
} else {
$parsed[ $key ] = $this->parseTagString( $parsed[ $key ] );
}
$i++;
} while ( $i < $count );
return $parsed;
}
public function parseTagString( string $value ): string
{
if ( ! $this->hasTag( $value ) ) {
return $value;
}
$parts = explode( $this->tagStartChar, $value );
$count = count( $parts );
$key = 0;
do {
if ( ! str_contains( $parts[ $key ], $this->tagEndChar ) ) {
$key++;
continue;
}
$part = explode( $this->tagEndChar, $parts[ $key ] );
$part[0] = $this->parseTag( $part[0] );
$parts[ $key ] = implode( '', $part );
$key++;
} while ( $key < $count );
return implode( '', $parts );
}
public function parseTag( string $tag = '' ): mixed
{
$value = '';
$res = $this->resource;
$parts = explode( $this->tagSep, trim( $tag ) );
$count = count( $parts );
$key = 0;
do {
$field = $parts[ $key ];
if ( is_object( $res ) && ! $res instanceof \ArrayAccess ) {
// @todo Normalize object.
if ( isset( $res->$field ) ) {
$res = $res->$field;
} elseif ( is_callable( [ $res, 'get' . ucfirst( $field ) ] ) ) {
$res = call_user_func( [ $res, 'get' . ucfirst( $field ) ] );
} else {
$res = null;
break;
}
} else {
$res = $res[ $field ] ?? null;
}
if ( null === $res ) {
break;
}
$key++;
if ( $key === $count ) {
$value = $res;
break;
}
} while ( $key < $count );
return $value;
}
}