Jump to content

Swap template file on hook


elabx
 Share

Recommended Posts

Hi, I've gone a different way to achieve kind of "auto swap" of template files through hooking TemplateFile, because I wanted to swap template files if a template file with some naming convention exists (eg. home.custom.php replaces home.php)  I'd like to ask for some opinions about the performance of this hook and if it makes a sensible approach because it feels a way too much to check for files on disk on every template render:

$wire->addHookBefore("TemplateFile::render", function($event){
    if($this->user->name == "admin"){
        $templateFile = $event->object;
        
        if($templateFile->page->template == "repeater_content"){
            $existingFiles = $this->files->find($this->config->paths->templates . "fields/content/");
            $customFileName = $this->config->paths->templates . "fields/content/{$templateFile->page->type}.custom.php";
            if(in_array($customFileName, $existingFiles)){
                $templateFile->setFilename($customFileName);
                $event->return = $templateFile;
         } elseif($templateFile->page->template == "home" ||
            $templateFile->page->template == "basic-content" ){
            $existingFiles = $this->files->find($this->config->paths->templates);
            $customFileName = $this->config->paths->templates . "{$templateFile->page->template}.custom.php";
            if(in_array($customFileName, $existingFiles)){
                $templateFile->setFilename($customFileName);
                $event->return = $templateFile;
            }
        }
       
        
    }
});
Link to comment
Share on other sites

27 minutes ago, elabx said:

it feels a way too much to check for files on disk on every template render:

Unless you will be storing the result of an initial check (e.g. in a session or cache), you will have to check for the existence of the file.

That aside, do you really need a hook for this? If I got you correctly, couldn't you do the check in the template file itself or that would mean repetitive code? If you did the check in init.php, you wouldn't need to have the same code check in different template files. I don't know if I am making sense, so on to an example. If you had this in init.php (assuming you are using delayed output).

$templateName = $page->template->name;
$customTemplateFile = $config->paths->templates . 'fields/content/' . $templateName . '.custom.php';
// if user is superuser (or user of your choice) AND we have a readable template file (e.g. home.custom.php)
// ... we include it
if($user->isSuperuser() && is_readable($customTemplateFile)) {
    include($customTemplateFile);
}
// else, include normal template file for this page
else {
    include("./basic-page.php"); 
}

 

Edited by kongondo
  • Like 2
Link to comment
Share on other sites

23 minutes ago, Robin S said:

To check if a given file exists, I think you would be better off using PHP's file_exists(). It's very fast and it caches so I doubt it would have any significant impact on performance.

 

I recently had to choose between the two and this swayed my preference:

https://stackoverflow.com/questions/6604726/file-exists-or-is-readable

I didn't find any other other pros/cons besides the potential 'false positives' mentioned in the SO link above. Btw, do you know if is_readable() caches too? Ta.
 
Edit: In answer to my own question. Yes, is_readable results are also cached.
Edited by kongondo
Link to comment
Share on other sites

2 hours ago, kongondo said:

Unless you will be storing the result of an initial check (e.g. in a session or cache), you will have to check for the existence of the file.

That aside, do you really need a hook for this? If I got you correctly, couldn't you do the check in the template file itself or that would mean repetitive code? If you did the check in init.php, you wouldn't need to have the same code check in different template files. I don't know if I am making sense, so on to an example. If you had this in init.php (assuming you are using delayed output).

One issue is I am not using delayed output but rendering normally through each template/file. Another issue is that I am using also repeater matrix heavily and to keep things organized I also decided to declare the field rendering in each "matrix type" file, so I also wanted to had "alt templates" for this repeater matrix fields rendering.

Link to comment
Share on other sites

On 15/03/2018 at 10:35 PM, elabx said:

One issue is I am not using delayed output but rendering normally through each template/file. Another issue is that I am using also repeater matrix heavily and to keep things organized I also decided to declare the field rendering in each "matrix type" file, so I also wanted to had "alt templates" for this repeater matrix fields rendering.

Hi @elabx,

Did you manage to sort this out?

Link to comment
Share on other sites

48 minutes ago, kongondo said:

Hi @elabx,

Did you manage to sort this out?

Yes!! It all worked perfectly, thanks!! Thought it was taken for granted lol sorry, this is the working code:

$wire->addHookBefore("TemplateFile::render", function($event){
        $templateFile = $event->object;
        
        if($templateFile->page->template == "repeater_content"){
            $customFileName = $this->config->paths->templates . "fields/content/{$templateFile->page->type}.custom.php";
            if(is_readable($customFileName)){
                $templateFile->setFilename($customFileName);
                $event->return = $templateFile;
            } 
            
        } elseif($templateFile->page->template == "home" ||
            $templateFile->page->template == "basic-content" ){
            $customFileName = $this->config->paths->templates . "{$templateFile->page->template}.custom.php";
            if(is_readable($customFileName)){
                $templateFile->setFilename($customFileName);
                $event->return = $templateFile;
            }
        }
});

I have some hardcoded if statements because I don't want to be checking for EVERY template, but this works nice for repeater matrix (which uses TemplateFile to render the matrix types) and any other template.  Also my first snippet was misleading because I didn't want to do a user check, so I removed that too. 

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...