addFolder is not what i want: how do i allow searching in more then 1 default directory? #59

Open
badpenguin opened this Issue Jan 22, 2015 · 17 comments

Projects

None yet

4 participants

@badpenguin

I've an array of 4 directories, is it possible to have them as default search paths instead of just 1 ?

@badpenguin

Ok i can rewrite my patch to be more general using its own propery and set/get funcs.

I need user's templates and package's templates to override the core framework's template (i.e. the default directory).
So, i need to provide the engine a default directory search order like this:
$dir=array(
'my app dir',
'pkg1 dir',
'pkg2 dir',
'framework dir'
);

So, if the framework provides loginform.tpl the package or the user can ovverride it just creating a modified file in their directory.

I undestand addFolder() is not what you want.

Can i add a new set/get directories to be used in addition to default directory?

That's the only missing point for me to use this template engine in replace of Twig.

@Giuseppe-Mazzapica

Hi @badpenguin,

I can understand you because in the days I wanted to use Plates as Twig replacement this was something I had to face too. (And this is the reason in Foil folders are handled like so).

However, at that time I used an approach that allowed me use multiple folders without to modify Plates.

First of all I created a class to hold and search folder paths, something like:

namespace BadPinguin;

class Folders
{
    private $folders = array();

    public function __construct(array $folders)
    {
        $ds = DIRECTORY_SEPARATOR;
        $this->folders = array_walk($folders, function($folder) {
            return rtrim(preg_replace('~[/\\]+~',$ds, $folder), $ds).$ds;
        });
    }

    public function find($file)
    {
        foreach($this->folders as $folder) {
            $path = $folder.ltrim($file,'\\/');
            if (is_file($path)) {
                return $path;
            }
        }

        return false;
    }
}

After that, I created a function that searches in folders using class above and returns a Plates template instance:

namespace BadPinguin;

function getTemplate(\League\Plates\Engine $engine, Folders $folders, $name)
{
    $found = $folders->find($name);
    if (!$found) {
        throw new \InvalidArgumentException(
            'A template named "' . $name . '" was not found in any folder.';
        );
    }
    $info = pathinfo($found);
    $engine->setDirectory($info['dirname']); // set engine folder "on the fly"

    return new \League\Plates\Template($engine, $info['filename']));
}

And finally, inside controllers:

$folders = new BadPinguin\Folders(array(
    '/path/to/files/one',
    '/path/to/files/two',
    '/path/to/files/three',
    '/path/to/files/four',
));
$engine = new League\Plates\Engine(null, 'tpl'); // no default folder
$template = BadPinguin\getTemplate($engine, $folders, 'home.tpl');

return $template->render($data);
@badpenguin

Thank you very much! I'm developing my own little framework and having a PHP native template system is essential to keep it small. I work a lot on small VPS and cannot afford to use the huges framework dinosaurs out there.

@badpenguin

Little problem... your solution will not work with fetch(), layout() and other function used within the template.

This will only work for the initial template.

This is not my case :/

@Giuseppe-Mazzapica

I know. Extend template class with your own where you override layout and fetch.

@badpenguin

Its easy for me to survive with my forked repository then :)

@Giuseppe-Mazzapica

Sure? Maintain a parallel forked repo is never easy. Thinks to all upgrades, new feautures and bug fixes may happen on main repo. You'll lost them or you have to integrate them one by one, checking that they do not break your fork, because of your edits. It's a way to go? Sure. But I'd stay away to say it's easy ;)

@badpenguin

Wow all this drama for exactly 6 lines of code :))

@Giuseppe-Mazzapica

That's exaclty the problem: maintain a forked repo just for 6 lines of code. You said you want to use the package for a custom framework. So I assume you want to keep it updated. Next time someone post a bugfix to Plates, I assume you want the bug fixed in your repo too.

How to do that? You have to watch Plates, look at any new commit and see if is the case to implement it in your repo too. And if so, be sure it does not overwrite your edits. It worth do that to just modify 6 lines of code?

Sure you can ignore any new Plates commit, and always keep that frozen version, or maybe develop your fork in parallel... but again, It worth do that to just modify 6 lines of code?

If that 6 lines of code are the only issue you have with Plates, how much time and effort you can save if you spent one hour in develop a solution that can work with Plates as is and then just composer update when needed?

Not to mention if you plan to share your framework. What you'll do, put your forked repo in Packagist? Or you'll ask your users to set repository settings in composer.json? And all that for just 6 lines of customization?

Please note that I'm not taking the role of Plates lawyer, in fact, I am someone who has done a lot of work to write a completely new package to replace Plates, but the issues I had with Plates were quite a lot...

@badpenguin

I'm waiting for him to know if he wants that extra features or not.

@reinink
Member
reinink commented Jan 25, 2015

I'm open to adding multiple folder support to Plates. Currently enjoying time with family, but will follow up with more details tomorrow.

@Giuseppe-Mazzapica

My honest opinion is that it can't be done with full backward compatibility.

Currently is possible to fallback a template to "main" folder if not found in required one.

When enabled, if a folder template is missing, Plates will automatically fallback and look for a template with the same name in the default folder.When enabled, if a folder template is missing, Plates will automatically fallback and look for a template with the same name in the default folder.

(quote from here)

So is possible that people that have their templates folder structure built upon current Plates version can see a template loaded in place of another because a template that should fallback to main folder, will fallback to another folder.

I feel it's a great addon for Plates, but I don't think is possible before version 4.

@badpenguin

Thanks @reinink ! Wich is your preferred public method name for this? What about i call it SetAdditionalFolders or SetExtraFolders ?

@reinink
Member
reinink commented Jan 26, 2015

Leave this with me to implement, I want to think through this carefully as to prevent any backwards compatibility breaks as @Giuseppe-Mazzapica is suggesting could happen.

Honestly, I'm seeing this as simple as having the option to pass an array of default directories, instead of just a string. This also prevents any breaks, since existing could will continue working exactly as it is.

// Set default directories when creating engine
$templates = new League\Plates\Engine([
    '/path/to/templates',
    '/path/to/more/templates',
    '/path/to/other/templates',
]);

// Set default directories with setter method
$templates->setDirectory([
    '/path/to/templates',
    '/path/to/more/templates',
    '/path/to/other/templates',
]);

This keeps this functionality totally separate from the existing folders functionality. In fact, the folder fallbacks will still work if multiple default directories are set, it will simply look in more than one directory at that point.

@badpenguin Does that sound like it would solve your issue?

@badpenguin

Yes, do you want me to code the patch this way?

@reinink
Member
reinink commented Jan 26, 2015

If you want to give it a try, by all means! You'll have to tweak Engine.php, Template/Name.php and Template/Directory, hopefully that's it.

@ragboyjr
Contributor

I think this falls under the same feature/system as #130 and #79, but will keep it around to try and get a system to work for all 3 types.

@funivan funivan referenced this issue Dec 29, 2016
Open

Name class #130

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment