Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow multiple "baseDir" (array) to search for templates. #306

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 49 additions & 16 deletions src/Mustache/Loader/FilesystemLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,23 @@ class Mustache_Loader_FilesystemLoader implements Mustache_Loader
*
* @throws Mustache_Exception_RuntimeException if $baseDir does not exist
*
* @param string $baseDir Base directory containing Mustache template files
* @param array $options Array of Loader options (default: array())
* @param string|array $baseDir Base directory containing Mustache template files
* @param array $options Array of Loader options (default: array())
*/
public function __construct($baseDir, array $options = array())
{
$this->baseDir = $baseDir;

if (strpos($this->baseDir, '://') === false) {
$this->baseDir = realpath($this->baseDir);
if (is_array($baseDir)) {
$this->baseDir = array();
foreach ($baseDir as $dir) {
$this->baseDir[] = $this->sanitizeDir($dir);
}
} else {
$this->baseDir = array($this->sanitizeDir($baseDir));
}

if ($this->shouldCheckPath() && !is_dir($this->baseDir)) {
throw new Mustache_Exception_RuntimeException(sprintf('FilesystemLoader baseDir must be a directory: %s', $baseDir));

if (empty($this->baseDir)) {
throw new Mustache_Exception_RuntimeException('FilesystemLoader baseDir must have at least one directory.');
}

if (array_key_exists('extension', $options)) {
Expand Down Expand Up @@ -96,40 +100,69 @@ public function load($name)
*/
protected function loadFile($name)
{
$fileName = $this->getFileName($name);
foreach ($this->baseDir as $dir) {
$fileName = $this->getFileName($name, $dir);

if ($this->shouldCheckPath() && !file_exists($fileName)) {
throw new Mustache_Exception_UnknownTemplateException($name);
if (!$this->shouldCheckPath($dir) || file_exists($fileName)) {
return file_get_contents($fileName);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a little bit weird, because if any "directory" in $this->baseDir uses a stream loader, it will never even check any directory after it in the list.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if there's a good way to fix that, it's just an observation :)

}
}

return file_get_contents($fileName);
// No template found
throw new Mustache_Exception_UnknownTemplateException($name);
}

/**
* Helper function for getting a Mustache template file name.
*
* @param string $name
* @param string $dir
*
* @return string Template file name
*/
protected function getFileName($name)
protected function getFileName($name, $dir)
{
$fileName = $this->baseDir . '/' . $name;
$fileName = $dir . '/' . $name;
if (substr($fileName, 0 - strlen($this->extension)) !== $this->extension) {
$fileName .= $this->extension;
}

return $fileName;
}

/**
* Sanitize a directory name.
*
* @throws Mustache_Exception_RuntimeException If a directory is not valid
*
* @param string $dir
*
* @return string The sanitized / real path of the directory
*/
protected function sanitizeDir($dir)
{

if (strpos($dir, '://') === false) {
$dir = realpath($dir);
}

if ($this->shouldCheckPath($dir) && !is_dir($dir)) {
throw new Mustache_Exception_RuntimeException(sprintf('FilesystemLoader directory must be a directory: %s', $dir));
}

return $dir;
}

/**
* Only check if baseDir is a directory and requested templates are files if
* baseDir is using the filesystem stream wrapper.
*
* @param string $dir
*
* @return bool Whether to check `is_dir` and `file_exists`
*/
protected function shouldCheckPath()
protected function shouldCheckPath($dir)
{
return strpos($this->baseDir, '://') === false || strpos($this->baseDir, 'file://') === 0;
return strpos($dir, '://') === false || strpos($dir, 'file://') === 0;
}
}
12 changes: 12 additions & 0 deletions test/Mustache/Test/Loader/FilesystemLoaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ public function testTrailingSlashes()
$this->assertEquals('one contents', $loader->load('one'));
}

public function testConstructorWithMultipleDirs()
{
$baseDir = array(
realpath(dirname(__FILE__) . '/../../../fixtures/templates'),
realpath(dirname(__FILE__) . '/../../../fixtures/more_templates'),
);
$loader = new Mustache_Loader_FilesystemLoader($baseDir, array('extension' => '.ms'));
$this->assertEquals('alpha contents', $loader->load('alpha'));
$this->assertEquals('beta contents', $loader->load('beta.ms'));
$this->assertEquals('gamma contents', $loader->load('gamma.ms'));
}

public function testConstructorWithProtocol()
{
$baseDir = realpath(dirname(__FILE__) . '/../../../fixtures/templates');
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/more_templates/gamma.ms
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
gamma contents
1 change: 1 addition & 0 deletions test/fixtures/more_templates/three.ms
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
three contents