获取模版文件名，可能返回文本或文本数组
@param string $template
@param string $theme
@return string
971356
public function getTemplateFile($template = null, $theme = null)
	{
		if(empty($theme))
		{
			$theme=array_pop($this->themeStack);
			$this->themeStack[] = $theme;
		}
		if (is_file($template))
		{
			// 是文件就不用解析了
			return $template;
		}
		else
		{
			if(is_string($template))
			{
				// 主题名
				if (false !== stripos($template, '@theme'))
				{
					$template = str_replace('@theme', $this->getThemeName($theme), $template);
				}
				// 模块名
				if (false !== stripos($template, '@module'))
				{
					$template = str_replace('@module', Dispatch::module(), $template);
				}
				// 控制器名
				if (false !== stripos($template, '@control'))
				{
					$template = str_replace('@control', Dispatch::control(), $template);
				}
				// 动作名
				if (false !== stripos($template, '@action'))
				{
					$template = str_replace('@action', Dispatch::action(), $template);
				}
				
				// 项目模版目录
				if (false !== stripos($template, '@app/'))
				{
					$template = str_replace('@app/', APP_TEMPLATE, $template);
				}
				// 模块模版目录
				else if (false !== stripos($template, '@m/'))
				{
					$template = str_replace('@m/', APP_MODULE . Dispatch::module() . '/' . Config::get('@.TEMPLATE_PATH').'/', $template);
				}
				else 
				{
					$arr=explode('/',$template);
					$s = count($arr);
					if(1 === $s)
					{
						// 动作
						list($action) = $arr;
					}
					else if(2 === $s)
					{
						// 控制器/动作
						list($control,$action) = $arr;
					}
					else if(3 === $s)
					{
						// 模块/控制器/动作
						list($module,$control,$action) = $arr;
					}
					else if(4 === $s)
					{
						// 主题/模块/控制器/动作
						list($themeName,$module,$control,$action) = $arr;
					}
					else
					{
						list($themeName,$module,$control) = $arr;
						$action=implode('/',array_slice($arr,3));
					}
				}
			}
			if(empty($template) || isset($arr))
			{
				$path=array_pop($this->pathStack);
				$this->pathStack[] = $path;
				if('/'!==$template[0] && null!==$path)
				{
					$template=$path.$template;
				}
				else 
				{
					if(!isset($themeName))
					{
						$themeName = $this->getThemeName($theme);
					}
					if(!isset($module))
					{
						$module = Dispatch::module();
					}
					if(!isset($control))
					{
						$control = Dispatch::control();
					}
					if(!isset($action))
					{
						$action = Dispatch::action();
					}
					if(Config::get('@.MODULE_TEMPLATE'))
					{
						$template=APP_MODULE."{$module}/".Config::get('@.TEMPLATE_PATH')."/{$themeName}/{$control}/{$action}";
					}
					else
					{
						$template=APP_TEMPLATE."{$themeName}/{$module}/{$control}/{$action}";
					}
				}
			}
			$template.=Config::get('@.TEMPLATE_EXT');
		}
		return $template;
	}
436084
public static function pub($file, $theme = null)
    {
        $theme = $theme ?: static::activeThemeName();

        return "/vendor/boomcms/themes/$theme/".ltrim(trim($file), '/');
    }
746146
protected function compiled($template)
    {
        $template = ltrim($template, '/');
        if (strrchr($template, '.') == $this->extension)
            $template = substr($template, 0, -strlen($this->extension));
        $file = $this->dir . DIRECTORY_SEPARATOR . $template . $this->extension;
        if (!is_file($file))
            throw new \RuntimeException("template not found:$file!");

        $modified = filemtime($file);
        $compiled = $this->temp . DIRECTORY_SEPARATOR . $template . ".{$modified}.php";
        if (!$this->debug && is_file($compiled) && filemtime($compiled) >= $modified)
            return $compiled;

        $content = self::compile(file_get_contents($file), $this->left, $this->right);
        self::writeFile($compiled, $content, $this->temp);

        return $compiled;
    }
1315969
public function parseTemplate($template='') {
        if(is_file($template)) {
            return $template;
        }
        $depr       =   C('TMPL_FILE_DEPR');
        $template   =   str_replace(':', $depr, $template);

        // 获取当前模块
        $module   =  MODULE_NAME;
        if(strpos($template,'@')){ // 跨模块调用模版文件
            list($module,$template)  =   explode('@',$template);
        }
        // 获取当前主题的模版路径
        defined('THEME_PATH') or    define('THEME_PATH', $this->getThemePath($module));

        // 分析模板文件规则
        if('' == $template) {
            // 如果模板文件名为空 按照默认规则定位
            $template = CONTROLLER_NAME . $depr . ACTION_NAME;
        }elseif(false === strpos($template, $depr)){
            $template = CONTROLLER_NAME . $depr . $template;
        }
        $file   =   THEME_PATH.$template.C('TMPL_TEMPLATE_SUFFIX');
        if(C('TMPL_LOAD_DEFAULTTHEME') && THEME_NAME != C('DEFAULT_THEME') && !is_file($file)){
            // 找不到当前主题模板的时候定位默认主题中的模板
            $file   =   dirname(THEME_PATH).'/'.C('DEFAULT_THEME').'/'.$template.C('TMPL_TEMPLATE_SUFFIX');
        }
        return $file;
    }
1275718
protected function findTwigFile($path, $template = null)
    {
        if ($template == null) {
            $template = $this->template;
        }

        return '::' . self::TWIG_TEMPLATE_PATH . '/' . $template . '/' . $path;
    }
1278329
private function buildTemplate($template)
    {
        $this->template = $template;
        $offset = "{
            x: $this->offsetX,
            y: $this->offsetY
        }";

        if ($this->offsetX == 20 && $this->offsetY == 20 || $this->offset == 20) {
            $offset = $this->offset;
        }

        $this->placement['enter'] = 'right';

        return "{
            icon: '$this->icon',
            title: '$this->title',
            message: '$this->message',
            url: '$this->url',
            target: '$this->target'
        }, {
            element: '$this->element',
            position: $this->position,
            type: '$this->type',
            allow_dismiss: $this->allowDismiss,
            newest_on_top: $this->newestFirst,
            showProgressbar: $this->progress,
            placement: " . json_encode($this->placement) . ",
            offset: $offset,
            spacing: $this->spacing,
            z_index: $this->zIndex,
            mouse_over: '$this->mouseOver',
            delay: $this->delay,
            timer: $this->timer,
            url_target: '$this->urlTarget',
            animate: " . json_encode($this->animate) . ",
            onShow: $this->onShow,
            onShown: $this->onShown,
            onClose: $this->onClose,
            onClosed: $this->onClosed,
            icon_type: '$this->iconType',
            template: `$this->template`
        }
        ";
    }
522291
private function loadTemplate($template)
    {
        if (!array_key_exists($template, $this->templateCache)) {
            $this->templateCache[$template] = $this->twig->loadTemplate($template);
        }

        return $this->templateCache[$template];
    }
1351301
public function getCompiledFile($template)
	{	
		$tplFile = static::getTemplateFile($template);
		if ($this->options['engine'] === 'php'){
			return $tplFile;
		}
		
		if(file_exists($tplFile)) {
		    if (is_file($template)) {
		        $tplCompiledFile = static::getCompiledPath() . '/_file/' . md5($template) . '.php';
		    } else {
                $tplCompiledFile = static::getCompiledPath() . $this->_getRelativeTemplate($template) . '.php';
		    }
		    
			if (!$this->options['isCompiled'] || !file_exists($tplCompiledFile) || (@filemtime($tplFile) > @filemtime($tplCompiledFile)) ) {
				$tplCompiledPath = dirname($tplCompiledFile);
				if (!file_exists($tplCompiledPath)) {
					Dir::create($tplCompiledPath, 0755);
				}
				
				$content = file_get_contents($tplFile);
				$content = $this->parse($content);
				
				$strlen = file_put_contents($tplCompiledFile, $content);
				chmod ($tplCompiledFile, 0755);
			}
			
			return $tplCompiledFile;
		} else {
			throw new ViewException('template: ' . $tplFile. ' is not exists.');
		}
	}
710567
protected function nospaces(string $template): string
	{
		// Compile regular nospace blocks

		$template = preg_replace_callback('/{%\s*nospace\s*%}(.*?){%\s*endnospace\s*%}/is', function($matches)
		{
			return trim(preg_replace('/>\s+</', '><', $matches[1]));
		}, $template);

		// Compile buffered nospace blocks

		$template = preg_replace('/{%\s*nospace:buffered\s*%}(.*?){%\s*endnospace\s*%}/is', '<?php ob_start(); ?>$1<?php echo trim(preg_replace(\'/>\s+</\', \'><\', ob_get_clean())); ?>', $template);

		return $template;
	}
1325272
protected function captures(string $template): string
	{
		return preg_replace_callback('/{%\s*capture:(\$?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*?)\s*%}(.*?){%\s*endcapture\s*%}/is', function($matches)
		{
			return '<?php ob_start(); ?>' . $matches[2] . '<?php $' . ltrim($matches[1], '$') . ' = ob_get_clean(); ?>';
		}, $template);
	}
397053
private function findTemplate($template)
    {
        $logicalName = (string) $template;

        if (isset($this->cache[$logicalName])) {
            return $this->cache[$logicalName];
        }

        $template = $this->templateNameParser->parse($template);
        $file = $this->templateLocator->locate($template);

        return $this->cache[$logicalName] = $file;
    }
520635
protected function makeFile($file, $template = null)
	{
		if ( ! $this->files->exists($this->getPath($file)))
		{
			$content = $this->getPath($file);

			$facade = $this->option('facade');
			if ( ! is_null($facade))
			{
				$template = preg_replace('/Theme(\.|::)/', $facade.'$1', $template);
			}

			$this->files->put($content, $template);
		}
	}
1204678
public function getTemplateRelativePath($template)
	{
	    $rootPath = Config::getRootPath();
	    return str_replace($rootPath, '', $this->getTemplatePath()) . $this->_getRelativeTemplate($template) . $this->getSuffix();
	}
397520
public static function load($template)
	{
		// alter template so that it works
		$template = get_template_directory() != substr($template, 0, strlen(get_template_directory())) ? $template : substr($template, strlen(get_template_directory()) + 1);
		$template = get_stylesheet_directory() != substr($template, 0, strlen(get_stylesheet_directory())) ? $template : substr($template, strlen(get_stylesheet_directory()) + 1);
		$template = '.php' != substr($template, -4) ? $template : substr($template, 0, -4);
		// $template = 'templates.' == substr($template, 0, 10) ? $template : 'templates.' . $template;

		$mappedTemplate = static::mapTemplate($template);
		$template = locate_template($mappedTemplate);

		return new Loader($template);
	}
19093
protected function extensions(string $template): string
	{
		// Replace first occurance of extends tag with an empty string
		// and append the template with a view tag

		if(preg_match('/^{%\s*extends:(.*?)\s*%}/i', $template, $matches) > 0)
		{
			$replacement = '<?php $__view__ = $__viewfactory__->create(' . $matches[1] . '); $__renderer__ = $__view__->getRenderer(); ?>';

			$template = preg_replace('/^{%\s*extends:(.*?)\s*%}/i', $replacement, $template, 1);

			$template .= '<?php echo $__view__->render(); ?>';
		}

		return $template;
	}
502877
protected function resolveTemplate($template)
    {
        if (!$this->pathCache[$template]) {

            foreach (array_reverse($this->templateDirs) as $dir) {
                $path = $dir . DIRECTORY_SEPARATOR . $template .'.'. $this->getFileExtension();
                if (is_readable($path)) {
                    $this->pathCache[$template] = $path;
                    break;
                }
            }

        }

        return $this->pathCache[$template];
    }
503621
public function getTemplateContent(Template $template, $placeholders = [], $mode = 'content')
    {
        switch ($mode) {
            case 'content':
                return $this->replacePlaceholders($template->getContent(), $placeholders);
            case 'title':
                return $template->getTitle() ?
                    $this->replacePlaceholders($template->getTitle(), $placeholders) :
                    '';
        }

        return '';
    }