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

New use_only_compiled option #835

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open

Conversation

gtozzi
Copy link

@gtozzi gtozzi commented Dec 15, 2022

If set to TRUE, Smarty will use only compiled templates, also
ignoring the (in)existence of base templates. Compiled filenames
will be constant and relative to the template basename.
Useful to use pre-compiled templates and distribute them already
compiled on production websites. Overrides and disables
$merge_compiled_includes

@wisskid
Copy link
Contributor

wisskid commented Feb 1, 2023

How does this relate to the compile_check setting?

@gtozzi
Copy link
Author

gtozzi commented Feb 2, 2023

How does this relate to the compile_check setting?

compile_check requires source template files to be present, use_only_compiled allows the dev to remove them completely: they do not need to be deployed in production.

compile_check compiles the template only once at first run in production, then stops checking about updates. use_only_compiled is meant to compile templates manually in a script before deployment (i.e. in you build CI) and deploy compiled-only templates.

@wisskid
Copy link
Contributor

wisskid commented Feb 2, 2023

compile_check requires source template files to be present

You are right. Even with $compile_check enabled, Smarty still checks if source files exist, although it won't compare the timestamps. I stumbled across this earlier this week and I actually think it is either a bug or feature that could be improved.

The way I see it: if you are going to check for the existence of a file, you might as well check its timestamp. Or, if you want to optimize for performance and want don't check the timestamp, then don't check for the existence of the file either.

So the way I see it, with $compile_check enabled, Smarty should not check for the existence of the source templates. I wrote the the following unit test to test compile_check behavior:

<?php
/**
 * Smarty PHPunit tests for compile check
 */
class CompileCheckTest extends PHPUnit_Smarty
{
    public $methodName = null;
    public function setUp(): void
    {
        $this->setUpSmarty(__DIR__);
        $this->smarty->addTemplateDir('./templates_tmp');
        $this->cleanDirs();
    }

    /**
     * generate templates
     */
    protected function makeFiles()
    {
        file_put_contents('./templates_tmp/t1.tpl', 'TPL1');
        file_put_contents('./templates_tmp/t2.tpl', 'TPL2');
        file_put_contents('./templates_tmp/base.tpl', '{include file="t1.tpl"}{include file="t2.tpl"}');
    }
    /**
     * remove generated templates
     */
    protected function removeFiles()
    {
        unlink('./templates_tmp/t1.tpl');
        unlink('./templates_tmp/t2.tpl');
        unlink('./templates_tmp/base.tpl');
    }

    /**
     * reset, but leave the files alone
     * @return void
     */
    private function softResetSmarty() {
        $this->smarty = new Smarty();
        $this->smarty->addTemplateDir('./templates_tmp');
    }

    /**
     * @group slow
     */
    public function testCompileCheckOn0()
    {
        $this->makeFiles();
        $this->assertEquals('TPL1TPL2', $this->smarty->fetch('base.tpl'));

        $this->softResetSmarty();
        $this->smarty->setCompileCheck(Smarty::COMPILECHECK_ON);

        $this->assertEquals('TPL1TPL2', $this->smarty->fetch('base.tpl'));
    }

    /**
     * @group slow
     */
    public function testCompileCheckOn1()
    {
        $this->makeFiles();
        $this->assertEquals('TPL1TPL2', $this->smarty->fetch('base.tpl'));

        $this->softResetSmarty();
        $this->smarty->setCompileCheck(Smarty::COMPILECHECK_ON);

        unlink('./templates_tmp/base.tpl');
        sleep(1);

        $this->expectException(Exception::class);
        $this->smarty->fetch('base.tpl');
    }

    /**
     * @group slow
     */
    public function testCompileCheckOn2()
    {
        $this->makeFiles();
        $this->assertEquals('TPL1TPL2', $this->smarty->fetch('base.tpl'));

        $this->softResetSmarty();
        $this->smarty->setCompileCheck(Smarty::COMPILECHECK_ON);

        sleep(1);
        file_put_contents('./templates_tmp/base.tpl', 'hello');

        $this->assertEquals('hello', $this->smarty->fetch('base.tpl'));
    }

    /**
     * @group slow
     */
    public function testCompileCheckOff0()
    {
        $this->makeFiles();
        $this->assertEquals('TPL1TPL2', $this->smarty->fetch('base.tpl'));

        $this->softResetSmarty();
        $this->smarty->setCompileCheck(Smarty::COMPILECHECK_OFF);

        $this->assertEquals('TPL1TPL2', $this->smarty->fetch('base.tpl'));
    }

    /**
     * @group slow
     */
    public function testCompileCheckOff1()
    {
        $this->makeFiles();
        $this->assertEquals('TPL1TPL2', $this->smarty->fetch('base.tpl'));

        $this->softResetSmarty();
        $this->smarty->setCompileCheck(Smarty::COMPILECHECK_OFF);

        unlink('./templates_tmp/base.tpl');
        sleep(1);

        $this->assertEquals('TPL1TPL2', $this->smarty->fetch('base.tpl'));
    }

    /**
     * @group slow
     */
    public function testCompileCheckOff2()
    {
        $this->makeFiles();
        $this->assertEquals('TPL1TPL2', $this->smarty->fetch('base.tpl'));

        $this->softResetSmarty();
        $this->smarty->setCompileCheck(Smarty::COMPILECHECK_OFF);

        sleep(1);
        file_put_contents('./templates_tmp/base.tpl', 'hello');

        $this->assertEquals('TPL1TPL2', $this->smarty->fetch('base.tpl'));
    }

}

You'll notice that testCompileCheckOff1 fails. If we fix this, we won't need an extra setting.

Your idea of making the compiled filenames independent of the actual source file names / file path is interesting as well. I am working on that in v5.

@gtozzi
Copy link
Author

gtozzi commented Feb 2, 2023

The way I see it: if you are going to check for the existence of a file, you might as well check its timestamp. Or, if you want to optimize for performance and want don't check the timestamp, then don't check for the existence of the file either.

So the way I see it, with $compile_check enabled, Smarty should not check for the existence of the source templates. I wrote the the following unit test to test compile_check behavior:

You'll notice that testCompileCheckOff1 fails. If we fix this, we won't need an extra setting.

Your idea of making the compiled filenames independent of the actual source file names / file path is interesting as well. I am working on that in v5.

We tried this approach in first place but looks like it was too invasive because compiled file names include the hash of the source file.

It looked like a too invasive mod to change the file naming scheme for the whole smarty, so we opted for a less invasive new flag. When enabled, compiled file names no longer include the hash in the name, making possible to have a two-way relation between the source and its compiled result.

@wisskid
Copy link
Contributor

wisskid commented Feb 5, 2023

Could you try composer require smarty/smarty:dev-smarty5 and let me know how that works for you?

<?php

use \Smarty\Smarty;
$smarty = new Smarty();
$smarty->setCompileCheck(false);
//...

should do the trick

@gtozzi
Copy link
Author

gtozzi commented Feb 6, 2023

Could you try composer require smarty/smarty:dev-smarty5 and let me know how that works for you?

I'm not using composer, can i checkout the "smarty5" branch?

@wisskid
Copy link
Contributor

wisskid commented Feb 6, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants