diff --git a/system/Common.php b/system/Common.php index 476348caaea0..28fc3cb52f5e 100644 --- a/system/Common.php +++ b/system/Common.php @@ -38,6 +38,7 @@ */ use Config\App; +use Config\View; use Config\Logger; use Config\Database; use Config\Services; @@ -1069,8 +1070,9 @@ function view(string $name, array $data = [], array $options = []): string */ $renderer = Services::renderer(); - $saveData = true; - if (array_key_exists('saveData', $options) && $options['saveData'] === true) + $saveData = config(View::class)->saveData; + + if (array_key_exists('saveData', $options)) { $saveData = (bool) $options['saveData']; unset($options['saveData']); diff --git a/system/View/Parser.php b/system/View/Parser.php index fcdd0ed15c22..051b059e0293 100644 --- a/system/View/Parser.php +++ b/system/View/Parser.php @@ -93,11 +93,11 @@ class Parser extends View /** * Constructor * - * @param \Config\View $config - * @param string $viewPath - * @param mixed $loader - * @param boolean $debug - * @param LoggerInterface $logger + * @param \Config\View $config + * @param string $viewPath + * @param mixed $loader + * @param boolean $debug + * @param LoggerInterface $logger */ public function __construct($config, string $viewPath = null, $loader = null, bool $debug = null, LoggerInterface $logger = null) { @@ -157,20 +157,25 @@ public function render(string $view, array $options = null, bool $saveData = nul throw ViewException::forInvalidFile($file); } + if (is_null($this->tempData)) + { + $this->tempData = $this->data; + } + $template = file_get_contents($file); - $output = $this->parse($template, $this->data, $options); + $output = $this->parse($template, $this->tempData, $options); $this->logPerformance($start, microtime(true), $view); - if (! $saveData) + if ($saveData) { - $this->data = []; + $this->data = $this->tempData; } // Should we cache? if (isset($options['cache'])) { cache()->save($cacheName, $output, (int) $options['cache']); } - + $this->tempData = null; return $output; } @@ -196,14 +201,22 @@ public function renderString(string $template, array $options = null, bool $save $saveData = $this->config->saveData; } - $output = $this->parse($template, $this->data, $options); + if (is_null($this->tempData)) + { + $this->tempData = $this->data; + } + + $output = $this->parse($template, $this->tempData, $options); $this->logPerformance($start, microtime(true), $this->excerpt($template)); - if (! $saveData) + if ($saveData) { - $this->data = []; + $this->data = $this->tempData; } + + $this->tempData = null; + return $output; } @@ -243,7 +256,8 @@ public function setData(array $data = [], string $context = null): RendererInter } } - $this->data = array_merge($this->data, $data); + $this->tempData = $this->tempData ?? $this->data; + $this->tempData = array_merge($this->tempData, $data); return $this; } @@ -532,7 +546,14 @@ protected function parseConditionals(string $template): string // Parse the PHP itself, or insert an error so they can debug ob_start(); - extract($this->data); + + if (is_null($this->tempData)) + { + $this->tempData = $this->data; + } + + extract($this->tempData); + try { eval('?>' . $template . '', 'saveData = $saveData; + $saveData = $this->saveData; } - $fileExt = pathinfo($view, PATHINFO_EXTENSION); $realPath = empty($fileExt) ? $view . '.php' : $view; // allow Views as .html, .tpl, etc (from CI3) $this->renderVars['view'] = $realPath; @@ -225,11 +229,17 @@ public function render(string $view, array $options = null, bool $saveData = nul } // Make our view data available to the view. - extract($this->data); - if (! $this->saveData) + if (is_null($this->tempData)) { - $this->data = []; + $this->tempData = $this->data; + } + + extract($this->tempData); + + if ($saveData) + { + $this->data = $this->tempData; } ob_start(); @@ -277,6 +287,8 @@ public function render(string $view, array $options = null, bool $saveData = nul cache()->save($this->renderVars['cacheName'], $output, (int) $this->renderVars['options']['cache']); } + $this->tempData = null; + return $output; } @@ -300,16 +312,22 @@ public function render(string $view, array $options = null, bool $saveData = nul public function renderString(string $view, array $options = null, bool $saveData = null): string { $start = microtime(true); + if (is_null($saveData)) { - $saveData = $this->config->saveData; + $saveData = $this->saveData; } - extract($this->data); + if (is_null($this->tempData)) + { + $this->tempData = $this->data; + } + + extract($this->tempData); - if (! $saveData) + if ($saveData) { - $this->data = []; + $this->data = $this->tempData; } ob_start(); @@ -320,6 +338,8 @@ public function renderString(string $view, array $options = null, bool $saveData $this->logPerformance($start, microtime(true), $this->excerpt($view)); + $this->tempData = null; + return $output; } @@ -355,7 +375,8 @@ public function setData(array $data = [], string $context = null): RendererInter $data = \esc($data, $context); } - $this->data = array_merge($this->data, $data); + $this->tempData = $this->tempData ?? $this->data; + $this->tempData = array_merge($this->tempData, $data); return $this; } @@ -379,7 +400,8 @@ public function setVar(string $name, $value = null, string $context = null): Ren $value = \esc($value, $context); } - $this->data[$name] = $value; + $this->tempData = $this->tempData ?? $this->data; + $this->tempData[$name] = $value; return $this; } @@ -407,7 +429,7 @@ public function resetData(): RendererInterface */ public function getData(): array { - return $this->data; + return is_null($this->tempData) ? $this->data : $this->tempData; } //-------------------------------------------------------------------- diff --git a/tests/_support/View/Views/simples.php b/tests/_support/View/Views/simples.php new file mode 100644 index 000000000000..74c2b3710760 --- /dev/null +++ b/tests/_support/View/Views/simples.php @@ -0,0 +1 @@ +

\ No newline at end of file diff --git a/tests/system/CommonFunctionsTest.php b/tests/system/CommonFunctionsTest.php index a855d0ceb296..2853b6d08fc3 100644 --- a/tests/system/CommonFunctionsTest.php +++ b/tests/system/CommonFunctionsTest.php @@ -25,7 +25,8 @@ class CommonFunctionsTest extends \CodeIgniter\Test\CIUnitTestCase protected function setUp(): void { parent::setUp(); - + $renderer = Services::renderer(); + $renderer->resetData(); unset($_ENV['foo'], $_SERVER['foo']); } @@ -429,4 +430,14 @@ public function testTrace() $this->assertStringContainsString('Debug Backtrace', $content); } + public function testViewNotSaveData() + { + $data = [ + 'testString' => 'bar', + 'bar' => 'baz', + ]; + $this->assertStringContainsString('

bar

', view('\Tests\Support\View\Views\simples', $data, ['saveData' => false])); + $this->assertStringContainsString('

is_not

', view('\Tests\Support\View\Views\simples')); + } + } diff --git a/tests/system/View/ParserTest.php b/tests/system/View/ParserTest.php index b25927d7eb47..6ab515340af1 100644 --- a/tests/system/View/ParserTest.php +++ b/tests/system/View/ParserTest.php @@ -940,27 +940,31 @@ public function testRenderCantFindView() public function testRenderSavingData() { - $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $parser = new Parser($this->config, $this->viewsDir, $this->loader); + $expected = "

Hello World

\n"; + $parser->setData(['testString' => 'Hello World']); + $this->assertEquals($expected, $parser->render('Simpler', [], false)); + $this->assertArrayNotHasKey('testString', $parser->getData()); - $expected = "

Hello World

\n"; + $parser->setData(['testString' => 'Hello World']); $this->assertEquals($expected, $parser->render('Simpler', [], true)); $this->assertArrayHasKey('testString', $parser->getData()); - $this->assertEquals($expected, $parser->render('Simpler', [], false)); - $this->assertArrayNotHasKey('testString', $parser->getData()); } public function testRenderStringSavingData() { - $parser = new Parser($this->config, $this->viewsDir, $this->loader); - $parser->setData(['testString' => 'Hello World']); - + $parser = new Parser($this->config, $this->viewsDir, $this->loader); $expected = '

Hello World

'; $pattern = '

{testString}

'; - $this->assertEquals($expected, $parser->renderString($pattern, [], true)); - $this->assertArrayHasKey('testString', $parser->getData()); + + $parser->setData(['testString' => 'Hello World']); $this->assertEquals($expected, $parser->renderString($pattern, [], false)); $this->assertArrayNotHasKey('testString', $parser->getData()); + //last set data is not saved + $parser->setData(['testString' => 'Hello World']); + $this->assertEquals($expected, $parser->renderString($pattern, [], true)); + $this->assertArrayHasKey('testString', $parser->getData()); } public function testRenderFindsOtherView() diff --git a/tests/system/View/ViewTest.php b/tests/system/View/ViewTest.php index 7827ee048cc5..c58c358488aa 100644 --- a/tests/system/View/ViewTest.php +++ b/tests/system/View/ViewTest.php @@ -230,14 +230,17 @@ public function testCachedRender() public function testRenderStringSavingData() { - $view = new View($this->config, $this->viewsDir, $this->loader); + $view = new View($this->config, $this->viewsDir, $this->loader); + $expected = '

Hello World

'; + //I think saveData is sava current data, is not clean already set data. $view->setVar('testString', 'Hello World'); - $expected = '

Hello World

'; - $this->assertEquals($expected, $view->renderString('

', [], true)); - $this->assertArrayHasKey('testString', $view->getData()); $this->assertEquals($expected, $view->renderString('

', [], false)); $this->assertArrayNotHasKey('testString', $view->getData()); + + $view->setVar('testString', 'Hello World'); + $this->assertEquals($expected, $view->renderString('

', [], true)); + $this->assertArrayHasKey('testString', $view->getData()); } //-------------------------------------------------------------------- @@ -343,4 +346,22 @@ public function testRenderLayoutNoContentSection() $this->assertStringContainsString($expected, $view->render('apples')); } + public function testRenderSaveDataCover() + { + $view = new View($this->config, $this->viewsDir, $this->loader); + $this->setPrivateProperty($view, 'saveData', true); + $view->setVar('testString', 'test'); + $view->render('simple', null, false); + $this->assertEquals(true, $this->getPrivateProperty($view, 'saveData')); + } + + public function testRenderSaveDataUseAflterSaveDataFalse() + { + $view = new View($this->config, $this->viewsDir, $this->loader); + $view->setVar('testString', 'test'); + $view->render('simple', null, true); + $view->render('simple', null, false); + $this->assertStringContainsString('

test

', $view->render('simple', null, false)); + } + } diff --git a/tests/system/View/Views/simple.php b/tests/system/View/Views/simple.php index 5bb1d81f9fc9..afd6c25fe226 100644 --- a/tests/system/View/Views/simple.php +++ b/tests/system/View/Views/simple.php @@ -1 +1 @@ -

+

\ No newline at end of file