mirror of
https://github.com/smarty-php/smarty.git
synced 2025-10-04 16:20:55 +02:00
638 lines
20 KiB
PHP
638 lines
20 KiB
PHP
<?php
|
|
/*
|
|
* This file is part of the Smarty PHPUnit tests.
|
|
*
|
|
*/
|
|
|
|
use Smarty\Exception;
|
|
use Smarty\TemplateBase;
|
|
use Smarty\Template;
|
|
|
|
/**
|
|
* Smarty Test Case Fixture
|
|
*/
|
|
class PHPUnit_Smarty extends PHPUnit\Framework\TestCase
|
|
{
|
|
|
|
/**
|
|
* Smarty object
|
|
*
|
|
* @var \Smarty\Smarty
|
|
*/
|
|
public $smarty = null;
|
|
|
|
/**
|
|
* Flag for initialization at first test
|
|
*
|
|
* @var bool
|
|
*/
|
|
public static $init = true;
|
|
|
|
/**
|
|
* Count test number
|
|
*
|
|
* @var bool
|
|
*/
|
|
public static $testNumber = 0;
|
|
|
|
/**
|
|
* Configuration data from config.xml
|
|
*
|
|
* @var array
|
|
*/
|
|
public static $config = null;
|
|
|
|
/**
|
|
* Saved current working directory
|
|
*
|
|
* @var null
|
|
*/
|
|
public static $cwd = null;
|
|
|
|
/**
|
|
* PDO object for Mysql tests
|
|
*
|
|
* @var PDO
|
|
*/
|
|
public static $pdo = null;
|
|
|
|
public static $pluginsdir = null;
|
|
|
|
/**
|
|
* This method is called before the first test of this test class is run.
|
|
*
|
|
*/
|
|
public static function setUpBeforeClass(): void
|
|
{
|
|
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
|
|
self::$init = true;
|
|
self::$pluginsdir =self::getSmartyPluginsDir();
|
|
}
|
|
|
|
/**
|
|
* This method is called after the last test of this test class is run.
|
|
*
|
|
*/
|
|
public static function tearDownAfterClass(): void
|
|
{
|
|
//self::$pdo = null;
|
|
self::$testNumber = 0;
|
|
}
|
|
|
|
/**
|
|
* Constructs a test case with the given name.
|
|
*
|
|
* @param string $name
|
|
* @param array $data
|
|
* @param string $dataName
|
|
*/
|
|
public function __construct($name = null, array $data = array(), $dataName = '')
|
|
{
|
|
date_default_timezone_set('Europe/Berlin');
|
|
if (!defined('individualFolders')) {
|
|
define('individualFolders', true);
|
|
}
|
|
parent::__construct($name, $data, $dataName);
|
|
}
|
|
|
|
/**
|
|
* Setup Smarty instance called for each test
|
|
*
|
|
* @param null $dir working directory
|
|
*/
|
|
public function setUpSmarty($dir)
|
|
{
|
|
static $s_dir;
|
|
// set up current working directory
|
|
chdir($dir);
|
|
self::$cwd = getcwd();
|
|
// create missing folders for test
|
|
if (self::$init) {
|
|
if (!is_dir($dir . '/templates')) {
|
|
mkdir($dir . '/templates');
|
|
}
|
|
if (!is_dir($dir . '/configs')) {
|
|
mkdir($dir . '/configs');
|
|
}
|
|
if (individualFolders != 'true') {
|
|
if (!isset($s_dir[ $dir ])) {
|
|
$this->cleanDir($dir . '/templates_c');
|
|
$this->cleanDir($dir . '/cache');
|
|
if (is_dir($dir . '/templates_tmp')) {
|
|
$this->cleanDir($dir . '/templates_tmp');
|
|
}
|
|
$s_dir[ $dir ] = true;
|
|
}
|
|
$dir = __DIR__;
|
|
}
|
|
if (!is_dir($dir . '/templates_c')) {
|
|
mkdir($dir . '/templates_c');
|
|
}
|
|
chmod($dir . '/templates_c', 0775);
|
|
if (!is_dir($dir . '/cache')) {
|
|
mkdir($dir . '/cache');
|
|
chmod($dir . '/cache', 0775);
|
|
}
|
|
self::$init = false;
|
|
}
|
|
clearstatcache();
|
|
|
|
// instance Smarty class
|
|
$this->smarty = new \Smarty\Smarty();
|
|
if (individualFolders != 'true') {
|
|
$this->smarty->setCompileDir(__DIR__ . '/templates_c');
|
|
$this->smarty->setCacheDir(__DIR__ . '/cache');
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Create Mysql PDO object
|
|
*
|
|
*/
|
|
final public function getConnection()
|
|
{
|
|
if (PHPUnit_Smarty::$pdo == null) {
|
|
try {
|
|
PHPUnit_Smarty::$pdo = new PDO(DB_DSN, DB_USER, DB_PASSWD);
|
|
}
|
|
catch (PDOException $e) {
|
|
throw new Exception('Mysql Resource failed: ' . $e->getMessage());
|
|
}
|
|
$timezone = date_default_timezone_get();
|
|
$j = PHPUnit_Smarty::$pdo->exec("SET time_zone = '{$timezone}';");
|
|
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create table for Mysql resource
|
|
*
|
|
*/
|
|
public function initMysqlResource()
|
|
{
|
|
$this->getConnection();
|
|
PHPUnit_Smarty::$pdo->exec("DROP TABLE `templates`");
|
|
PHPUnit_Smarty::$pdo->exec("CREATE TABLE IF NOT EXISTS `templates` (
|
|
`name` varchar(100) NOT NULL,
|
|
`modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
`source` text,
|
|
PRIMARY KEY (`name`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8");
|
|
|
|
}
|
|
|
|
/**
|
|
* Create table for Mysql cache resource
|
|
*
|
|
*/
|
|
public function initMysqlCache()
|
|
{
|
|
$this->getConnection();
|
|
PHPUnit_Smarty::$pdo->exec("DROP TABLE `output_cache`");
|
|
PHPUnit_Smarty::$pdo->exec("CREATE TABLE IF NOT EXISTS `output_cache` (
|
|
`name` varchar(256) NOT NULL,
|
|
`id` char(40) NOT NULL,
|
|
`cache_id` varchar(250) DEFAULT NULL,
|
|
`compile_id` varchar(250) DEFAULT NULL,
|
|
`modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
`content` mediumblob NOT NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `cache_id` (`cache_id`),
|
|
KEY `compile_id` (`compile_id`),
|
|
KEY `modified` (`modified`),
|
|
KEY `name` (`name`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8");
|
|
// PHPUnit_Smarty::$pdo->exec("CREATE TABLE IF NOT EXISTS `output_cache` (
|
|
//`id` char(40) NOT NULL,
|
|
//`name` varchar(250) NOT NULL,
|
|
//`cache_id` varchar(250) DEFAULT NULL,
|
|
//`compile_id` varchar(250) DEFAULT NULL,
|
|
//`modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
//`expire` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
//`content` mediumblob NOT NULL,
|
|
///PRIMARY KEY (`id`),
|
|
//KEY `name` (`name`),
|
|
//KEY `cache_id` (`cache_id`),
|
|
//KEY `compile_id` (`compile_id`),
|
|
//KEY `modified` (`modified`),
|
|
//KEY `expire` (`expire`)
|
|
//) ENGINE=InnoDB DEFAULT CHARSET=utf8");
|
|
|
|
}
|
|
|
|
/**
|
|
* Delete files in templates_c and cache folders
|
|
*
|
|
*/
|
|
public function cleanDirs()
|
|
{
|
|
$this->cleanCompileDir();
|
|
$this->cleanCacheDir();
|
|
if (is_dir(self::$cwd . '/templates_tmp')) {
|
|
$this->cleanDir(self::$cwd . '/templates_tmp');
|
|
}
|
|
$this->assertTrue(true);
|
|
}
|
|
|
|
/**
|
|
* Make temporary template file
|
|
*
|
|
*/
|
|
public function makeTemplateFile($name, $code)
|
|
{
|
|
if (!is_dir(self::$cwd . '/templates_tmp')) {
|
|
mkdir(self::$cwd . '/templates_tmp');
|
|
chmod(self::$cwd . '/templates_tmp', 0775);
|
|
}
|
|
$fileName = self::$cwd . '/templates_tmp/' . "{$name}";
|
|
file_put_contents($fileName, $code);
|
|
}
|
|
|
|
/**
|
|
* Delete files in templates_c folder
|
|
*
|
|
*/
|
|
public function cleanCompileDir()
|
|
{
|
|
$smarty = $this->getSmarty();
|
|
if (isset($smarty)) {
|
|
$dir = $smarty->getCompileDir();
|
|
$this->cleanDir($dir);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete files in cache folder
|
|
*
|
|
*/
|
|
public function cleanCacheDir()
|
|
{
|
|
$smarty = $this->getSmarty();
|
|
if (isset($smarty)) {
|
|
$dir = $smarty->getCacheDir();
|
|
$this->cleanDir($dir);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete files and sub folders
|
|
*
|
|
* @param string $dir
|
|
*/
|
|
public function cleanDir($dir)
|
|
{
|
|
$di = new RecursiveDirectoryIterator($dir);
|
|
$ri = new RecursiveIteratorIterator($di, RecursiveIteratorIterator::CHILD_FIRST);
|
|
foreach ($ri as $file) {
|
|
if (substr(basename($file->getPathname()), 0, 1) === '.' || substr((string)$file,-4) === '.txt') {
|
|
continue;
|
|
}
|
|
// directory ?
|
|
if ($file->isDir()) {
|
|
if (!$ri->isDot()) {
|
|
// delete folder if empty
|
|
@rmdir($file->getPathname());
|
|
}
|
|
} else {
|
|
unlink($file->getPathname());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get PDO object
|
|
*
|
|
* @return null|PDO
|
|
*/
|
|
final public function getPDO()
|
|
{
|
|
return PHPUnit_Smarty::$pdo;
|
|
}
|
|
|
|
/**
|
|
* Remove "\r" and replace "\t" with spaces
|
|
*
|
|
* @param string $in
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function normalizeString($in)
|
|
{
|
|
if (is_string($in)) {
|
|
return str_replace(array("\r", "\t"), array('', ' '), $in);
|
|
} else {
|
|
return $in;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove all spaces
|
|
*
|
|
* @param string $in
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function strip($in)
|
|
{
|
|
if (is_string($in)) {
|
|
return preg_replace('/\s/', '', $in);
|
|
} else {
|
|
return $in;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return source path
|
|
*
|
|
* @param TemplateBase $tpl template object
|
|
* @param null|string $name optional template name
|
|
* @param null|string $type optional template type
|
|
* @param null|string $dir optional template folder
|
|
*
|
|
* @return string
|
|
* @throws \Exception
|
|
*/
|
|
public function buildSourcePath($tpl, $name = null, $type = null, $dir = null)
|
|
{
|
|
$name = isset($name) ? $name : $tpl->getSource()->name;
|
|
$type = isset($type) ? $type : $tpl->getSource()->type;
|
|
$dir = isset($dir) ? $dir : $this->smarty->getTemplateDir(0);
|
|
switch ($type) {
|
|
case 'file':
|
|
case 'filetest':
|
|
case 'php':
|
|
return $this->normalizePath($dir . $name);
|
|
case 'mysqltest':
|
|
case 'mysql':
|
|
return sha1($type . ':' . $name);
|
|
case 'string':
|
|
$this->smarty->getTemplateDir();
|
|
return sha1($name . $this->smarty->_joined_template_dir);
|
|
default:
|
|
throw new Exception("Unhandled source resource type '{$type}'");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build template uid
|
|
*
|
|
* @param TemplateBase $tpl template object
|
|
* @param null|string $value
|
|
* @param null|string $name optional template name
|
|
* @param null|string $type optional template type
|
|
*
|
|
* @return string
|
|
* @throws \Exception
|
|
*/
|
|
public function buildUid($tpl, $value = null, $name = null, $type = null)
|
|
{
|
|
$type = isset($type) ? $type : $tpl->getSource()->type;
|
|
$name = isset($name) ? $name : $tpl->getSource()->name;
|
|
switch ($type) {
|
|
case 'php':
|
|
case 'file':
|
|
case 'filetest':
|
|
if ($tpl instanceof \Smarty\Smarty) {
|
|
return sha1($this->normalizePath($this->smarty->getTemplateDir(0) . $name) .
|
|
$this->smarty->_joined_template_dir);
|
|
}
|
|
return sha1($tpl->getSource()->uid . $this->smarty->_joined_template_dir);
|
|
case 'mysqltest':
|
|
case 'mysql':
|
|
return sha1($type . ':' . $name);
|
|
case 'string':
|
|
$this->smarty->getTemplateDir();
|
|
return sha1($name . $this->smarty->_joined_template_dir);
|
|
default:
|
|
throw new Exception("Unhandled source resource type '{$type}'");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Normalize path
|
|
* - remove /./ and /../
|
|
* - make it absolute
|
|
*
|
|
* @param string $path file path
|
|
*
|
|
* @return string
|
|
*/
|
|
public function normalizePath($path, $ds =null ,$absolute = true)
|
|
{
|
|
$ds = isset($ds) ? $ds : DIRECTORY_SEPARATOR;
|
|
$nds = $ds == '/' ? '\\' : '/';
|
|
$getcwd = getcwd();
|
|
// normalize $ds
|
|
$path = str_replace($nds, $ds, $path);
|
|
preg_match('#^([a-zA-Z][:])?([.]{1,2}[\/\\\]+)?([\\\])?([.]{0,2}[\/\\\]+)?([[:print:]]*)#', $path, $match);
|
|
if ($match[1] === '') {
|
|
if ($match[ 2 ] !== '' || $match[ 2 ] . $match[ 3 ] . $match[ 4 ] === '') {
|
|
$path = $getcwd . $ds . $path;
|
|
} else if (\Smarty\Smarty::$_IS_WINDOWS && $match[ 3 ] !== '') {
|
|
$path = substr($getcwd, 0, 2) . $path;
|
|
}
|
|
}
|
|
$path = preg_replace('#[\\\/]+([.][\\\/]+)*#', $ds, $path);
|
|
while (strrpos($path, '.' . $ds) !== false) {
|
|
$path =
|
|
preg_replace('#([\\\/]([^\\\/]+[\\\/]){2}([.][.][\\\/]){2})|([\\\/][^\\\/]+[\\\/][.][.][\\\/])#', $ds,
|
|
$path);
|
|
}
|
|
$cwd = preg_replace('#[\\\/]#', $ds, $getcwd);
|
|
$path = str_ireplace($cwd,$getcwd, $path);
|
|
if (!$absolute) {
|
|
$path = preg_replace('#'.$getcwd.'#', '', $path);
|
|
}
|
|
return $path;
|
|
}
|
|
|
|
/**
|
|
* Return base name
|
|
*
|
|
* @param \Smarty\Template|\Smarty\TemplateBase $tpl template object
|
|
* @param null|string $name optional template name
|
|
* @param null|string $type optional template type
|
|
*
|
|
* @return null|string
|
|
*/
|
|
public function getBasename(Template $tpl, $name = null, $type = null)
|
|
{
|
|
$name = isset($name) ? $name : $tpl->getSource()->name;
|
|
$type = isset($type) ? $type : $tpl->getSource()->type;
|
|
switch ($type) {
|
|
case 'file':
|
|
case 'filetest':
|
|
if (($_pos = strpos($name, ']')) !== false) {
|
|
$name = substr($name, $_pos + 1);
|
|
}
|
|
return basename($name);
|
|
case 'mysqltest':
|
|
case 'mysql':
|
|
return $name;
|
|
case 'string':
|
|
return '';
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return compiled file path
|
|
*
|
|
* @param \Smarty\Template|\Smarty\TemplateBase $tpl template object
|
|
* @param bool $sub use sub directory flag
|
|
* @param bool $caching caching flag
|
|
* @param null|string $compile_id optional compile id
|
|
* @param null|string $name optional template name
|
|
* @param null|string $type optional template type
|
|
* @param null|string $dir optional template folder
|
|
*
|
|
* @return string
|
|
* @throws \Exception
|
|
*/
|
|
public function buildCompiledPath(Template $tpl, $sub = true, $caching = false, $compile_id = null,
|
|
$name = null, $type = null, $dir = null)
|
|
{
|
|
$sep = DIRECTORY_SEPARATOR;
|
|
$_compile_id = isset($compile_id) ? preg_replace('![^\w\|]+!', '_', $compile_id) : null;
|
|
$sp = $this->buildSourcePath($tpl, $name, $type, $dir);
|
|
$uid = $this->buildUid($tpl, $sp, $name, $type);
|
|
$_flag = '';
|
|
if ($tpl->getSource() && $tpl->getSource()->isConfig) {
|
|
$_flag = '_' . ((int) $tpl->getSmarty()->config_read_hidden + (int) $tpl->getSmarty()->config_booleanize * 2 +
|
|
(int) $tpl->getSmarty()->config_overwrite * 4);
|
|
} else {
|
|
$_flag = '_' . ((int) $tpl->getSmarty()->merge_compiled_includes + (int) $tpl->getSmarty()->escape_html * 2);
|
|
}
|
|
$_filepath = $uid . $_flag;
|
|
// if use_sub_dirs, break file into directories
|
|
if ($sub) {
|
|
$_filepath =
|
|
substr($_filepath, 0, 2) . $sep . substr($_filepath, 2, 2) . $sep . substr($_filepath, 4, 2) . $sep .
|
|
$_filepath;
|
|
}
|
|
$_compile_dir_sep = $sub ? $sep : '^';
|
|
if (isset($_compile_id)) {
|
|
$_filepath = $_compile_id . $_compile_dir_sep . $_filepath;
|
|
}
|
|
// caching token
|
|
if ($caching) {
|
|
$_cache = '.cache';
|
|
} else {
|
|
$_cache = '';
|
|
}
|
|
$_compile_dir = $tpl->getSmarty()->getCompileDir();
|
|
// set basename if not specified
|
|
$_basename = $this->getBasename($tpl, $name, $type);
|
|
if ($_basename === null) {
|
|
$_basename = basename(preg_replace('![^\w\/]+!', '_', $name));
|
|
}
|
|
// separate (optional) basename by dot
|
|
if ($_basename) {
|
|
$_basename = '.' . $_basename;
|
|
}
|
|
|
|
return $_compile_dir . $_filepath . '.' . $type . $_basename . $_cache . '.php';
|
|
}
|
|
|
|
/**
|
|
* Return cache file path
|
|
*
|
|
* @param TemplateBase $tpl template object
|
|
* @param bool $sub use sub directory flag
|
|
* @param null|string $cache_id optional cache id
|
|
* @param null|string $compile_id optional compile id
|
|
* @param null|string $name optional template name
|
|
* @param null|string $type optional template type
|
|
* @param null|string $dir optional template folder
|
|
* @param null|string $cacheType optional cache resource type
|
|
*
|
|
* @return string
|
|
* @throws \Exception
|
|
*/
|
|
public function buildCachedPath(TemplateBase $tpl, $sub = true, $cache_id = null, $compile_id = null, $name = null, $type = null,
|
|
$dir = null, $cacheType = null)
|
|
{
|
|
$cacheType = $cacheType ?? $tpl->getSmarty()->getCachingType();
|
|
switch ($cacheType) {
|
|
case 'file':
|
|
case 'filetest':
|
|
$sep = DIRECTORY_SEPARATOR;
|
|
$_compile_id = isset($compile_id) ? preg_replace('![^\w\|]+!', '_', $compile_id) : null;
|
|
$_cache_id = isset($cache_id) ? preg_replace('![^\w\|]+!', '_', $cache_id) : null;
|
|
$sp = $this->buildSourcePath($tpl, $name, $type, $dir);
|
|
$uid = $this->buildUid($tpl, $sp, $name, $type);
|
|
$_filepath = $uid;
|
|
// if use_sub_dirs, break file into directories
|
|
if ($sub) {
|
|
$_filepath =
|
|
substr($_filepath, 0, 2) . $sep . substr($_filepath, 2, 2) . $sep . substr($_filepath, 4, 2) .
|
|
$sep . $_filepath;
|
|
}
|
|
$_compile_dir_sep = $sub ? $sep : '^';
|
|
if (isset($_cache_id)) {
|
|
$_cache_id = str_replace('|', $_compile_dir_sep, $_cache_id) . $_compile_dir_sep;
|
|
} else {
|
|
$_cache_id = '';
|
|
}
|
|
if (isset($_compile_id)) {
|
|
$_compile_id = $_compile_id . $_compile_dir_sep;
|
|
} else {
|
|
$_compile_id = '';
|
|
}
|
|
return $tpl->getSmarty()->getCacheDir() . $_cache_id . $_compile_id . $_filepath . '.' . basename($sp) . '.php';
|
|
case 'mysqltest':
|
|
case 'pdo':
|
|
case 'foobar':
|
|
$sp = $this->buildSourcePath($tpl, $name, $type, $dir);
|
|
$uid = $this->buildUid($tpl, $sp, $name, $type);
|
|
$_compile_id = isset($compile_id) ? preg_replace('![^\w\|]+!', '_', $compile_id) : null;
|
|
$_cache_id = isset($cache_id) ? preg_replace('![^\w\|]+!', '_', $cache_id) : null;
|
|
return sha1($uid . $_cache_id . $_compile_id);
|
|
case 'memcachetest':
|
|
case 'apc':
|
|
$sp = $this->buildSourcePath($tpl, $name, $type, $dir);
|
|
$uid = $this->buildUid($tpl, $sp, $name, $type);
|
|
$_compile_id = isset($compile_id) ? preg_replace('![^\w\|]+!', '_', $compile_id) : null;
|
|
$_cache_id = isset($cache_id) ? preg_replace('![^\w\|]+!', '_', $cache_id) : null;
|
|
return sha1($uid) . '#' . preg_replace('#[^\w\|]+#S', '_', $tpl->template_resource) . '#' . $_cache_id .
|
|
'#' . $_compile_id;
|
|
|
|
default:
|
|
throw new Exception("Unhandled cache resource type '{$cacheType}'");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* prefilter to insert test number
|
|
*
|
|
* @param string $source
|
|
* @param \Smarty\Template $tpl
|
|
*
|
|
* @return string
|
|
*/
|
|
public function prefilterTest($source, Template $tpl)
|
|
{
|
|
return str_replace('#test#', "test:{\$test nocache} compiled:{$tpl->getTemplateVars('test')} rendered:{\$test}",
|
|
$source);
|
|
}
|
|
|
|
/**
|
|
* Gat Smarty object
|
|
* @return null|\Smarty
|
|
*/
|
|
public function getSmarty(){
|
|
return $this->smarty;
|
|
}
|
|
|
|
public static function getSmartyPluginsDir(){
|
|
if (is_dir(__DIR__ . '/../smarty/src/plugins')) {
|
|
return __DIR__ . '/../smarty/src/plugins';
|
|
} else if(is_dir(__DIR__ . '/../libs/plugins')) {
|
|
return __DIR__ . '/../libs/plugins';
|
|
}
|
|
}
|
|
}
|