fix config_load, compile fetched arrays to compile_dir, switch display

back to runtime. clean up var names and function names,  split up compile
testing and compiling to separate funcs, rename some template_* functions to
file_* functions and update logic so they can be used for file resources
other than templates.
This commit is contained in:
mohrt
2003-06-16 19:45:11 +00:00
parent d62680f94e
commit f42a23f504
11 changed files with 143 additions and 255 deletions

View File

@@ -1069,9 +1069,9 @@ reques * @var string
*/
function template_exists($tpl_file)
{
$_params = array('tpl_path' => $tpl_file);
require_once(SMARTY_DIR . 'core/core.fetch_template_info.php');
return smarty_core_fetch_template_info($_params, $this);
$_params = array('file_path' => $this->template_dir . '/' . $tpl_file);
require_once(SMARTY_DIR . 'core/core.fetch_file_info.php');
return smarty_core_fetch_file_info($_params, $this);
}
/**
@@ -1245,18 +1245,21 @@ reques * @var string
}
}
$_smarty_compile_path = $this->_get_compile_path($tpl_file);
$_template_file_path = $this->template_dir . '/' . $tpl_file;
$_smarty_compile_path = $this->_get_compile_path($_template_file_path);
// if we just need to display the results, don't perform output
// buffering - for speed
if ($display && !$this->caching && count($this->_plugins['outputfilter']) == 0) {
if ($this->_process_template($tpl_file, $_smarty_compile_path))
if (!$this->_file_needs_compiling($_template_file_path, $_smarty_compile_path)
|| $this->_compile_template($tpl_file, $_smarty_compile_path))
{
include($_smarty_compile_path);
}
} else {
ob_start();
if ($this->_process_template($tpl_file, $_smarty_compile_path))
if (!$this->_file_needs_compiling($_template_file_path, $_smarty_compile_path)
|| $this->_compile_template($tpl_file, $_smarty_compile_path))
{
include($_smarty_compile_path);
}
@@ -1401,85 +1404,65 @@ reques * @var string
}
/**
* umm... process the template
* test if source file needs compiling
*
* @param string $tpl_file
* @param string $compile_path
* @return boolean
*/
function _process_template($tpl_file, $compile_path)
function _file_needs_compiling($file_path, $compile_path)
{
// test if template needs to be compiled
if (!$this->force_compile && file_exists($compile_path)) {
if (!$this->compile_check) {
// no need to check if the template needs recompiled
return true;
// no need to check compiled file
return false;
} else {
// get template source and timestamp
$_params = array('tpl_path' => $tpl_file);
require_once(SMARTY_DIR . 'core/core.fetch_template_info.php');
if (!smarty_core_fetch_template_info($_params, $this)) {
return false;
// get file source and timestamp
require_once(SMARTY_DIR . 'core/core.fetch_file_info.php');
$_params = array('file_path' => $file_path);
if (!smarty_core_fetch_file_info($_params, $this)) {
return true;
}
$_template_source = $_params['template_source'];
$_template_timestamp = $_params['template_timestamp'];
$_file_source = $_params['file_source'];
$_file_timestamp = $_params['file_timestamp'];
if ($_template_timestamp <= filemtime($compile_path)) {
// template not expired, no recompile
return true;
return false;
} else {
// compile template
$this->_compile_template($tpl_file, $_template_source, $_template_compiled);
$_params = array('compile_path' => $compile_path, 'template_compiled' => $_template_compiled, 'template_timestamp' => $_template_timestamp);
require_once(SMARTY_DIR . 'core/core.write_compiled_template.php');
smarty_core_write_compiled_template($_params, $this);
// compile template
return true;
}
}
} else {
// compiled template does not exist, or forced compile
$_params = array('tpl_path' => $tpl_file);
require_once(SMARTY_DIR . 'core/core.fetch_template_info.php');
if (!smarty_core_fetch_template_info($_params, $this)) {
return false;
}
$_template_source = $_params['template_source'];
$_template_timestamp = $_params['template_timestamp'];
$this->_compile_template($tpl_file, $_template_source, $_template_compiled);
$_params = array('compile_path' => $compile_path, 'template_compiled' => $_template_compiled, 'template_timestamp' => $_template_timestamp);
require_once(SMARTY_DIR . 'core/core.write_compiled_template.php');
smarty_core_write_compiled_template($_params, $this);
return true;
}
}
/**
* Get the compile path for this template file
/**
* compile the template
*
* @param string $tpl_file
* @return string results of {@link _get_auto_filename()}
*/
function _get_compile_path($tpl_file)
{
return $this->_get_auto_filename($this->compile_dir, $tpl_file,
$this->_compile_id);
}
/**
* called to compile the templates
*
* sets $template_compiled to the compiled template
* @param string $tpl_file
* @param string $template_source
* @param string $template_compiled
* @param string $compile_path
* @return boolean
*/
function _compile_template($tpl_file, $template_source, &$template_compiled)
{
if(file_exists(SMARTY_DIR.$this->compiler_file)) {
require_once SMARTY_DIR.$this->compiler_file;
function _compile_template($tpl_file, $compile_path)
{
// compiled template does not exist, or forced compile
$_params = array('file_path' => $this->template_dir . '/' . $tpl_file);
require_once(SMARTY_DIR . 'core/core.fetch_file_info.php');
if (!smarty_core_fetch_file_info($_params, $this)) {
return false;
}
$_file_source = $_params['file_source'];
$_file_timestamp = $_params['file_timestamp'];
if (file_exists(SMARTY_DIR . $this->compiler_file)) {
require_once(SMARTY_DIR . $this->compiler_file);
} else {
// use include_path
require_once $this->compiler_file;
require_once($this->compiler_file);
}
$smarty_compiler = new $this->compiler_class;
@@ -1507,12 +1490,28 @@ reques * @var string
$smarty_compiler->request_use_auto_globals = $this->request_use_auto_globals;
if ($smarty_compiler->_compile_file($tpl_file, $template_source, $template_compiled)) {
if ($smarty_compiler->_compile_file($tpl_file, $_file_source, $_file_compiled)) {
$_params = array('compile_path' => $compile_path, 'template_compiled' => $_file_compiled, 'template_timestamp' => $_file_timestamp);
require_once(SMARTY_DIR . 'core/core.write_compiled_template.php');
smarty_core_write_compiled_template($_params, $this);
return true;
} else {
$this->trigger_error($smarty_compiler->_error_msg);
return false;
}
}
}
/**
* Get the compile path for this template file
*
* @param string $tpl_file
* @return string results of {@link _get_auto_filename()}
*/
function _get_compile_path($tpl_file)
{
return $this->_get_auto_filename($this->compile_dir, $tpl_file,
$this->_compile_id);
}
/**

View File

@@ -668,7 +668,7 @@ class Smarty_Compiler extends Smarty {
* @return string
*/
function _compile_custom_tag($tag_command, $tag_args, $tag_modifier)
{
{
$this->_add_plugin('function', $tag_command);
$arg_list = array();
@@ -683,7 +683,6 @@ class Smarty_Compiler extends Smarty {
}
$_return = $this->_compile_plugin_call('function', $tag_command).'(array('.implode(',', (array)$arg_list)."), \$this)";
if($tag_modifier != '') {
$this->_parse_modifiers($return, $tag_modifier);
}
@@ -1458,7 +1457,6 @@ class Smarty_Compiler extends Smarty {
}
elseif(preg_match('!^' . $this->_cvar_regexp . '(?:' . $this->_mod_regexp . '*)$!', $val)) {
// config var
$this->_output_type = 'static';
return $this->_parse_conf_var($val);
}
elseif(preg_match('!^' . $this->_svar_regexp . '(?:' . $this->_mod_regexp . '*)$!', $val)) {
@@ -1600,24 +1598,22 @@ class Smarty_Compiler extends Smarty {
* parse configuration variable expression into PHP code
*
* @param string $conf_var_expr
* @return string
*/
function _parse_conf_var($conf_var_expr)
{
{
$parts = explode('|', $conf_var_expr, 2);
$var_ref = $parts[0];
$modifiers = isset($parts[1]) ? $parts[1] : '';
$var_name = substr($var_ref, 1, -1);
$output = isset($this->_config[0]['vars'][$var_name]) ? $this->_config[0]['vars'][$var_name] : '';
$output = "\$this->_config[0]['vars']['$var_name']";
$this->_parse_modifiers($output, $modifiers);
return $output;
}
/**
* parse section property expression into PHP code
*
@@ -1651,11 +1647,9 @@ class Smarty_Compiler extends Smarty {
*/
function _parse_modifiers(&$output, $modifier_string)
{
// match each modifier and its arguments
preg_match_all('!\|(@?\w+)((?>:(?:'. $this->_qstr_regexp . '|[^|]+))*)!', '|' . $modifier_string, $_match);
list(, $_modifiers, $_modifiers_argstrings) = $_match;
list(, $_modifiers, $modifier_arg_strings) = $_match;
for ($_i = 0, $_for_max = count($_modifiers); $_i < $_for_max; $_i++) {
$_modifier_name = $_modifiers[$_i];
@@ -1664,23 +1658,17 @@ class Smarty_Compiler extends Smarty {
continue;
}
// split up all the args
preg_match_all('!:(' . $this->_qstr_regexp . '|[^:]+)!', $_modifiers_argstrings[$_i], $_match);
preg_match_all('!:(' . $this->_qstr_regexp . '|[^:]+)!', $modifier_arg_strings[$_i], $_match);
$_modifier_args = $_match[1];
if ($_modifier_name{0} == '@') {
// apply modifier to entire array
$_map_array = 'false';
$_modifier_name = substr($_modifier_name, 1);
} else {
// apply modifier to each individual array element
$_map_array = 'true';
}
if($this->_output_type == 'php') {
// add to list of modifiers to load into the template
$this->_add_plugin('modifier', $_modifier_name);
}
$this->_add_plugin('modifier', $_modifier_name);
$this->_parse_vars_props($_modifier_args);
if($_modifier_name == 'default') {
@@ -1692,29 +1680,13 @@ class Smarty_Compiler extends Smarty {
$_modifier_args[0] = '@' . $_modifier_args[0];
}
}
if (count($_modifier_args) > 0)
$_modifier_args = ', '.implode(', ', $_modifier_args);
else
$_modifier_args = '';
if($this->_output_type == 'php') {
if (count($_modifier_args) > 0) {
$_modifier_args = $output . ',' . implode(',', $_modifier_args);
} else {
$_modifier_args = $output;
}
$output = "\$this->_run_mod_handler('$_modifier_name', $_map_array, array($_modifier_args))";
} else {
// static output
foreach($_modifier_args as $_key => $_val) {
// get rid of quotes around static values
$_modifier_args[$_key] = $this->_dequote($_val);
}
if(!isset($this->_plugins['modifier'][$_modifier_name])) {
$_params = array('plugins' => array(array('modifier', $_modifier_name, null, null, false)));
require_once(SMARTY_DIR . 'core/core.load_plugins.php');
smarty_core_load_plugins($_params, $this);
}
array_unshift($_modifier_args, $output);
$output = $this->_run_mod_handler($_modifier_name, $_map_array, $_modifier_args);
}
}
$output = "\$this->_run_mod_handler('$_modifier_name', $_map_array, $output$_modifier_args)";
}
}
@@ -1828,9 +1800,7 @@ class Smarty_Compiler extends Smarty {
break;
case 'config':
array_shift($indexes);
$compiled_ref = isset($this->_config[0]['vars'][substr($indexes[0],1)]) ? $this->_config[0]['vars'][substr($indexes[0],1)] : '';
$this->_output_type = 'static';
$compiled_ref = "\$this->_config[0]['vars']";
$_max_index = 2;
break;

View File

@@ -37,12 +37,12 @@ function smarty_core_parse_file_path(&$params, &$this)
$params['resource_name'] = $_file_path_parts[1];
}
}
if ($params['resource_type'] == 'file') {
if (!preg_match("/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/", $params['resource_name'])) {
// relative pathname to $params['file_base_path']
// use the first directory where the file is found
$_file_base_path = $params['file_base_path'];
$_file_base_path = isset($params['file_base_path']) ? $params['file_base_path'] : array('.');
settype($_file_base_path, 'array');
foreach ($_file_base_path as $_curr_path) {
$_fullpath = $_curr_path . DIRECTORY_SEPARATOR . $params['resource_name'];

View File

@@ -68,22 +68,25 @@ function smarty_core_read_cache_file(&$params, &$this)
}
if ($this->compile_check) {
require_once(SMARTY_DIR . 'core/core.fetch_file_info.php');
foreach (array_keys($this->_cache_info['template']) as $_template_dep) {
$_params = array('tpl_path' => $_template_dep);
require_once(SMARTY_DIR . 'core/core.fetch_template_info.php');
smarty_core_fetch_template_info($_params, $this);
if ($this->_cache_info['timestamp'] < $_params['template_timestamp']) {
$_params = array('file_path' => $this->template_dir . '/' . $_template_dep);
smarty_core_fetch_file_info($_params, $this);
if ($this->_cache_info['timestamp'] < $_params['file_timestamp']) {
// template file has changed, regenerate cache
return false;
}
}
if (isset($this->_cache_info['config'])) {
foreach (array_keys($this->_cache_info['config']) as $config_dep) {
if ($this->_cache_info['timestamp'] < filemtime($this->config_dir . DIRECTORY_SEPARATOR . $config_dep)) {
// config file has changed, regenerate cache
return false;
}
require_once(SMARTY_DIR . 'core/core.fetch_file_info.php');
foreach (array_keys($this->_cache_info['config']) as $_config_dep) {
$_params = array('file_path' => $this->config_dir . '/' . $_config_dep);
smarty_core_fetch_file_info($_params, $this);
if ($this->_cache_info['timestamp'] < $_params['file_timestamp']) {
// config file has changed, regenerate cache
return false;
}
}
}
}

View File

@@ -18,7 +18,7 @@
* @param Smarty clever method emulation
* @return string $content stripped of whitespace
*/
function smarty_block_strip($params, $content, &$this)
function smarty_block_strip($params, $content, &$smarty)
{
/* Reformat data between 'strip' and '/strip' tags, removing spaces, tabs and newlines. */
$_strip_search = array(

View File

@@ -27,7 +27,7 @@
* @param Smarty clever simulation of a method
* @return string string $content re-formatted
*/
function smarty_block_textformat($params, $content, &$this)
function smarty_block_textformat($params, $content, &$smarty)
{
$style = null;
$indent = 0;
@@ -71,7 +71,7 @@ function smarty_block_textformat($params, $content, &$this)
}
if($assign != null) {
$this->assign($assign,$output);
$smarty->assign($assign,$output);
} else {
return $output;
}

View File

@@ -1,107 +0,0 @@
<?php
/**
* Smarty plugin
* @package Smarty
* @subpackage plugins
*/
/**
* Smarty {config_load} function plugin
*
* Type: compiler<br>
* Name: config_load<br>
* Purpose: load config file vars
* @link http://smarty.php.net/manual/en/language.function.config.load.php {config_load}
* (Smarty online manual)
* @param array Format:
* <pre>
* array('file' => required config file name,
* 'section' => optional config file section to load
* 'scope' => local/parent/global
* 'global' => overrides scope, setting to parent if true)
* </pre>
* @param Smarty
*/
function smarty_compiler_config_load($params, &$smarty)
{
$params = $smarty->_parse_attrs($params, false);
if ($smarty->debugging) {
$_params = array();
$_debug_start_time = $smarty->_execute_core_function('get_microtime', $_params);
}
$_file = isset($params['file']) ? $smarty->_dequote($params['file']) : null;
$_section = isset($params['section']) ? $smarty->_dequote($params['section']) : null;
$_scope = isset($params['scope']) ? $smarty->_dequote($params['scope']) : 'global';
$_global = isset($params['global']) ? $smarty->_dequote($params['global']) : false;
if (!isset($_file) || strlen($_file) == 0) {
$smarty->_syntax_error("missing 'file' attribute in config_load tag", E_USER_ERROR, __FILE__, __LINE__);
}
if (isset($_scope)) {
if ($_scope != 'local' &&
$_scope != 'parent' &&
$_scope != 'global') {
$smarty->_syntax_error("invalid 'scope' attribute value", E_USER_ERROR, __FILE__, __LINE__);
}
} else {
if ($_global) {
$_scope = 'parent';
} else {
$_scope = 'local';
}
}
if(@is_dir($smarty->config_dir)) {
$_config_dir = $smarty->config_dir;
} else {
// config_dir not found, try include_path
$_params = array('file_path' => $smarty->config_dir);
$smarty->_execute_core_function('get_include_path', $_params);
$_config_dir = $_params['new_file_path'];
}
if(!is_object($smarty->_conf_obj)) {
require_once SMARTY_DIR . $smarty->config_class . '.class.php';
$smarty->_conf_obj = new $smarty->config_class($_config_dir);
$smarty->_conf_obj->overwrite = $smarty->config_overwrite;
$smarty->_conf_obj->booleanize = $smarty->config_booleanize;
$smarty->_conf_obj->read_hidden = $smarty->config_read_hidden;
$smarty->_conf_obj->fix_newlines = $smarty->config_fix_newlines;
$smarty->_conf_obj->set_path = $_config_dir;
}
$_config_vars = array_merge($smarty->_conf_obj->get($_file),
$smarty->_conf_obj->get($_file, $_section));
if ($smarty->caching) {
$smarty->_cache_info['config'][$_file] = true;
}
$smarty->_config[0]['vars'] = @array_merge($smarty->_config[0]['vars'], $_config_vars);
$smarty->_config[0]['files'][$_file] = true;
if ($_scope == 'parent') {
$smarty->_config[1]['vars'] = @array_merge($smarty->_config[1]['vars'], $_config_vars);
$smarty->_config[1]['files'][$_file] = true;
} else if ($_scope == 'global') {
for ($i = 1, $for_max = count($smarty->_config); $i < $for_max; $i++) {
$smarty->_config[$i]['vars'] = @array_merge($smarty->_config[$i]['vars'], $_config_vars);
$smarty->_config[$i]['files'][$_file] = true;
}
}
if ($smarty->debugging) {
$_params = array();
$smarty->_smarty_debug_info[] = array('type' => 'config',
'filename' => $_file.' ['.$_section.'] '.$_scope,
'depth' => $smarty->_inclusion_depth,
'exec_time' => $smarty->_execute_core_function('get_microtime', $_params) - $_debug_start_time);
}
}
/* vim: set expandtab: */
?>

View File

@@ -26,13 +26,14 @@ function smarty_function_config_load($params, &$smarty)
{
if ($smarty->debugging) {
$_params = array();
$_debug_start_time = $smarty->_execute_core_function('get_microtime', $_params);
require_once(SMARTY_DIR . 'core/core.get_microtime.php');
$_debug_start_time = smarty_core_get_microtime($_params, $smarty);
}
$_file = isset($params['file']) ? $params['file'] : null;
$_section = isset($params['section']) ? $params['section'] : null;
$_scope = isset($params['scope']) ? $params['scope'] : 'global';
$_global = isset($params['global']) ? $params['global'] : false;
$_file = isset($params['file']) ? $smarty->_dequote($params['file']) : null;
$_section = isset($params['section']) ? $smarty->_dequote($params['section']) : null;
$_scope = isset($params['scope']) ? $smarty->_dequote($params['scope']) : 'global';
$_global = isset($params['global']) ? $smarty->_dequote($params['global']) : false;
if (!isset($_file) || strlen($_file) == 0) {
$smarty->_syntax_error("missing 'file' attribute in config_load tag", E_USER_ERROR, __FILE__, __LINE__);
@@ -51,28 +52,46 @@ function smarty_function_config_load($params, &$smarty)
$_scope = 'local';
}
}
if(@is_dir($smarty->config_dir)) {
$_config_dir = $smarty->config_dir;
} else {
// config_dir not found, try include_path
$_params = array('file_path' => $smarty->config_dir);
$smarty->_execute_core_function('get_include_path', $_params);
require_once(SMARTY_DIR . 'core/core.get_include_path.php');
smarty_core_get_include_path($_params, $smarty);
$_config_dir = $_params['new_file_path'];
}
if(!is_object($smarty->_conf_obj)) {
require_once SMARTY_DIR . $smarty->config_class . '.class.php';
$smarty->_conf_obj = new $smarty->config_class($_config_dir);
$smarty->_conf_obj->overwrite = $smarty->config_overwrite;
$smarty->_conf_obj->booleanize = $smarty->config_booleanize;
$smarty->_conf_obj->read_hidden = $smarty->config_read_hidden;
$smarty->_conf_obj->fix_newlines = $smarty->config_fix_newlines;
$smarty->_conf_obj->set_path = $_config_dir;
}
$_config_vars = array_merge($smarty->_conf_obj->get($_file),
$smarty->_conf_obj->get($_file, $_section));
$_compile_file = $smarty->_get_compile_path($_config_dir . '/' . $_file);
if($smarty->force_compile
|| !file_exists($_compile_file)
|| ($smarty->compile_check
&& $smarty->_file_needs_compiling($_config_dir . '/' . $_file, $_compile_file))) {
// compile config file
if(!is_object($smarty->_conf_obj)) {
require_once SMARTY_DIR . $smarty->config_class . '.class.php';
$smarty->_conf_obj = new $smarty->config_class($_config_dir);
$smarty->_conf_obj->overwrite = $smarty->config_overwrite;
$smarty->_conf_obj->booleanize = $smarty->config_booleanize;
$smarty->_conf_obj->read_hidden = $smarty->config_read_hidden;
$smarty->_conf_obj->fix_newlines = $smarty->config_fix_newlines;
$smarty->_conf_obj->set_path = $_config_dir;
}
$_config_vars = array_merge($smarty->_conf_obj->get($_file),
$smarty->_conf_obj->get($_file, $_section));
if(function_exists('var_export')) {
$_output = '<?php $_config_vars = ' . var_export($_config_vars, true) . '; ?>';
} else {
$_output = '<?php $_config_vars = unserialize(' . serialize($_config_vars) . '); ?>';
}
$_params = (array('compile_path' => $_compile_file, 'template_compiled' => $_output));
require_once(SMARTY_DIR . 'core/core.write_compiled_template.php');
smarty_core_write_compiled_template($_params, $smarty);
} else {
include_once($_compile_file);
}
if ($smarty->caching) {
$smarty->_cache_info['config'][$_file] = true;
@@ -90,14 +109,16 @@ function smarty_function_config_load($params, &$smarty)
$smarty->_config[$i]['files'][$_file] = true;
}
}
if ($smarty->debugging) {
$_params = array();
require_once(SMARTY_DIR . 'core/core.get_microtime.php');
$smarty->_smarty_debug_info[] = array('type' => 'config',
'filename' => $_file.' ['.$_section.'] '.$_scope,
'depth' => $smarty->_inclusion_depth,
'exec_time' => $smarty->_execute_core_function('get_microtime', $_params) - $_debug_start_time);
}
'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time);
}
}
/* vim: set expandtab: */

View File

@@ -17,19 +17,19 @@
* @param array
* @param Smarty
*/
function smarty_function_eval($params, &$this)
function smarty_function_eval($params, &$smarty)
{
extract($params);
if (!isset($var)) {
$this->trigger_error("eval: missing 'var' parameter");
$smarty->trigger_error("eval: missing 'var' parameter");
return;
}
if($var == '') {
return;
}
$this->_compile_template("evaluated template", $var, $source);
$smarty->_compile_template("evaluated template", $var, $source);
ob_start();
eval('?>' . $source);
@@ -37,7 +37,7 @@ function smarty_function_eval($params, &$this)
ob_end_clean();
if (!empty($assign)) {
$this->assign($assign, $contents);
$smarty->assign($assign, $contents);
} else {
return $contents;
}

View File

@@ -28,7 +28,8 @@ function smarty_function_fetch($params, &$smarty)
if ($smarty->security && !preg_match('!^(http|ftp)://!i', $params['file'])) {
$_params = array('resource_type' => 'file', 'resource_name' => $params['file']);
if(!$smarty->_execute_core_function('is_secure', $_params)) {
require_once(SMARTY_DIR . 'core/core.is_secure.php');
if(!smarty_core_is_secure($_params, $smarty)) {
$smarty->_trigger_fatal_error('[plugin] (secure mode) fetch \'' . $params['file'] . '\' is not allowed');
return;
}

View File

@@ -113,7 +113,8 @@ function smarty_function_html_image($params, &$smarty)
}
}
$_params = array('resource_type' => 'file', 'resource_name' => $_image_path);
if(!$smarty->security && !$this->_execute_core_function('is_secure', $_params)) {
require_once(SMARTY_DIR . 'core/core.is_secure.php');
if(!$smarty->security && !smarty_core_is_secure($_params, $smarty)) {
$smarty->trigger_error("html_image: (secure) '$_image_path' not in secure directory", E_USER_NOTICE);
return;
}