Convert include code into a method of Template class

This commit is contained in:
Kijin Sung 2023-10-18 00:01:11 +09:00
parent 012dbb9ab7
commit e044e11c5f
4 changed files with 77 additions and 114 deletions

View file

@ -457,6 +457,63 @@ class Template
* =================== HELPER FUNCTIONS FOR TEMPLATE v2 ===================
*/
/**
* Include another template from v2 @include directive.
*
* Blade has several variations of the @include directive, and we need
* access to the actual PHP args in order to process them accurately.
* So we do this in the Template class, not in the converter.
*
* @param ...$args
* @return string
*/
protected function _v2_include(...$args): string
{
// Set some basic information.
$directive = $args[0];
$extension = $this->extension === 'blade.php' ? 'blade.php' : null;
$isConditional = in_array($directive, ['includeWhen', 'includeUnless']);
$basedir = $this->relative_dirname;
$cond = $isConditional ? $args[1] : null;
$path = $isConditional ? $args[2] : $args[1];
$vars = $isConditional ? ($args[3] ?? null) : ($args[2] ?? null);
// Handle paths relative to the Rhymix installation directory.
if (preg_match('#^\^/?(\w.+)$#s', $path, $match))
{
$basedir = str_contains($match[1], '/') ? dirname($match[1]) : \RX_BASEDIR;
$path = basename($match[1]);
}
// If the conditions are not met, return.
if ($isConditional && $directive === 'includeWhen' && !$cond)
{
return '';
}
if ($isConditional && $directive === 'includeUnless' && $cond)
{
return '';
}
// Create a new instance of TemplateHandler.
$template = new self($basedir, $path, $extension);
// If the directive is @includeIf and the template file does not exist, return.
if ($directive === 'includeIf' && !$template->exists())
{
return '';
}
// Set variables.
if ($vars !== null)
{
$template->setVars($vars);
}
// Compile and return.
return $template->compile();
}
/**
* Load a resource from v2 @load directive.
*

View file

@ -374,58 +374,9 @@ class TemplateParser_v2
$parentheses = self::_getRegexpForParentheses(2);
$regexp = '#(?<!@)@(include(?:If|When|Unless)?)\x20?(' . $parentheses . ')#';
$content = preg_replace_callback($regexp, function($match) {
// Convert the path if necessary.
$match[2] = self::_convertVariableScope(substr($match[2], 1, strlen($match[2]) - 2));
$extension = $this->template->extension === 'blade.php' ? 'blade.php' : 'html';
$dir = '$this->relative_dirname';
if ($match[1] === 'include' || $match[1] === 'includeIf')
{
$path = preg_match('#^([\'"])([^\'"]+)\1#', $match[2], $m) ? $m[2] : '';
if (preg_match('#^\^/?(\w.+)$#s', $path, $mm))
{
$dir = '"' . escape_dqstr(str_contains($mm[1], '/') ? dirname($mm[1]) : '') . '"';
$filename = basename($mm[1]);
$match[2] = preg_replace('#^([\'"])([^\'"]+)\1#', '$1' . $filename . '$1', $match[2]);
}
}
else
{
$path = preg_match('#^([^,]+,\s*)([\'"])([^\'"]+)\2#', $match[2], $m) ? $m[3] : '';
if (preg_match('#^\^/?(\w.+)$#s', $path, $mm))
{
$dir = '"' . escape_dqstr(str_contains($mm[1], '/') ? dirname($mm[1]) : '') . '"';
$filename = basename($mm[1]);
$match[2] = preg_replace('#^([^,]+,\s*)([\'"])([^\'"]+)\2#', '$1$2' . $filename . '$2', $match[2]);
}
}
// Generate an IIFE to create a new Template object and compile it.
if ($match[1] === 'include')
{
$tpl = '<?php (function($__dir, $__path, $__vars = null) { ';
$tpl .= '$__tpl = new \Rhymix\Framework\Template($__dir, $__path, "' . $extension . '"); ';
$tpl .= 'if ($__vars) $__tpl->setVars($__vars); ' ;
$tpl .= 'echo $__tpl->compile(); })(' . $dir . ', ' . $match[2] . '); ?>';
}
elseif ($match[1] === 'includeIf')
{
$tpl = '<?php (function($__dir, $__path, $__vars = null) { ';
$tpl .= '$__tpl = new \Rhymix\Framework\Template($__dir, $__path, "' . $extension . '"); ';
$tpl .= 'if (!$__tpl->exists()) return; ';
$tpl .= 'if ($__vars) $__tpl->setVars($__vars); ' ;
$tpl .= 'echo $__tpl->compile(); })(' . $dir . ', ' . $match[2] . '); ?>';
}
else
{
$tpl = '<?php (function($__type, $__dir, $__cond, $__path, $__vars = null) { ';
$tpl .= 'if ($__type === "includeWhen" && !$__cond) return; ';
$tpl .= 'if ($__type === "includeUnless" && $__cond) return; ';
$tpl .= '$__tpl = new \Rhymix\Framework\Template($__dir, $__path, "' . $extension . '"); ';
$tpl .= 'if ($__vars) $__tpl->setVars($__vars); ' ;
$tpl .= 'echo $__tpl->compile(); })("' . $match[1] . '", ' . $dir . ', ' . $match[2] . '); ?>';
}
return self::_escapeVars($tpl);
$directive = trim($match[1]);
$args = self::_convertVariableScope(substr($match[2], 1, strlen($match[2]) - 2));
return sprintf("<?php echo \$this->_v2_include('%s', %s); ?>", $directive, $args);
}, $content);
// Handle the @each directive.
@ -435,23 +386,13 @@ class TemplateParser_v2
// Convert the path if necessary.
$args = self::_convertVariableScope(substr($match[1], 1, strlen($match[1]) - 2));
$extension = $this->template->extension === 'blade.php' ? 'blade.php' : 'html';
$dir = '$this->relative_dirname';
$path = preg_match('#^([\'"])([^\'"]+)\1#', $args, $m) ? $m[2] : '';
if (preg_match('#^\^/?(\w.+)$#s', $path, $mm))
{
$dir = '"' . escape_dqstr(str_contains($mm[1], '/') ? dirname($mm[1]) : '') . '"';
$filename = basename($mm[1]);
$args = preg_replace('#^([\'"])([^\'"]+)\1#', '$1' . $filename . '$1', $args);
}
// Generate the IIFE code.
$tpl = '<?php (function($__dir, $__path, $__vars, $__varname, $__empty = null) { ';
$tpl .= 'if (!$__vars): $__vars = []; if ($__empty): $__path = $__empty; $__vars[] = \'\'; endif; endif; ';
// Generate the loop code.
$tpl = '<?php (function($__filename, $__vars, $__varname, $__empty = null) { ';
$tpl .= 'if (!$__vars): $__vars = []; if ($__empty): $__filename = $__empty; $__vars[] = \'\'; endif; endif; ';
$tpl .= 'foreach ($__vars as $__var): ';
$tpl .= '$__tpl = new \Rhymix\Framework\Template($__dir, $__path, "' . $extension . '"); ';
$tpl .= '$__tpl->setVars([(string)$__varname => $__var]); ' ;
$tpl .= 'echo $__tpl->compile(); endforeach; })(' . $dir . ', ' . $args . '); ?>';
$tpl .= 'echo $this->_v2_include("include", $__filename, [(string)$__varname => $__var]); ';
$tpl .= 'endforeach; })(' . $args . '); ?>';
return self::_escapeVars($tpl);
}, $content);