Skip to content

Commit 3a25196

Browse files
committed
Disable dot helper when used inside isset()
1 parent 561fcfa commit 3a25196

File tree

4 files changed

+54
-17
lines changed

4 files changed

+54
-17
lines changed

src/JsPhpize/Compiler/Compiler.php

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -205,12 +205,12 @@ protected function visitDyiade(Dyiade $dyiade, $indent)
205205
return $leftHand . ' ' . $dyiade->operator . ' ' . $rightHand;
206206
}
207207

208-
protected function mapNodesArray($array, $indent, $pattern = null)
208+
protected function mapNodesArray($array, $indent, $pattern = null, $dotDisabled = false)
209209
{
210210
$visitNode = [$this, 'visitNode'];
211211

212-
return array_map(function ($value) use ($visitNode, $indent, $pattern) {
213-
$value = $visitNode($value, $indent);
212+
return array_map(function ($value) use ($visitNode, $indent, $pattern, $dotDisabled) {
213+
$value = $visitNode($value, $indent, $dotDisabled);
214214

215215
if ($pattern) {
216216
$value = sprintf($pattern, $value);
@@ -220,17 +220,17 @@ protected function mapNodesArray($array, $indent, $pattern = null)
220220
}, $array);
221221
}
222222

223-
protected function visitNodesArray($array, $indent, $glue = '', $pattern = null)
223+
protected function visitNodesArray($array, $indent, $glue = '', $pattern = null, $dotDisabled = false)
224224
{
225-
return implode($glue, $this->mapNodesArray($array, $indent, $pattern));
225+
return implode($glue, $this->mapNodesArray($array, $indent, $pattern, $dotDisabled));
226226
}
227227

228228
protected function visitFunctionCall(FunctionCall $functionCall, $indent)
229229
{
230230
$function = $functionCall->function;
231231
$arguments = $functionCall->arguments;
232232
$applicant = $functionCall->applicant;
233-
$arguments = $this->visitNodesArray($arguments, $indent, ', ');
233+
$arguments = $this->visitNodesArray($arguments, $indent, ', ', null, $function instanceof Variable && $function->name === 'isset');
234234
$dynamicCall = $this->visitNode($function, $indent) . '(' . $arguments . ')';
235235

236236
if ($function instanceof Variable && count($function->children) === 0) {
@@ -286,14 +286,14 @@ protected function visitInstruction(Instruction $group, $indent)
286286
}, $group->instructions));
287287
}
288288

289-
public function visitNode(Node $node, $indent)
289+
public function visitNode(Node $node, $indent, $dotDisabled = false)
290290
{
291291
$method = preg_replace(
292292
'/^(.+\\\\)?([^\\\\]+)$/',
293293
'visit$2',
294294
get_class($node)
295295
);
296-
$php = method_exists($this, $method) ? $this->$method($node, $indent) : '';
296+
$php = method_exists($this, $method) ? $this->$method($node, $indent, $dotDisabled) : '';
297297

298298
if ($node instanceof Value) {
299299
$php = $node->getBefore() . $php . $node->getAfter();
@@ -314,19 +314,33 @@ protected function visitTernary(Ternary $ternary, $indent)
314314
' : ' . $this->visitNode($ternary->falseValue, $indent);
315315
}
316316

317-
protected function handleVariableChildren(DynamicValue $dynamicValue, $indent, $php)
317+
protected function handleVariableChildren(DynamicValue $dynamicValue, $indent, $php, $dotDisabled = false)
318318
{
319-
if (count($dynamicValue->children)) {
320-
$arguments = $this->mapNodesArray($dynamicValue->children, $indent);
319+
$children = $dynamicValue->children;
320+
321+
if (count($children)) {
322+
$arguments = $this->mapNodesArray($children, $indent, null, $dotDisabled);
321323
array_unshift($arguments, $php);
322324
$dot = $this->engine->getHelperName('dot');
325+
326+
if ($dotDisabled) {
327+
$lastChild = end($children);
328+
$dotChild = $lastChild instanceof Constant && $lastChild->dotChild;
329+
$lastChild = array_pop($arguments);
330+
}
331+
323332
$php = $this->helperWrap($dot, $arguments);
333+
334+
if ($dotDisabled) {
335+
$pattern = $dotChild ? '%s->{%s}' : '%s[%s]';
336+
$php = sprintf($pattern, $php, $lastChild);
337+
}
324338
}
325339

326340
return $php;
327341
}
328342

329-
protected function visitVariable(Variable $variable, $indent)
343+
protected function visitVariable(Variable $variable, $indent, $dotDisabled = false)
330344
{
331345
$name = $variable->name;
332346
if (in_array($name, ['Math', 'RegExp'])) {
@@ -339,7 +353,7 @@ protected function visitVariable(Variable $variable, $indent)
339353
$name = '$' . $name;
340354
}
341355

342-
return $this->handleVariableChildren($variable, $indent, $name);
356+
return $this->handleVariableChildren($variable, $indent, $name, $dotDisabled);
343357
}
344358

345359
public function compile(Block $block, $indent = '')

src/JsPhpize/Nodes/Constant.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
/**
88
* Class Constant.
99
*
10-
* @property-read string $value raw value
11-
* @property-read string $type constant type
10+
* @property-read string $value raw value
11+
* @property-read string $type constant type
12+
* @property-read bool $dotChild rather is constant is used as an object child (dot operator, e.g. `->` for PHP)
1213
*/
1314
class Constant extends Value implements Assignable
1415
{
@@ -22,22 +23,29 @@ class Constant extends Value implements Assignable
2223
*/
2324
protected $value;
2425

26+
/**
27+
* @var bool
28+
*/
29+
protected $dotChild;
30+
2531
/**
2632
* Constant constructor.
2733
*
2834
* @param $type
2935
* @param $value
36+
* @param $dotChild
3037
*
3138
* @throws Exception
3239
*/
33-
public function __construct($type, $value)
40+
public function __construct($type, $value, $dotChild = false)
3441
{
3542
if (!in_array($type, ['constant', 'number', 'string', 'regexp'])) {
3643
throw new Exception("The given type [$type] is not a valid constant type.", 23);
3744
}
3845

3946
$this->type = $type;
4047
$this->value = $value;
48+
$this->dotChild = $dotChild;
4149
}
4250

4351
public function getNonAssignableReason()

src/JsPhpize/Parser/TokenExtractor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ protected function getVariableChildFromToken(Token $token)
4141
$token = $this->next();
4242

4343
if ($token && $token->isValidMember()) {
44-
return new Constant('string', var_export($token->value, true));
44+
return new Constant('string', var_export($token->value, true), true);
4545
}
4646

4747
throw $this->unexpected($token);

tests/render.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,5 +133,20 @@ public function testDollarVariablePrefix()
133133
$this->assertFalse($jsPhpize->renderCode($code));
134134
$this->assertTrue($jsPhpize->renderCode($code, ['variable' => 1]));
135135
$this->assertFalse($jsPhpize->renderCode($code, ['variable' => false]));
136+
137+
$code = 'return $foo && isset($bar[$foo])';
138+
139+
$this->assertFalse($jsPhpize->renderCode($code, ['foo' => 'a']));
140+
$this->assertTrue($jsPhpize->renderCode($code, ['foo' => 'a', 'bar' => ['a' => 'x']]));
141+
142+
$code = 'return $foo && isset($bar.foo)';
143+
144+
$this->assertFalse($jsPhpize->renderCode($code, ['foo' => 'a']));
145+
$this->assertTrue($jsPhpize->renderCode($code, ['foo' => 'a', 'bar' => (object) ['foo' => 'x']]));
146+
147+
$code = 'return $foo && isset($bar["foo"])';
148+
149+
$this->assertFalse($jsPhpize->renderCode($code, ['foo' => 'a']));
150+
$this->assertTrue($jsPhpize->renderCode($code, ['foo' => 'a', 'bar' => ['foo' => 'x']]));
136151
}
137152
}

0 commit comments

Comments
 (0)