diff --git a/src/Compiler/CompileUtil.php b/src/Compiler/CompileUtil.php index e9eccd6..8ff4362 100644 --- a/src/Compiler/CompileUtil.php +++ b/src/Compiler/CompileUtil.php @@ -2,6 +2,10 @@ namespace PhpPkg\EasyTpl\Compiler; +use function defined; +use function str_contains; +use function str_starts_with; + /** * class CompileUtil * @@ -26,7 +30,22 @@ class CompileUtil */ public static function canAddVarPrefix(string $line): bool { - return $line[0] !== '$' && preg_match(self::REGEX_VAR_NAME, $line) === 1; + // has prefix or is magic const. (eg: __LINE__) + if ($line[0] === '$' || str_starts_with($line, '__')) { + return false; + } + + if (preg_match(self::REGEX_VAR_NAME, $line) === 1) { + if (str_contains($line, '.') || str_contains($line, '-')) { + return true; + } + + // up: check is const name + // - defined() cannot check magic const. (eg: __LINE__) + return !defined($line); + } + + return false; } /** diff --git a/test/Compiler/CompileUtilTest.php b/test/Compiler/CompileUtilTest.php index 90d085f..10da2c5 100644 --- a/test/Compiler/CompileUtilTest.php +++ b/test/Compiler/CompileUtilTest.php @@ -21,6 +21,8 @@ public function testCanAddVarPrefix(): void $this->assertFalse(CompileUtil::canAddVarPrefix("top['abc']")); $this->assertFalse(CompileUtil::canAddVarPrefix('abc()')); + $this->assertFalse(CompileUtil::canAddVarPrefix('PHP_OS')); + $this->assertFalse(CompileUtil::canAddVarPrefix('__LINE__')); } public function testPathToArrayAccess(): void diff --git a/test/Compiler/PregCompilerTest.php b/test/Compiler/PregCompilerTest.php index 12320fd..36c8878 100644 --- a/test/Compiler/PregCompilerTest.php +++ b/test/Compiler/PregCompilerTest.php @@ -63,7 +63,7 @@ public function testToken_getBlockNamePattern():void ]; $pattern = Token::getBlockNamePattern(); - vdump($pattern); + // vdump($pattern); foreach ($tests as [$in, $out]) { $ret = preg_match($pattern, $in, $matches); if ($out) { @@ -79,10 +79,27 @@ public function testCompileCode_inline_echo():void { $p = new PregCompiler(); + $this->assertNotEquals('', $p->compile('{{= name }}')); + $tests = [ ['{{ "a" . "b" }}', ''], + // const + ['{{ PHP_OS }}', ''], + ['{{= PHP_OS }}', ''], + ["{{\n PHP_OS }}", ""], + ['{{ echo PHP_OS }}', ''], + ['{{ __LINE__ }}', ''], + ['{{= __LINE__ }}', ''], + ['{{ echo __LINE__ }}', ''], + ['{{ SomeClass::NAME }}', ''], + ['{{ echo SomeClass::NAME }}', ''], + // prop + ['{{ SomeClass::$name }}', ''], + // var ['{{ name }}', ''], ['{{ $name }}', ''], + ['{{= $name }}', ''], + ['{{ echo $name }}', ''], ['{{ $name; }}', ''], ['{{ $name ?: "inhere" }}', ''], ['{{ $name ?? "inhere" }}', ''], @@ -104,37 +121,21 @@ public function testCompileCode_inline_echo():void // func ['{{ some_func() }}', ''], ['{{ some_func(); }}', ''], + ['{{ SomeClass::func(); }}', ''], ['{{ $this->include("header.tpl") }}', 'include("header.tpl") ?>'], + // more + [ + '{{= $ctx.pkgName ?? "org.example.entity" }}', + '' + ], + [ + '{{= $ctx->pkgName ?? "org.example.entity" }}', + 'pkgName ?? "org.example.entity" ?>' + ], ]; foreach ($tests as [$in, $out]) { $this->assertEquals($out, $p->compile($in)); } - - $tplCode = <<<'TPL' - -{{= $ctx.pkgName ?? "org.example.entity" }} - -TPL; - $compiled = $p->compile($tplCode); - // vdump($tplCode, $compiled); - $this->assertNotEmpty($compiled); - $this->assertEquals(<<<'CODE' - - - -CODE - ,$compiled); - - $tplCode = <<<'TPL' -{{= $ctx->pkgName ?? "org.example.entity" }} -TPL; - $compiled = $p->compile($tplCode); - // vdump($tplCode, $compiled); - $this->assertNotEmpty($compiled); - $this->assertEquals(<<<'CODE' -pkgName ?? "org.example.entity" ?> -CODE - ,$compiled); } public function testCompile_inline_echo_with_filters():void @@ -182,6 +183,38 @@ public function testCompile_disableEchoFilter():void } } + public function testCompile_ml_define():void + { + $p = new PregCompiler(); + + $code = <<<'CODE' +{{ + +$a = random_int(1, 10); +}} +CODE; + $compiled = $p->compile($code); + $this->assertEquals(<<<'CODE' + +CODE + ,$compiled); + + $code = <<<'CODE' +{{ +// comments +$a = random_int(1, 10); +}} +CODE; + $compiled = $p->compile($code); + $this->assertEquals(<<<'CODE' + +CODE + ,$compiled); + } + public function testCompile_comments():void { $p = new PregCompiler(); @@ -274,38 +307,6 @@ public function testCompile_foreach():void ,$compiled); } - public function testCompile_ml_define():void - { - $p = new PregCompiler(); - - $code = <<<'CODE' -{{ - -$a = random_int(1, 10); -}} -CODE; - $compiled = $p->compile($code); - $this->assertEquals(<<<'CODE' - -CODE - ,$compiled); - - $code = <<<'CODE' -{{ -// comments -$a = random_int(1, 10); -}} -CODE; - $compiled = $p->compile($code); - $this->assertEquals(<<<'CODE' - -CODE - ,$compiled); - } - public function testCompile_customDirective_include():void { $p = new PregCompiler();