Jump to content

[SOLVED] Template prepend file runs twice when in a Page::render hook


Ivan Gretsky
 Share

Recommended Posts

Good day!

I am trying to do a frontend check in a Page::render hook and return completely different markup on condition:
 

<?php 

// This is site/ready.php

wire()->addHookAfter('Page::render', function (HookEvent $event) {

	$page = $event->object;

    ... //Some condition here
		
	$config = wire("config");
	$t = new ProcessWire\TemplateFile($config->paths->templates . "test.php");
	$t->setArray(array(
			'page' => wire()->pages->get("1234"),
		)
	);
	$t->setPrependFilename($config->paths->templates . '_init.php');
	$t->setAppendFilename($config->paths->templates . '_main.php');
  	$out = $t->render();
	$event->return = $out;
}

But I get this error: Cannot redeclare SomeFubction() (previously declared in ...\site\templates\_func.php:123)

_func.php is included with include_once in _init.php. But somehow _init.php happens to run twice.

Can't get my head around this one. Please help!

Link to comment
Share on other sites

Maybe this does not work (I'm on mobile), but have you tried to set a var in _init.php like this:

if(isset($alreadyExecuted) && $alreadyExecuted) return;
$alreadyExecuted = true; // set it in the first run.

EDIT: Or bind the include of _functions.php on the condition of the var.

  • Like 1
Link to comment
Share on other sites

Changing the condition to use a super global variable indeed helped me to prevent _init.php from running once again. But in this case the TemplateFile object doesn't get any variables from _init.php which it need to render correctly.

I thought, that I need to move all the code to another hook before the Page:render. So I made PageRender::beforeRenderPage hookable and moved the code there. But that still didn't work. I am definitely lost here((

Link to comment
Share on other sites

Let all your code you need to run twice in the root of _init.php.

Wrap all other, like the include_once of the _functions.php into a superglobal var condition, or, if the include of the _functions.php is the only issue you have, you can wrap this in a condition with function_exists:

if(!function_exists("aFunctionNameThatExistsInFunctionsPhp")) include(__DIR__ . "/_functions.php");

 

Link to comment
Share on other sites

@Ivan Gretsky I am not sure that this will help, but for one project I been using these hooks for a similar task. Maybe it will give you some ideas.

public function init()
	{
		$this->addHookBefore('PageRender::renderPage', $this, 'hookBeforePageRenderTemplater');
		$this->addHookAfter('TemplateFile::render', $this, 'hookAfterTemplateRender');
		$this->wire('config')->ignoreTemplateFileRegex = "/(\.before\.)|(\.after\.)|(\.{$this->template_files_suffix}\.)|(^_)/";

	}


public function hookBeforePageRenderTemplater($e)
	{
		$event = $e->arguments(0);
		$page  = $event->object;
		if ($page->template->name == 'admin') return;
		$options                 = $event->arguments(0);
		$template                = $page->template;
		$options['prependFiles'] = [
			"{$template}.before.php",
			"_init.php",
		];
		$options['appendFiles']  = [
			"{$template}.after.php",
			"_after.php",
		];

		$event->setArgument(0, $options);
	}


public function hookAfterTemplateRender($event)
	{
		if ($this->wire('page') == null) return;
		if (strpos($event->object->filename, 'TracyDebugger') !== false) return;
		if (str_replace('site/assets/cache/FileCompiler/', '', $event->object->filename) !== $this->wire('page')->template->filename) return;
		if (strpos($_SERVER['REQUEST_URI'], $this->wire('config')->urls->admin) === 0 || $this->wire('page')->template->name == 'admin') return;
		$template = $event->object;
		$options  = $template->options;


		if (is_array($options) && array_key_exists('pageStack', $options)) {
			$view   = $this->wire($this->api_view_var);
			$layout = $this->wire($this->api_layout_var);
			$page   = $this->wire('page');

			$page_template = $page->template;

			if ($template->halt) {
				return;
			};

			if (empty($options['pageStack']) && $page_template->templater_url_segments) $this->wire('session')->redirect($page->url);
			$template_name = ($page->template->altFilename) ? $page->template->altFilename : $page->template->name;
			$view_file     = $this->getViewFilePath($template_name);

			if (is_file($view_file)) {
				$view->setFilename($view_file);
			} else {
				throw new WireException("View file for this page template ({$view_file}) does not exist");
			}
			$event->return = $event->return . $layout->render();
		}
	}

 

  • Like 2
Link to comment
Share on other sites

  • 2 weeks later...

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...