diff --git a/library/think/Template.php b/library/think/Template.php index 3ec89e56..91741571 100644 --- a/library/think/Template.php +++ b/library/think/Template.php @@ -12,6 +12,7 @@ namespace think; use think\exception\TemplateNotFoundException; +use think\template\TagLib; /** * ThinkPHP分离出来的模板引擎 @@ -121,7 +122,7 @@ class Template * 模板引擎配置项 * @access public * @param array|string $config - * @return void|array + * @return string|void|array */ public function config($config) { @@ -235,7 +236,7 @@ class Template * @access public * @param mixed $name 布局模板名称 false 则关闭布局 * @param string $replace 布局模板内容替换标识 - * @return object + * @return Template */ public function layout($name, $replace = '') { @@ -689,6 +690,7 @@ class Template } else { $className = '\\think\\template\\taglib\\' . ucwords($tagLib); } + /** @var Taglib $tLib */ $tLib = new $className($this); $tLib->parseTag($content, $hide ? '' : $tagLib); return; @@ -1071,7 +1073,7 @@ class Template } else { $path = isset($module) ? APP_PATH . $module . DS . basename($this->config['view_path']) . DS : $this->config['view_path']; } - $template = $path . $template . '.' . ltrim($this->config['view_suffix'], '.'); + $template = realpath($path . $template . '.' . ltrim($this->config['view_suffix'], '.')); } if (is_file($template)) { diff --git a/tests/thinkphp/library/think/display.html b/tests/application/views/display.html similarity index 100% rename from tests/thinkphp/library/think/display.html rename to tests/application/views/display.html diff --git a/tests/application/views/display.phtml b/tests/application/views/display.phtml new file mode 100644 index 00000000..e99d3025 --- /dev/null +++ b/tests/application/views/display.phtml @@ -0,0 +1 @@ +{$name??'default'} \ No newline at end of file diff --git a/tests/thinkphp/library/think/extend.html b/tests/application/views/extend.html similarity index 100% rename from tests/thinkphp/library/think/extend.html rename to tests/application/views/extend.html diff --git a/tests/thinkphp/library/think/extend2.html b/tests/application/views/extend2.html similarity index 100% rename from tests/thinkphp/library/think/extend2.html rename to tests/application/views/extend2.html diff --git a/tests/thinkphp/library/think/include.html b/tests/application/views/include.html similarity index 100% rename from tests/thinkphp/library/think/include.html rename to tests/application/views/include.html diff --git a/tests/thinkphp/library/think/include2.html b/tests/application/views/include2.html similarity index 100% rename from tests/thinkphp/library/think/include2.html rename to tests/application/views/include2.html diff --git a/tests/thinkphp/library/think/layout.html b/tests/application/views/layout.html similarity index 100% rename from tests/thinkphp/library/think/layout.html rename to tests/application/views/layout.html diff --git a/tests/thinkphp/library/think/layout2.html b/tests/application/views/layout2.html similarity index 100% rename from tests/thinkphp/library/think/layout2.html rename to tests/application/views/layout2.html diff --git a/tests/thinkphp/library/think/controllerTest.php b/tests/thinkphp/library/think/controllerTest.php index fba8d6c5..4164770e 100644 --- a/tests/thinkphp/library/think/controllerTest.php +++ b/tests/thinkphp/library/think/controllerTest.php @@ -40,13 +40,13 @@ class Foo extends Controller public function fetchTest() { - $template = dirname(__FILE__) . '/display.html'; + $template = APP_PATH . 'views' . DS .'display.html'; return $this->fetch($template, ['name' => 'ThinkPHP']); } public function displayTest() { - $template = dirname(__FILE__) . '/display.html'; + $template = APP_PATH . 'views' . DS .'display.html'; return $this->display($template, ['name' => 'ThinkPHP']); } public function test() @@ -161,7 +161,7 @@ class controllerTest extends \PHPUnit_Framework_TestCase { $controller = new Foo(Request::instance()); $view = $this->getView($controller); - $template = dirname(__FILE__) . '/display.html'; + $template = APP_PATH . 'views' . DS .'display.html'; $viewFetch = $view->fetch($template, ['name' => 'ThinkPHP']); $this->assertEquals($controller->fetchTest(), $viewFetch); } @@ -170,7 +170,7 @@ class controllerTest extends \PHPUnit_Framework_TestCase { $controller = new Foo; $view = $this->getView($controller); - $template = dirname(__FILE__) . '/display.html'; + $template = APP_PATH . 'views' . DS .'display.html'; $viewFetch = $view->display($template, ['name' => 'ThinkPHP']); $this->assertEquals($controller->displayTest(), $viewFetch); diff --git a/tests/thinkphp/library/think/templateTest.php b/tests/thinkphp/library/think/templateTest.php index a23cb7c0..11358306 100644 --- a/tests/thinkphp/library/think/templateTest.php +++ b/tests/thinkphp/library/think/templateTest.php @@ -16,331 +16,160 @@ namespace tests\thinkphp\library\think; +use think\Cache; use think\Template; class templateTest extends \PHPUnit_Framework_TestCase { - public function testVar() + /** + * @var Template + */ + protected $template; + + public function setUp() { - $template = new Template(); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($data, $content); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($data, $content); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($data, $content); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($data, $content); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($data, $content); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($data, $content); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($data, $content); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($data, $content); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($data, $content); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($data, $content); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($data, $content); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($data, $content); - - $content = <<parse($content); - $this->assertEquals($data, $content); - - $content = <<parse($content); - $this->assertEquals($data, $content); - + $this->template = new Template(); } - public function testVarFunction() + public function testAssign() { - $template = new Template(); + $reflectProperty = new \ReflectionProperty(get_class($this->template), 'data'); + $reflectProperty->setAccessible(true); - $content = << -EOF; + $this->template->assign('version', 'ThinkPHP3.2'); + $data = $reflectProperty->getValue($this->template); + $this->assertEquals('ThinkPHP3.2', $data['version']); - $template->parse($content); - $this->assertEquals($data, $content); - - $content = << -EOF; - - $template->parse($content); - $this->assertEquals($data, $content); - - $content = << - -EOF; - - $template->parse($content); - $this->assertEquals($data, $content); + $this->template->assign(['name' => 'Gao', 'version' => 'ThinkPHP5']); + $data = $reflectProperty->getValue($this->template); + $this->assertEquals('Gao', $data['name']); + $this->assertEquals('ThinkPHP5', $data['version']); } - public function testVarIdentify() + public function testGet() { - $config['tpl_begin'] = '<#'; - $config['tpl_end'] = '#>'; - $config['tpl_var_identify'] = ''; - $template = new Template($config); + $this->template = new Template(); + $data = [ + 'project' => 'ThinkPHP', + 'version' => [ + 'ThinkPHP5' => ['Think5.0', 'Think5.1'] + ] + ]; + $this->template->assign($data); - $content = << -EOF; - $data = <<a)) ? (is_array(\$info)?\$info['a']:\$info->a) : 'test'; ?> -EOF; - - $template->parse($content); - $this->assertEquals($data, $content); - - $content = << -EOF; - $data = <<a)) echo 'test'; ?> -EOF; - - $template->parse($content); - $this->assertEquals($data, $content); - - $content = << -EOF; - $data = <<a)==(is_array(\$info)?\$info['b']:\$info->b)) echo 'test'; ?> -EOF; - - $template->parse($content); - $this->assertEquals($data, $content); - - $content = << -EOF; - $data = <<a) ?: 'test')?'yes':'no'; ?> -EOF; - $template->parse($content); - $this->assertEquals($data, $content); - - $template2 = new Template(); - $template2->tpl_var_identify = 'obj'; - $content = <<b)?'yes':'no'; ?> -EOF; - $template2->parse($content); - $this->assertEquals($data, $content); + $this->assertSame($data, $this->template->get()); + $this->assertSame('ThinkPHP', $this->template->get('project')); + $this->assertSame(['Think5.0', 'Think5.1'], $this->template->get('version.ThinkPHP5')); + $this->assertNull($this->template->get('version.ThinkPHP3.2')); } - public function testThinkVar() + /** + * @dataProvider provideTestParseWithVar + */ + public function testParseWithVar($content, $expected) + { + $this->template = new Template(); + + $this->template->parse($content); + $this->assertEquals($expected, $content); + } + + /** + * @dataProvider provideTestParseWithVarFunction + */ + public function testParseWithVarFunction($content, $expected) + { + $this->template = new Template(); + + $this->template->parse($content); + $this->assertEquals($expected, $content); + } + + /** + * @dataProvider provideTestParseWithVarIdentify + */ + public function testParseWithVarIdentify($content, $expected, $config) + { + $this->template = new Template($config); + + $this->template->parse($content); + $this->assertEquals($expected, $content); + } + + /** + * @dataProvider provideTestParseWithThinkVar + */ + public function testParseWithThinkVar($content, $expected) { $config['tpl_begin'] = '{'; $config['tpl_end'] = '}'; - $template = new Template($config); + $this->template = new Template($config); $_SERVER['SERVER_NAME'] = 'server_name'; $_GET['action'] = 'action'; $_POST['action'] = 'action'; $_COOKIE['name'] = 'name'; $_SESSION['action'] = ['name' => 'name']; - define('SITE_NAME', 'site_name'); - $content = << -{\$Think.GET.action}
-{\$Think.POST.action}
-{\$Think.COOKIE.action}
-{\$Think.COOKIE.action.name}
-{\$Think.SESSION.action}
-{\$Think.SESSION.action.name}
-{\$Think.ENV.OS}
-{\$Think.REQUEST.action}
-{\$Think.CONST.SITE_NAME}
-{\$Think.LANG.action}
-{\$Think.CONFIG.action.name}
-{\$Think.NOW}
-{\$Think.VERSION}
-{\$Think.LDELIM}
-{\$Think.RDELIM}
-{\$Think.SITE_NAME}
-{\$Think.SITE.URL} -EOF; - $data = <<server('SERVER_NAME'); ?>
-get('action'); ?>
-post('action'); ?>
-
-
-
-
-env('OS'); ?>
-request('action'); ?>
-
-
-
-
-
-
-
-
- -EOF; - $template->parse($content); - $this->assertEquals($data, $content); + $this->template->parse($content); + $this->assertEquals($expected, $content); } - public function testFetch() + /** + * @expectedException \think\exception\TemplateNotFoundException + */ + public function testFetchWithEmptyTemplate() { - $template = new Template(); - $template->assign('name', 'name'); + $this->template = new Template(); + + $this->template->fetch('Foo'); + } + + /** + * @dataProvider provideTestFetchWithNoCache + */ + public function testFetchWithNoCache($data, $expected) + { + $this->template = new Template(); + + $this->template->fetch($data['template'], $data['vars'], $data['config']); + + $this->expectOutputString($expected); + } + + public function testFetchWithCache() + { + $this->template = new Template(); + + $data = [ + 'name' => 'value' + ]; $config = [ - 'strip_space' => true, - 'view_path' => dirname(__FILE__) . DS, - 'cache_id' => '__CACHE_ID__', + 'cache_id' => 'TEST_FETCH_WITH_CACHE', 'display_cache' => true, ]; - $data = ['name' => 'value']; - $template->layout('layout')->fetch('display', $data, $config); + + $this->template->fetch(APP_PATH . 'views' . DS .'display.html', $data, $config); + $this->expectOutputString('value'); + $this->assertEquals('value', Cache::get($config['cache_id'])); } public function testDisplay() { - $config['view_path'] = dirname(__FILE__) . DS; - $config['view_suffix'] = '.html'; - $config['layout_on'] = true; - $config['layout_name'] = 'layout'; - $template = new Template($config); - $files = ['extend' => 'extend', 'include' => 'include']; - $template->assign('files', $files); - $template->assign('user', ['name' => 'name', 'account' => 100]); - $template->assign('message', 'message'); - $template->assign('info', ['value' => 'value']); + $config = [ + 'view_path' => APP_PATH . DS . 'views' . DS, + 'view_suffix' => '.html', + 'layout_on' => true, + 'layout_name' => 'layout' + ]; + + $this->template = new Template($config); + + $this->template->assign('files', ['extend' => 'extend', 'include' => 'include']); + $this->template->assign('user', ['name' => 'name', 'account' => 100]); + $this->template->assign('message', 'message'); + $this->template->assign('info', ['value' => 'value']); $content = << header
@@ -382,33 +211,205 @@ value: php code
EOF; - $template->display($content); - $this->expectOutputString($content2); -// $template->parse($content); - // var_dump($content); + $this->template->display($content); + $this->expectOutputString($expected); } - public function testVarAssign() + /** + * @dataProvider provideTestLayout + */ + public function testLayout($data, $expected) { - $template = new Template(); - $template->assign('name', 'value'); - $value = $template->get('name'); - $this->assertEquals('value', $value); + $this->template = new Template(); + + $this->template->layout($data['name'], $data['replace']); + + $this->assertSame($expected['layout_on'], $this->template->config('layout_on')); + $this->assertSame($expected['layout_name'], $this->template->config('layout_name')); + $this->assertSame($expected['layout_item'], $this->template->config('layout_item')); } - public function testVarGet() + public function testParseAttr() { - $template = new Template(); - $data = ['a' => 'a', 'b' => 'b']; - $template->assign($data); - $this->assertEquals($data, $template->get()); + $attributes = $this->template->parseAttr(""); + $this->assertSame(['version' => 'ThinkPHP', 'name' => 'Gao'], $attributes); + + $attributes = $this->template->parseAttr("TestCase", 'version'); + $this->assertSame('ThinkPHP', $attributes); } public function testIsCache() { - $template = new Template(['cache_id' => '__CACHE_ID__', 'display_cache' => true]); - $this->assertTrue($template->isCache('__CACHE_ID__')); - $template->display_cache = false; - $this->assertTrue(!$template->isCache('__CACHE_ID__')); + $this->template = new Template(); + $config = [ + 'cache_id' => rand(0, 10000) . rand(0, 10000) . time(), + 'display_cache' => true + ]; + + $this->assertFalse($this->template->isCache($config['cache_id'])); + + $this->template->fetch(APP_PATH . 'views' . DS .'display.html', [], $config); + $this->assertTrue($this->template->isCache($config['cache_id'])); + } + + public function provideTestParseWithVar() + { + return [ + ["{\$name.a.b}", ""], + ["{\$name.a??'test'}", ""], + ["{\$name.a?='test'}", ""], + ["{\$name.a?:'test'}", ""], + ["{\$name.a?\$name.b:'no'}", ""], + ["{\$name.a==\$name.b?='test'}", ""], + ["{\$name.a==\$name.b?'a':'b'}", ""], + ["{\$name.a|default='test'==\$name.b?'a':'b'}", ""], + ["{\$name.a|trim==\$name.b?='eq'}", ""], + ["{:ltrim(rtrim(\$name.a))}", ""], + ["{~echo(trim(\$name.a))}", ""], + ["{++\$name.a}", ""], + ["{/*\$name*/}", ""], + ["{\$0a}", "{\$0a}"] + ]; + } + + public function provideTestParseWithVarFunction() + { + return [ + ["{\$name.a.b|default='test'}", ""], + ["{\$create_time|date=\"y-m-d\",###}", ""], + ["{\$name}\n{\$name|trim|substr=0,3}", "\n"] + ]; + } + + public function provideTestParseWithVarIdentify() + { + $config['tpl_begin'] = '<#'; + $config['tpl_end'] = '#>'; + $config['tpl_var_identify'] = ''; + + return [ + [ + "<#\$info.a??'test'#>", + "a)) ? (is_array(\$info)?\$info['a']:\$info->a) : 'test'; ?>", + $config + ], + [ + "<#\$info.a?='test'#>", + "a)) echo 'test'; ?>", + $config + ], + [ + "<#\$info.a==\$info.b?='test'#>", + "a)==(is_array(\$info)?\$info['b']:\$info->b)) echo 'test'; ?>", + $config + ], + [ + "<#\$info.a|default='test'?'yes':'no'#>", + "a) ?: 'test')?'yes':'no'; ?>", + $config + ], + [ + "{\$info2.b|trim?'yes':'no'}", + "b)?'yes':'no'; ?>", + array_merge(['tpl_var_identify' => 'obj']) + ] + ]; + } + + public function provideTestParseWithThinkVar() + { + return [ + ["{\$Think.SERVER.SERVER_NAME}
", "server('SERVER_NAME'); ?>
"], + ["{\$Think.GET.action}
", "get('action'); ?>
"], + ["{\$Think.POST.action}
", "post('action'); ?>
"], + ["{\$Think.COOKIE.action}
", "
"], + ["{\$Think.COOKIE.action.name}
", "
"], + ["{\$Think.SESSION.action}
", "
"], + ["{\$Think.SESSION.action.name}
", "
"], + ["{\$Think.ENV.OS}
", "env('OS'); ?>
"], + ["{\$Think.REQUEST.action}
", "request('action'); ?>
"], + ["{\$Think.CONST.THINK_VERSION}
", "
"], + ["{\$Think.LANG.action}
", "
"], + ["{\$Think.CONFIG.action.name}
", "
"], + ["{\$Think.NOW}
", "
"], + ["{\$Think.VERSION}
", "
"], + ["{\$Think.LDELIM}
", "
"], + ["{\$Think.RDELIM}
", "
"], + ["{\$Think.THINK_VERSION}
", "
"], + ["{\$Think.SITE.URL}", ""] + ]; + } + + public function provideTestFetchWithNoCache() + { + $provideData = []; + + $this->template = [ + 'template' => APP_PATH . 'views' . DS .'display.html', + 'vars' => [], + 'config' => [] + ]; + $expected = 'default'; + $provideData[] = [$this->template, $expected]; + + $this->template = [ + 'template' => APP_PATH . 'views' . DS .'display.html', + 'vars' => ['name' => 'ThinkPHP5'], + 'config' => [] + ]; + $expected = 'ThinkPHP5'; + $provideData[] = [$this->template, $expected]; + + $this->template = [ + 'template' => 'views@display', + 'vars' => [], + 'config' => [ + 'view_suffix' => 'html' + ] + ]; + $expected = 'default'; + $provideData[] = [$this->template, $expected]; + + $this->template = [ + 'template' => 'views@/display', + 'vars' => ['name' => 'ThinkPHP5'], + 'config' => [ + 'view_suffix' => 'phtml' + ] + ]; + $expected = 'ThinkPHP5'; + $provideData[] = [$this->template, $expected]; + + $this->template = [ + 'template' => 'display', + 'vars' => ['name' => 'ThinkPHP5'], + 'config' => [ + 'view_suffix' => 'html', + 'view_base' => APP_PATH . 'views' . DS + ] + ]; + $expected = 'ThinkPHP5'; + $provideData[] = [$this->template, $expected]; + + return $provideData; + } + + public function provideTestLayout() + { + $provideData = []; + + $data = ['name' => false, 'replace' => '']; + $expected = ['layout_on' => false, 'layout_name' => 'layout', 'layout_item' => '{__CONTENT__}']; + $provideData[] = [$data, $expected]; + + $data = ['name' => null, 'replace' => '']; + $expected = ['layout_on' => true, 'layout_name' => 'layout', 'layout_item' => '{__CONTENT__}']; + $provideData[] = [$data, $expected]; + + $data = ['name' => 'ThinkName', 'replace' => 'ThinkReplace']; + $expected = ['layout_on' => true, 'layout_name' => 'ThinkName', 'layout_item' => 'ThinkReplace']; + $provideData[] = [$data, $expected]; + + return $provideData; } }