Skip to content

Commit

Permalink
Change logic of template file searching
Browse files Browse the repository at this point in the history
  • Loading branch information
vjik committed Jun 25, 2024
1 parent 793fc9e commit 32e6b2f
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 113 deletions.
20 changes: 0 additions & 20 deletions src/ViewInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -269,26 +269,6 @@ public function getPlaceholderSignature(): string;
*/
public function render(string $view, array $parameters = []): string;

/**
* Renders a view file.
*
* If the theme was set {@see setTheme()}, it will try to render the themed version of the view file
* as long as it is available.
*
* If the renderer was set {@see withRenderers()}, the method will use it to render the view file. Otherwise,
* it will simply include the view file as a normal PHP file, capture its output and return it as a string.
*
* @param string $viewFile The full absolute path of the view file.
* @param array $parameters The parameters (name-value pairs) that will be extracted and made available in the view
* file.
*
* @throws Throwable
* @throws ViewNotFoundException If the view file does not exist
*
* @return string The rendering result.
*/
public function renderFile(string $viewFile, array $parameters = []): string;

/**
* Returns the localized version of a specified file.
*
Expand Down
78 changes: 42 additions & 36 deletions src/ViewTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -440,29 +440,6 @@ public function render(string $view, array $parameters = []): string
{
$viewFile = $this->findTemplateFile($view);

return $this->renderFile($viewFile, $parameters);
}

/**
* Renders a view file.
*
* If the theme was set {@see setTheme()}, it will try to render the themed version of the view file
* as long as it's available.
*
* If the renderer was set {@see withRenderers()}, the method will use it to render the view file. Otherwise,
* it will simply include the view file as a normal PHP file, capture its output and return it as a string.
*
* @param string $viewFile The full absolute path of the view file.
* @param array $parameters The parameters (name-value pairs) that will be extracted and made available in the view
* file.
*
* @throws Throwable
* @throws ViewNotFoundException If the view file doesn't exist
*
* @return string The rendering result.
*/
public function renderFile(string $viewFile, array $parameters = []): string
{
$parameters = array_merge($this->state->getParameters(), $parameters);

// TODO: these two match now
Expand Down Expand Up @@ -646,20 +623,10 @@ private function setPlaceholderSalt(string $salt): void
*/
private function findTemplateFile(string $view): string
{
if ($view !== '' && $view[0] === '/') {
// path relative to basePath e.g. "/layouts/main"
$file = $this->getBasePath() . '/' . ltrim($view, '/');
} elseif (($currentViewFile = $this->getRequestedViewFile()) !== null) {
// path relative to currently rendered view
$file = dirname($currentViewFile) . '/' . $view;
} elseif ($this->context instanceof ViewContextInterface) {
// path provided by context
$file = $this->context->getViewPath() . '/' . $view;
} else {
throw new RuntimeException("Unable to resolve view file for view \"$view\": no active view context.");
}
$file = $this->findViewFilePath($view);
$hasExtension = pathinfo($file, PATHINFO_EXTENSION) !== '';

if (pathinfo($file, PATHINFO_EXTENSION) !== '' && is_file($file)) {
if ($hasExtension && is_file($file)) {
return $file;
}

Expand All @@ -670,9 +637,40 @@ private function findTemplateFile(string $view): string
}
}

if ($hasExtension) {
return $file;
}

return $file . '.' . $this->fallbackExtensions[0];
}

private function findViewFilePath(string $view): string
{
if (str_starts_with($view, './')) {
$currentViewFile = $this->getRequestedViewFile();
if ($currentViewFile === null) {
throw new LogicException('...');

Check warning on line 652 in src/ViewTrait.php

View check run for this annotation

Codecov / codecov/patch

src/ViewTrait.php#L652

Added line #L652 was not covered by tests
}
return dirname($currentViewFile) . substr($view, 1);
}

if (str_starts_with($view, '//')) {
return $this->getBasePath() . substr($view, 1);
}

if ($this->isWindows()) {
if (str_contains($view, ':')) {
return $view;

Check warning on line 663 in src/ViewTrait.php

View check run for this annotation

Codecov / codecov/patch

src/ViewTrait.php#L662-L663

Added lines #L662 - L663 were not covered by tests
}
} else {
if (str_starts_with($view, '/')) {
return $view;
}
}

return ($this->context?->getViewPath() ?? $this->getBasePath()) . '/' . $view;
}

/**
* @return string|null The requested view currently being rendered. `null` if no view file is being rendered.
*/
Expand All @@ -681,4 +679,12 @@ private function getRequestedViewFile(): ?string
/** @psalm-suppress InvalidArrayOffset */
return empty($this->viewFiles) ? null : end($this->viewFiles)['requested'];
}

/**
* Returns whether the current environment is Windows.
*/
private function isWindows(): bool
{
return DIRECTORY_SEPARATOR === '\\';
}
}
4 changes: 1 addition & 3 deletions src/WebView.php
Original file line number Diff line number Diff line change
Expand Up @@ -188,15 +188,13 @@ public function endPage(bool $ajaxMode = false): void
*/
public function renderAjax(string $view, array $parameters = []): string
{
$viewFile = $this->findTemplateFile($view);

ob_start();
ob_implicit_flush(false);

$this->beginPage();
$this->head();
$this->beginBody();
echo $this->renderFile($viewFile, $parameters);
echo $this->render($view, $parameters);
$this->endBody();
$this->endPage(true);

Expand Down
47 changes: 20 additions & 27 deletions tests/ViewTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ public function testExceptionOnRenderFile(): void
$obInitialLevel = ob_get_level();

try {
$view->renderFile($exceptionViewFile);
$view->render($exceptionViewFile);
} catch (Exception) {
// shutdown exception
}
$view->renderFile($normalViewFile);
$view->render($normalViewFile);

$this->assertEquals($obInitialLevel, ob_get_level());
}
Expand All @@ -90,20 +90,13 @@ public function testExceptionWhenRenderIfFileNotExists(): void
$view = $this->createViewWithBasePath($this->tempDirectory);

$this->expectException(ViewNotFoundException::class);
$this->expectExceptionMessage('The view file "not-exist.php" does not exist.');

$view->renderFile('not-exist.php');
}

public function testExceptionWhenRenderIfNoActiveViewContext(): void
{
$view = $this->createViewWithBasePath($this->tempDirectory);
file_put_contents("$this->tempDirectory/file.php", 'Test');

$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('Unable to resolve view file for view "file.php": no active view context.');
$this->expectExceptionMessage(
'The view file "' .
__DIR__ . '/public/tmp/View/not-exist.php' .
'" does not exist.'
);

$this->assertSame('Test', $view->render('file.php'));
$view->render('not-exist.php');
}

public function testRelativePathInView(): void
Expand All @@ -115,8 +108,8 @@ public function testRelativePathInView(): void
file_put_contents(
$baseView,
<<<'PHP'
<?= $this->render("sub") ?>
PHP
<?= $this->render('./sub') ?>
PHP
);

$subView = "{$this->tempDirectory}/sub.php";
Expand All @@ -132,7 +125,7 @@ public function testRelativePathInView(): void
$this->assertSame('php', $view->getDefaultExtension());
$this->assertSame(null, $view->getViewFile());
$this->assertSame($theme, $view->getTheme());
$this->assertSame($subViewContent, $view->render('/base'));
$this->assertSame($subViewContent, $view->render('base'));
$this->assertSame($subViewContent, $view->render('//base'));
}

Expand All @@ -145,8 +138,8 @@ public function testRelativePathInViewWithContext(): void
file_put_contents(
$baseView,
<<<'PHP'
<?= $this->render("sub/sub") ?>
PHP
<?= $this->render('./sub/sub') ?>
PHP
);

$subViewPath = $baseViewPath . DIRECTORY_SEPARATOR . 'sub';
Expand Down Expand Up @@ -177,7 +170,7 @@ public function testFlushViewFilesOnChangeContext(): void
{
$view = TestHelper::createView();

$this->assertSame('42', $view->render('/change-context'));
$this->assertSame('42', $view->render('change-context'));
}

public function renderFilesWithExtensionProvider(): array
Expand Down Expand Up @@ -284,7 +277,7 @@ public function testRenderSetLocale(): void

$this->assertSameIgnoringSlash(
'test es render',
$view->render('/file'),
$view->render('file'),
);
}

Expand All @@ -299,9 +292,9 @@ public function testRenderWithLocale(): void

$this->assertSameIgnoringSlash(
'test es render',
$view->withLocale('es')->render('/file'),
$view->withLocale('es')->render('file'),
);
$this->assertSame('test en render', $view->render('/file'));
$this->assertSame('test en render', $view->render('file'));
}

public function testSubRenderWithLocale(): void
Expand All @@ -318,9 +311,9 @@ public function testSubRenderWithLocale(): void

$this->assertSameIgnoringSlash(
'test es sub render',
$view->withLocale('es')->render('/file'),
$view->withLocale('es')->render('file'),
);
$this->assertSame('test en sub render', $view->render('/file'));
$this->assertSame('test en sub render', $view->render('file'));
}

public function testLocalizeWithChangedLocale(): void
Expand Down Expand Up @@ -529,7 +522,7 @@ public function testClear(): void
$view->setParameter('age', 42);

try {
$view->renderFile(__DIR__ . '/public/view/error.php');
$view->render(__DIR__ . '/public/view/error.php');
} catch (Exception) {
}

Expand Down
Loading

0 comments on commit 32e6b2f

Please sign in to comment.