php-debugbar icon indicating copy to clipboard operation
php-debugbar copied to clipboard

TraceableTwigEnvironment breaks Twig is subtle ways

Open mnpenner opened this issue 9 years ago • 3 comments

I tried hot-swapping my Twig_Environment for a TraceableTwigEnvironment like so,

$twig = new TraceableTwigEnvironment($twig, $debugBar->getCollector('time'));
$debugBar->addCollector(new TwigCollector($twig));

Turns out it affects how {% includes %} and {% embeds %} and {% imports %} are processed. As an example,

{% embed 'monitor/type/_monitor_base_dialog.twig' %}
    {% import 'macros/bluebox.twig' as bb %} {# <--- this import wasn't needed here before because bluebox is already imported in the parent tempalte #}

    {% block inputs %}
        {{ bb.text({name:'weight[baseline_weight]',label:'Baseline Weight (' ~ unit ~ ')',value:formData.monitor_weight_base,required:true}) }}
        {{ bb.text({name:'weight[measure_weight]',label:'Measurement Taken (' ~ unit ~ ')',value:formData.monitor_weight_measure,required:true}) }}
        {{ bb.hidden({name:'weight[id]',value:id,label:' '}) }}
        {{ parent() }}
    {% endblock %}
{% endembed %}

Also, it doesn't seem to be tracking all the templates. e.g. when one layout extends another, and macro files.

Also, I think it calls into some "cache" functions which are now deprecated by Twig. I think this caused it to throw an exception in production which I haven't been able to produce in our dev environment.

I'm going to remove it for now as it's not really critical, but it would make it easier for us to find which template a page is using :smile:

mnpenner avatar Jan 29 '16 17:01 mnpenner

+1 on the cache break here. It appears TraceableTwigEnvironment calls Twig_Environment::writeCacheFile(), which doesn't has the $cache property set. Calling $this->twig->writeCacheFile() should fix this (for now).

Also, maybe TraceableTwigEnvironment should not extend Twig_Environment?

    public function loadTemplate($name, $index = null)
    {
        $cls = $this->twig->getTemplateClass($name, $index);

        if (isset($this->twig->loadedTemplates[$cls])) {
            return $this->twig->loadedTemplates[$cls];
        }

        if (!class_exists($cls, false)) {
            if (false === $cache = $this->getCacheFilename($name)) {
                eval('?>'.$this->compileSource($this->getLoader()->getSource($name), $name));
            } else {
                if (!is_file($cache) || ($this->isAutoReload() && !$this->isTemplateFresh($name, filemtime($cache)))) {
                    $this->writeCacheFile($cache, $this->compileSource($this->getLoader()->getSource($name), $name));
                }

                require_once $cache;
            }
        }

        if (!$this->twig->runtimeInitialized) {
            $this->initRuntime();
        }

        return $this->twig->loadedTemplates[$cls] = new TraceableTwigTemplate($this, new $cls($this));
    }

ivarb avatar Mar 04 '16 13:03 ivarb

+1 on the Twig cache problem.

itstudiocz avatar Jun 08 '16 10:06 itstudiocz

Same problem here. Is there any workaround or is Twig collector unusable at this point?

acasar avatar Jul 06 '16 21:07 acasar