Skip to content

Commit 78697a2

Browse files
committed
Add TextBinder 1.0.0
1 parent 9a86ad2 commit 78697a2

3 files changed

Lines changed: 162 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Includes the following helpers:
2121
- [SimpleCipher](https://github.com/nabeghe/simple-cipher-php) <small>v1.0.0</small>
2222
- [Stringer](https://github.com/nabeghe/stringer-php) <small>v1.1.4</small>
2323
- [Tepade](https://github.com/nabeghe/tepade-php) <small>v1.0.0</small>
24+
- [TextBinder](https://github.com/nabeghe/text-binder-php) <small>v1.0.0</small>
2425
- [Traituctor](https://github.com/nabeghe/traituctor) <small>v0.1.1</small>
2526
- [Yielder](https://github.com/nabeghe/yielder-php) <small>v1.0.0</small>
2627

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"Nabeghe\\SimpleCipher\\": "src/SimpleCipher",
3939
"Nabeghe\\Stringer\\": "src/Stringer",
4040
"Nabeghe\\Tepade\\": "src/Tepade",
41+
"Nabeghe\\TextBinder\\": "src/TextBinder",
4142
"Nabeghe\\Traituctor\\": "src/Traituctor",
4243
"Nabeghe\\Yielder\\": "src/Yielder"
4344
}

src/TextBinder/TextBinder.php

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
<?php namespace Nabeghe\TextBinder;
2+
3+
/**
4+
* Lightweight text binding engine with function chaining support.
5+
*
6+
* Allows replacing placeholders inside text using variables
7+
* and applying chained functions on their values.
8+
*/
9+
class TextBinder
10+
{
11+
/**
12+
* Registered functions available for placeholder processing.
13+
*
14+
* @var array<string, callable>
15+
*/
16+
protected array $functions;
17+
18+
/**
19+
* Initialize the binder and register default functions.
20+
*/
21+
public function __construct()
22+
{
23+
$this->defineFunctions();
24+
}
25+
26+
/**
27+
* Define built-in placeholder functions.
28+
*
29+
* @return void
30+
*/
31+
protected function defineFunctions(): void
32+
{
33+
$this->functions['exists'] ??= function ($value) {
34+
return $value == '' ? '0' : '1';
35+
};
36+
37+
$this->functions['ok'] ??= function ($value) {
38+
return $value ? '1' : '0';
39+
};
40+
}
41+
42+
/**
43+
* Register a custom function for use in placeholders.
44+
*
45+
* @param string $name Function identifier
46+
* @param callable $func Function handler
47+
* @return void
48+
*/
49+
public function addFunc(string $name, callable $func): void
50+
{
51+
$this->functions[$name] = $func;
52+
}
53+
54+
/**
55+
* Check if a function is registered.
56+
*
57+
* @param string $name Function identifier
58+
* @return bool
59+
*/
60+
public function hasFunc(string $name): bool
61+
{
62+
return isset($this->functions[$name]);
63+
}
64+
65+
/**
66+
* Remove a registered function.
67+
*
68+
* @param string $name Function identifier
69+
* @return bool True if removed, false otherwise
70+
*/
71+
public function delFunc(string $name): bool
72+
{
73+
if (isset($this->functions[$name])) {
74+
unset($this->functions[$name]);
75+
return true;
76+
}
77+
78+
return false;
79+
}
80+
81+
/**
82+
* Render text by replacing placeholders with variables
83+
* and applying chained functions.
84+
*
85+
* @param string $text Input text
86+
* @param array $vars Variables for binding
87+
* @param bool $default Replace missing variables with empty string
88+
* @return string
89+
*/
90+
public function render(string $text, array $vars, bool $default = true): string
91+
{
92+
if (!$vars) {
93+
return $text;
94+
}
95+
96+
// Pattern for single braces with function support: {name} or {name.func1.func2}
97+
$text = preg_replace_callback(
98+
'/\{\s*([a-zA-Z0-9_-]+(?:\.[^.\s}]+)*)\s*}/',
99+
function ($matches) use ($vars, $default) {
100+
$parts = explode('.', $matches[1]);
101+
$key = array_shift($parts);
102+
103+
if (isset($vars[$key])) {
104+
$value = $vars[$key];
105+
} elseif ($default) {
106+
$value = '';
107+
} else {
108+
return $matches[0];
109+
}
110+
111+
// Apply functions in chain
112+
foreach ($parts as $func) {
113+
$handle = false;
114+
115+
if (isset($this->functions[$func])) {
116+
$value = $this->functions[$func]($value);
117+
$handle = true;
118+
} elseif (function_exists($func)) {
119+
$value = $func($value);
120+
$handle = true;
121+
}
122+
123+
if ($handle) {
124+
$value = $this->handleFunctionOutput($value);
125+
}
126+
}
127+
128+
return $value;
129+
},
130+
$text
131+
);
132+
133+
return $text;
134+
}
135+
136+
/**
137+
* Normalize function output before further processing.
138+
*
139+
* @param mixed $value
140+
* @return string
141+
*/
142+
protected function handleFunctionOutput($value): string
143+
{
144+
// Convert to string if it's a boolean or null
145+
if (is_bool($value)) {
146+
return $value ? '1' : '0';
147+
}
148+
149+
if (is_null($value)) {
150+
return '';
151+
}
152+
153+
// Convert arrays/objects to string representation
154+
if (is_array($value) || is_object($value)) {
155+
return json_encode($value);
156+
}
157+
158+
return (string) $value;
159+
}
160+
}

0 commit comments

Comments
 (0)