Skip to content

Commit 8462018

Browse files
committed
devel: consolidate multiple smarty->assign into arrays
1 parent 5a8eca9 commit 8462018

1 file changed

Lines changed: 304 additions & 0 deletions

File tree

Lines changed: 304 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
1+
<?php
2+
3+
if ($argc < 2) {
4+
die("Usage: php refactor_smarty_assign_using_array.php <file|directory>\n");
5+
}
6+
7+
$target = $argv[1];
8+
9+
function getTokens($source)
10+
{
11+
return token_get_all($source);
12+
}
13+
14+
function processFile($filePath)
15+
{
16+
echo "Processing: $filePath\n";
17+
$source = file_get_contents($filePath);
18+
$tokens = token_get_all($source);
19+
20+
$newSource = '';
21+
$count = count($tokens);
22+
$i = 0;
23+
24+
$modified = false;
25+
26+
while ($i < $count) {
27+
// Look for $SMARTY->assign(
28+
// Expected sequence: T_VARIABLE ($SMARTY) -> T_OBJECT_OPERATOR (->) -> T_STRING (assign) -> (
29+
30+
$matchFound = false;
31+
32+
// Check if we are at start of a potential assign block
33+
if (is_array($tokens[$i]) && $tokens[$i][0] == T_VARIABLE && $tokens[$i][1] == '$SMARTY') {
34+
// Check ahead for -> assign (
35+
$j = $i + 1;
36+
while ($j < $count && is_array($tokens[$j]) && $tokens[$j][0] == T_WHITESPACE) {
37+
$j++; // skip whitespace
38+
}
39+
40+
if ($j < $count && is_array($tokens[$j]) && $tokens[$j][0] == T_OBJECT_OPERATOR) {
41+
$j++;
42+
while ($j < $count && is_array($tokens[$j]) && $tokens[$j][0] == T_WHITESPACE) {
43+
$j++; // skip whitespace
44+
}
45+
46+
if ($j < $count && is_array($tokens[$j]) && $tokens[$j][0] == T_STRING && $tokens[$j][1] == 'assign') {
47+
$j++;
48+
while ($j < $count && is_array($tokens[$j]) && $tokens[$j][0] == T_WHITESPACE) {
49+
$j++; // skip whitespace
50+
}
51+
52+
if ($j < $count && $tokens[$j] == '(') {
53+
// Found valid $SMARTY->assign( start
54+
55+
// Now we need to collect this assignment and any immediately following ones
56+
$assignments = [];
57+
$currentStart = $i;
58+
59+
// Parsing loop to collect consecutive assignments
60+
while (true) {
61+
// Check if this is a $SMARTY->assign call
62+
// Rewind slightly logic wise: we are essentially attempting to parse one full statement here
63+
// We need to verify it is exactly $SMARTY->assign('key', $val);
64+
65+
// Re-verify the sequence for the current potential assignment (since we loop)
66+
$tempJ = $currentStart;
67+
68+
// Skip whitespace
69+
while ($tempJ < $count && is_array($tokens[$tempJ]) && $tokens[$tempJ][0] == T_WHITESPACE) {
70+
$tempJ++;
71+
}
72+
73+
// Must be $SMARTY
74+
if (!($tempJ < $count && is_array($tokens[$tempJ]) && $tokens[$tempJ][0] == T_VARIABLE && $tokens[$tempJ][1] == '$SMARTY')) {
75+
break;
76+
}
77+
$tempJ++;
78+
79+
while ($tempJ < $count && is_array($tokens[$tempJ]) && $tokens[$tempJ][0] == T_WHITESPACE) {
80+
$tempJ++;
81+
}
82+
if (!($tempJ < $count && is_array($tokens[$tempJ]) && $tokens[$tempJ][0] == T_OBJECT_OPERATOR)) {
83+
break;
84+
}
85+
$tempJ++;
86+
87+
while ($tempJ < $count && is_array($tokens[$tempJ]) && $tokens[$tempJ][0] == T_WHITESPACE) {
88+
$tempJ++;
89+
}
90+
if (!($tempJ < $count && is_array($tokens[$tempJ]) && $tokens[$tempJ][0] == T_STRING && $tokens[$tempJ][1] == 'assign')) {
91+
break;
92+
}
93+
$tempJ++;
94+
95+
while ($tempJ < $count && is_array($tokens[$tempJ]) && $tokens[$tempJ][0] == T_WHITESPACE) {
96+
$tempJ++;
97+
}
98+
if (!($tempJ < $count && $tokens[$tempJ] == '(')) {
99+
break;
100+
}
101+
$openParenPos = $tempJ;
102+
$tempJ++;
103+
104+
// Now extraction of arguments: key and value
105+
// We only support simple string keys: 'key' or "key"
106+
// Value can be complex expression, UP TO the comma
107+
108+
while ($tempJ < $count && is_array($tokens[$tempJ]) && $tokens[$tempJ][0] == T_WHITESPACE) {
109+
$tempJ++;
110+
}
111+
112+
$keyTokens = [];
113+
if ($tempJ < $count && is_array($tokens[$tempJ]) && $tokens[$tempJ][0] == T_CONSTANT_ENCAPSED_STRING) {
114+
$keyTokens[] = $tokens[$tempJ];
115+
$tempJ++;
116+
} else {
117+
// First arg is not a simple string, abort this block logic
118+
break;
119+
}
120+
121+
while ($tempJ < $count && is_array($tokens[$tempJ]) && $tokens[$tempJ][0] == T_WHITESPACE) {
122+
$tempJ++;
123+
}
124+
125+
if (!($tempJ < $count && $tokens[$tempJ] == ',')) {
126+
// Only one argument? or "assign by ref"? ignored
127+
break;
128+
}
129+
$tempJ++; // consume comma
130+
131+
// Now capturing value until );
132+
// Careful with nested parens
133+
134+
$valueTokens = [];
135+
$parenDepth = 1; // We are inside assign( ...
136+
137+
while ($tempJ < $count) {
138+
$t = $tokens[$tempJ];
139+
if ($t == '(') {
140+
$parenDepth++;
141+
} elseif ($t == ')') {
142+
$parenDepth--;
143+
}
144+
145+
if ($parenDepth == 0) {
146+
// Found closing paren of assign(...)
147+
break;
148+
}
149+
150+
$valueTokens[] = $t;
151+
$tempJ++;
152+
}
153+
154+
if ($parenDepth != 0) {
155+
break; // formatting error or weirdness
156+
}
157+
158+
$closeParenPos = $tempJ;
159+
$tempJ++; // consume )
160+
161+
while ($tempJ < $count && is_array($tokens[$tempJ]) && $tokens[$tempJ][0] == T_WHITESPACE) {
162+
$tempJ++;
163+
}
164+
165+
if (!($tempJ < $count && $tokens[$tempJ] == ';')) {
166+
// Not a simple statement ending with ;
167+
break;
168+
}
169+
$semiColonPos = $tempJ;
170+
$tempJ++; // consume ;
171+
172+
// Success finding one assignment
173+
$assignments[] = [
174+
'key' => $keyTokens,
175+
'value' => $valueTokens,
176+
'end_pos' => $tempJ // exclusive
177+
];
178+
179+
// Prepare to look for next
180+
$currentStart = $tempJ;
181+
}
182+
183+
if (count($assignments) > 1) {
184+
// We found consecutive assignments!
185+
// Write replacement
186+
$matchFound = true;
187+
188+
// Check indentation of the first variable to try to preserve it
189+
// We can look at whitespace immediately preceding $i if any
190+
$baseIndent = "";
191+
if ($i > 0 && is_array($tokens[$i - 1]) && $tokens[$i - 1][0] == T_WHITESPACE) {
192+
$ws = $tokens[$i - 1][1];
193+
$pos = strrpos($ws, "\n");
194+
if ($pos !== false) {
195+
$baseIndent = substr($ws, $pos + 1);
196+
} else {
197+
$baseIndent = $ws;
198+
}
199+
}
200+
201+
$indentUnit = (strpos($baseIndent, "\t") !== false) ? "\t" : " ";
202+
$twoIndents = $indentUnit . $indentUnit;
203+
204+
$newSource .= "\$SMARTY->assign(\n";
205+
$newSource .= $baseIndent . $indentUnit . "array(\n";
206+
207+
foreach ($assignments as $idx => $assign) {
208+
$newSource .= $baseIndent . $twoIndents; // indent
209+
// Key
210+
foreach ($assign['key'] as $kt) {
211+
$newSource .= is_array($kt) ? $kt[1] : $kt;
212+
}
213+
$newSource .= " => ";
214+
// Value - process token by token
215+
$isFirstValueToken = true;
216+
$valueOutput = '';
217+
foreach ($assign['value'] as $vt) {
218+
$isWhitespace = is_array($vt) && $vt[0] == T_WHITESPACE;
219+
$tokenValue = is_array($vt) ? $vt[1] : $vt;
220+
221+
if ($isFirstValueToken) {
222+
// Strip only leading horizontal whitespace (spaces/tabs), not newlines
223+
$tokenValue = ltrim($tokenValue, " \t");
224+
if ($tokenValue === '') {
225+
continue;
226+
}
227+
$isFirstValueToken = false;
228+
}
229+
230+
// Only modify whitespace tokens, never string content
231+
if ($isWhitespace && strpos($tokenValue, "\n") !== false) {
232+
// Replace each newline + old indent with newline + shifted indent
233+
$wsLines = explode("\n", $tokenValue);
234+
for ($wl = 1; $wl < count($wsLines); $wl++) {
235+
$wsLine = $wsLines[$wl];
236+
if ($indentUnit === "\t") {
237+
$wsLine = str_replace(" ", "\t", $wsLine);
238+
}
239+
$wsLines[$wl] = $twoIndents . $wsLine;
240+
}
241+
$tokenValue = implode("\n", $wsLines);
242+
}
243+
244+
$valueOutput .= $tokenValue;
245+
}
246+
247+
// Clean trailing whitespace on each line of the final value
248+
$valueLines = explode("\n", $valueOutput);
249+
foreach ($valueLines as &$vLine) {
250+
$vLine = rtrim($vLine);
251+
}
252+
$valueOutput = implode("\n", $valueLines);
253+
254+
// If value starts with newline, trim trailing space from "=> " on the key line
255+
if (strlen($valueOutput) > 0 && $valueOutput[0] === "\n") {
256+
$newSource = rtrim($newSource);
257+
}
258+
259+
$newSource .= $valueOutput;
260+
261+
$newSource .= ",\n";
262+
}
263+
264+
$newSource .= $baseIndent . $indentUnit . ")\n";
265+
$newSource .= $baseIndent . ");";
266+
267+
// Advance main loop to end of last assignment
268+
$i = $assignments[count($assignments)-1]['end_pos'];
269+
$modified = true;
270+
} else {
271+
// Only 0 or 1 assignment found, not enough to merge, or structure wasn't perfect
272+
// Just print the token at $i and move on normally
273+
// We fall through to default printer
274+
}
275+
}
276+
}
277+
}
278+
}
279+
280+
if (!$matchFound && $i < $count) {
281+
$token = $tokens[$i];
282+
$newSource .= is_array($token) ? $token[1] : $token;
283+
$i++;
284+
}
285+
}
286+
287+
if ($modified) {
288+
file_put_contents($filePath, $newSource);
289+
echo "Modified: $filePath\n";
290+
}
291+
}
292+
293+
if (is_dir($target)) {
294+
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($target));
295+
foreach ($iterator as $file) {
296+
if ($file->isFile() && $file->getExtension() === 'php') {
297+
processFile($file->getPathname());
298+
}
299+
}
300+
} elseif (is_file($target)) {
301+
processFile($target);
302+
} else {
303+
die("Invalid target.\n");
304+
}

0 commit comments

Comments
 (0)