From 131daf401e63ee35bebd65fea118069bb138a4b1 Mon Sep 17 00:00:00 2001 From: Andrey Pyzhikov <5071@mail.ru> Date: Thu, 29 Apr 2021 18:46:21 +0800 Subject: [PATCH] Fix: Nested sections rendering --- system/View/View.php | 30 +++++++++++++--------- tests/system/View/ViewTest.php | 15 ++++++++++- tests/system/View/Views/nested_section.php | 14 ++++++++++ 3 files changed, 46 insertions(+), 13 deletions(-) create mode 100644 tests/system/View/Views/nested_section.php diff --git a/system/View/View.php b/system/View/View.php index 935729393626..9bc3367d2c42 100644 --- a/system/View/View.php +++ b/system/View/View.php @@ -120,9 +120,9 @@ class View implements RendererInterface * The name of the current section being rendered, * if any. * - * @var string|null + * @var array */ - protected $currentSection; + protected $sectionStack = []; /** * Constructor @@ -227,7 +227,7 @@ public function render(string $view, array $options = null, bool $saveData = nul // When using layouts, the data has already been stored // in $this->sections, and no other valid output // is allowed in $output so we'll overwrite it. - if (! is_null($this->layout) && empty($this->currentSection)) + if (! is_null($this->layout) && $this->sectionStack === []) { $layoutView = $this->layout; $this->layout = null; @@ -402,35 +402,41 @@ public function extend(string $layout) /** * Starts holds content for a section within the layout. * - * @param string $name + * @param string $name Section name + * + * @return void */ - public function section(string $name) + public function section(string $name): void { - $this->currentSection = $name; + $this->sectionStack[] = $name; ob_start(); } /** + * Captures the last section + * + * @return void * @throws RuntimeException */ - public function endSection() + public function endSection(): void { $contents = ob_get_clean(); - if (empty($this->currentSection)) + if ($this->sectionStack === []) { throw new RuntimeException('View themes, no current section.'); } + $section = array_pop($this->sectionStack); + // Ensure an array exists so we can store multiple entries for this. - if (! array_key_exists($this->currentSection, $this->sections)) + if (! array_key_exists($section, $this->sections)) { - $this->sections[$this->currentSection] = []; + $this->sections[$section] = []; } - $this->sections[$this->currentSection][] = $contents; - $this->currentSection = null; + $this->sections[$section][] = $contents; } /** diff --git a/tests/system/View/ViewTest.php b/tests/system/View/ViewTest.php index 8dd1d4431a38..7d2cf84becbb 100644 --- a/tests/system/View/ViewTest.php +++ b/tests/system/View/ViewTest.php @@ -367,7 +367,7 @@ public function testRenderSaveDataCover() $this->assertEquals(true, $this->getPrivateProperty($view, 'saveData')); } - public function testRenderSaveDataUseAflterSaveDataFalse() + public function testRenderSaveDataUseAfterSaveDataFalse() { $view = new View($this->config, $this->viewsDir, $this->loader); $view->setVar('testString', 'test'); @@ -387,4 +387,17 @@ public function testCachedAutoDiscoverAndRender() // this second renderings should go thru the cache $this->assertStringContainsString($expected, $view->render('Nested/simple', ['cache' => 10])); } + + public function testRenderNestedSections() + { + $view = new View($this->config, $this->viewsDir, $this->loader); + + $view->setVar('testString', 'Hello World'); + + $content = $view->render('nested_section'); + + $this->assertStringContainsString('

First

', $content); + $this->assertStringContainsString('

Second

', $content); + $this->assertStringContainsString('

Third

', $content); + } } diff --git a/tests/system/View/Views/nested_section.php b/tests/system/View/Views/nested_section.php new file mode 100644 index 000000000000..a89e6234ec5c --- /dev/null +++ b/tests/system/View/Views/nested_section.php @@ -0,0 +1,14 @@ +extend('layout'); ?> + +section('content'); ?> +

Second

+ + section('content'); ?> +

First

+ endSection(); ?> + +endSection(); ?> + +section('content'); ?> +

Third

+endSection(); ?>