Merge e938c6b372
into e0224aa18b
This commit is contained in:
commit
e24a6de92c
138
src/Fenom.php
138
src/Fenom.php
|
@ -93,12 +93,6 @@ class Fenom
|
|||
* @var Fenom\Render[] Templates storage
|
||||
*/
|
||||
protected $_storage = array();
|
||||
|
||||
/**
|
||||
* @var string compile directory
|
||||
*/
|
||||
protected $_compile_dir = "/tmp";
|
||||
|
||||
/**
|
||||
* @var int masked options
|
||||
*/
|
||||
|
@ -258,12 +252,11 @@ class Fenom
|
|||
* Just factory
|
||||
*
|
||||
* @param string|Fenom\ProviderInterface $source path to templates or custom provider
|
||||
* @param string $compile_dir path to compiled files
|
||||
* @param int $options
|
||||
* @throws InvalidArgumentException
|
||||
* @return Fenom
|
||||
*/
|
||||
public static function factory($source, $compile_dir = '/tmp', $options = 0)
|
||||
public static function factory($source, $options = 0)
|
||||
{
|
||||
if (is_string($source)) {
|
||||
$provider = new Fenom\Provider($source);
|
||||
|
@ -272,9 +265,8 @@ class Fenom
|
|||
} else {
|
||||
throw new InvalidArgumentException("Source must be a valid path or provider object");
|
||||
}
|
||||
$fenom = new static($provider);
|
||||
/* @var Fenom $fenom */
|
||||
$fenom->setCompileDir($compile_dir);
|
||||
$fenom = new static($provider);
|
||||
if ($options) {
|
||||
$fenom->setOptions($options);
|
||||
}
|
||||
|
@ -286,25 +278,10 @@ class Fenom
|
|||
*/
|
||||
public function __construct(Fenom\ProviderInterface $provider)
|
||||
{
|
||||
$provider->setFenom($this);
|
||||
$this->_provider = $provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set compile directory
|
||||
*
|
||||
* @param string $dir directory to store compiled templates in
|
||||
* @throws LogicException
|
||||
* @return Fenom
|
||||
*/
|
||||
public function setCompileDir($dir)
|
||||
{
|
||||
if(!is_writable($dir)) {
|
||||
throw new LogicException("Cache directory $dir is not writable");
|
||||
}
|
||||
$this->_compile_dir = $dir;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param callable $cb
|
||||
|
@ -624,6 +601,7 @@ class Fenom
|
|||
*/
|
||||
public function addProvider($scm, \Fenom\ProviderInterface $provider)
|
||||
{
|
||||
$provider->setFenom($this);
|
||||
$this->_providers[$scm] = $provider;
|
||||
return $this;
|
||||
}
|
||||
|
@ -735,14 +713,29 @@ class Fenom
|
|||
/** @var Fenom\Template $tpl */
|
||||
$tpl = $this->_storage[$key];
|
||||
if (($this->_options & self::AUTO_RELOAD) && !$tpl->isValid()) {
|
||||
return $this->_storage[$key] = $this->compile($template, true, $options);
|
||||
return $this->_storage[$key] = $this->getProviderByTemplate($template)->compile($template, true, $options);
|
||||
} else {
|
||||
return $tpl;
|
||||
}
|
||||
} elseif ($this->_options & self::FORCE_COMPILE) {
|
||||
return $this->compile($template, $this->_options & self::DISABLE_CACHE & ~self::FORCE_COMPILE, $options);
|
||||
return $this->getProviderByTemplate($template)->compile($template, $this->_options & self::DISABLE_CACHE & ~self::FORCE_COMPILE, $options);
|
||||
} else {
|
||||
return $this->_storage[$key] = $this->_load($template, $options);
|
||||
return $this->_storage[$key] = $this->getProviderByTemplate($template)->load($template, $options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $template
|
||||
* @return ProviderInterface
|
||||
*/
|
||||
public function getProviderByTemplate($template)
|
||||
{
|
||||
if ($provider = strstr($template, ":", true)) {
|
||||
if(isset($this->_providers[$provider])) {
|
||||
return $this->_providers[$provider];
|
||||
}
|
||||
} else {
|
||||
return $this->_provider;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -754,77 +747,12 @@ class Fenom
|
|||
public function templateExists($template)
|
||||
{
|
||||
if ($provider = strstr($template, ":", true)) {
|
||||
if (isset($this->_providers[$provider])) {
|
||||
if(isset($this->_providers[$provider])) {
|
||||
return $this->_providers[$provider]->templateExists(substr($template, strlen($provider) + 1));
|
||||
}
|
||||
} else {
|
||||
return $this->_provider->templateExists($template);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load template from cache or create cache if it doesn't exists.
|
||||
*
|
||||
* @param string $tpl
|
||||
* @param int $opts
|
||||
* @return Fenom\Render
|
||||
*/
|
||||
protected function _load($tpl, $opts)
|
||||
{
|
||||
$file_name = $this->_getCacheName($tpl, $opts);
|
||||
if (is_file($this->_compile_dir . "/" . $file_name)) {
|
||||
$fenom = $this; // used in template
|
||||
$_tpl = include($this->_compile_dir . "/" . $file_name);
|
||||
/* @var Fenom\Render $_tpl */
|
||||
if (!($this->_options & self::AUTO_RELOAD) || ($this->_options & self::AUTO_RELOAD) && $_tpl->isValid()) {
|
||||
return $_tpl;
|
||||
}
|
||||
}
|
||||
return $this->compile($tpl, true, $opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate unique name of compiled template
|
||||
*
|
||||
* @param string $tpl
|
||||
* @param int $options
|
||||
* @return string
|
||||
*/
|
||||
private function _getCacheName($tpl, $options)
|
||||
{
|
||||
$hash = $tpl . ":" . $options;
|
||||
return sprintf("%s.%x.%x.php", str_replace(":", "_", basename($tpl)), crc32($hash), strlen($hash));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile and save template
|
||||
*
|
||||
* @param string $tpl
|
||||
* @param bool $store store template on disk
|
||||
* @param int $options
|
||||
* @throws RuntimeException
|
||||
* @return \Fenom\Template
|
||||
*/
|
||||
public function compile($tpl, $store = true, $options = 0)
|
||||
{
|
||||
$options = $this->_options | $options;
|
||||
$template = $this->getRawTemplate()->load($tpl);
|
||||
if ($store) {
|
||||
$cache = $this->_getCacheName($tpl, $options);
|
||||
$tpl_tmp = tempnam($this->_compile_dir, $cache);
|
||||
$tpl_fp = fopen($tpl_tmp, "w");
|
||||
if (!$tpl_fp) {
|
||||
throw new \RuntimeException("Can't to open temporary file $tpl_tmp. Directory " . $this->_compile_dir . " is writable?");
|
||||
}
|
||||
fwrite($tpl_fp, $template->getTemplateCode());
|
||||
fclose($tpl_fp);
|
||||
$file_name = $this->_compile_dir . "/" . $cache;
|
||||
if (!rename($tpl_tmp, $file_name)) {
|
||||
throw new \RuntimeException("Can't to move $tpl_tmp to $file_name");
|
||||
}
|
||||
}
|
||||
return $template;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -840,7 +768,25 @@ class Fenom
|
|||
*/
|
||||
public function clearAllCompiles()
|
||||
{
|
||||
\Fenom\Provider::clean($this->_compile_dir);
|
||||
$this->_provider->clearCompiles();
|
||||
foreach($this->_providers as $provider)
|
||||
{
|
||||
$provider->clearCompiles();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile and save template
|
||||
*
|
||||
* @param string $tpl
|
||||
* @param bool $store store template on disk
|
||||
* @param int $options
|
||||
* @throws \RuntimeException
|
||||
* @return \Fenom\Template
|
||||
*/
|
||||
public function compile($tpl, $store = true, $options = 0)
|
||||
{
|
||||
return $this->getProviderByTemplate($tpl)->compile($tpl, $store, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,62 +17,46 @@ use Fenom\ProviderInterface;
|
|||
*/
|
||||
class Provider implements ProviderInterface
|
||||
{
|
||||
/**
|
||||
* Templates source path
|
||||
* @var string
|
||||
*/
|
||||
private $_path;
|
||||
|
||||
/**
|
||||
* Clean directory from files
|
||||
*
|
||||
* @param string $path
|
||||
* Fenom engine object
|
||||
* @var \Fenom $_fenom
|
||||
*/
|
||||
public static function clean($path)
|
||||
{
|
||||
if (is_file($path)) {
|
||||
unlink($path);
|
||||
} elseif (is_dir($path)) {
|
||||
$iterator = iterator_to_array(
|
||||
new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator($path,
|
||||
\FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS),
|
||||
\RecursiveIteratorIterator::CHILD_FIRST
|
||||
)
|
||||
);
|
||||
foreach ($iterator as $file) {
|
||||
/* @var \splFileInfo $file */
|
||||
if ($file->isFile()) {
|
||||
if (strpos($file->getBasename(), ".") !== 0) {
|
||||
unlink($file->getRealPath());
|
||||
}
|
||||
} elseif ($file->isDir()) {
|
||||
rmdir($file->getRealPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private $_fenom;
|
||||
/**
|
||||
* Recursive remove directory
|
||||
*
|
||||
* @param string $path
|
||||
* Templates compile_dir
|
||||
* @var string compile directory
|
||||
*/
|
||||
public static function rm($path)
|
||||
{
|
||||
self::clean($path);
|
||||
if (is_dir($path)) {
|
||||
rmdir($path);
|
||||
}
|
||||
}
|
||||
protected $_compile_dir = "/tmp";
|
||||
|
||||
/**
|
||||
* @param string $template_dir directory of templates
|
||||
* @param string $compile_dir directory of compiled templates
|
||||
* @throws \LogicException if directory doesn't exists
|
||||
*/
|
||||
public function __construct($template_dir)
|
||||
public function __construct($template_dir, $compile_dir = null)
|
||||
{
|
||||
if ($_dir = realpath($template_dir)) {
|
||||
$this->_path = $_dir;
|
||||
} else {
|
||||
throw new \LogicException("Template directory {$template_dir} doesn't exists");
|
||||
}
|
||||
if(!is_null($compile_dir))
|
||||
{
|
||||
$this->setCompileDir($compile_dir);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Fenom $fenom
|
||||
*/
|
||||
public function setFenom(\Fenom $fenom)
|
||||
{
|
||||
$this->_fenom = $fenom;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -167,4 +151,113 @@ class Provider implements ProviderInterface
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set compile directory
|
||||
*
|
||||
* @param string $dir directory to store compiled templates in
|
||||
* @throws \LogicException
|
||||
* @return \Fenom
|
||||
*/
|
||||
public function setCompileDir($dir)
|
||||
{
|
||||
if (!is_writable($dir)) {
|
||||
throw new \LogicException("Cache directory $dir is not writable");
|
||||
}
|
||||
$this->_compile_dir = $dir;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate unique name of compiled template
|
||||
*
|
||||
* @param string $tpl
|
||||
* @param int $options
|
||||
* @return string
|
||||
*/
|
||||
private function _getCacheName($tpl, $options)
|
||||
{
|
||||
$hash = $tpl . ":" . $options;
|
||||
return sprintf("%s.%x.%x.php", str_replace(":", "_", basename($tpl)), crc32($hash), strlen($hash));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile and save template
|
||||
*
|
||||
* @param string $tpl
|
||||
* @param bool $store store template on disk
|
||||
* @param int $options
|
||||
* @throws \RuntimeException
|
||||
* @return \Fenom\Template
|
||||
*/
|
||||
public function compile($tpl, $store = true, $options = 0)
|
||||
{
|
||||
$options = $this->_fenom->getOptions() | $options;
|
||||
$template = $this->_fenom->getRawTemplate()->load($tpl);
|
||||
if ($store) {
|
||||
$cache = $this->_getCacheName($tpl, $options);
|
||||
$tpl_tmp = tempnam($this->_compile_dir, $cache);
|
||||
$tpl_fp = fopen($tpl_tmp, "w");
|
||||
if (!$tpl_fp) {
|
||||
throw new \RuntimeException("Can't to open temporary file $tpl_tmp. Directory " . $this->_compile_dir . " is writable?");
|
||||
}
|
||||
fwrite($tpl_fp, $template->getTemplateCode());
|
||||
fclose($tpl_fp);
|
||||
$file_name = $this->_compile_dir . "/" . $cache;
|
||||
if (!rename($tpl_tmp, $file_name)) {
|
||||
throw new \RuntimeException("Can't to move $tpl_tmp to $file_name");
|
||||
}
|
||||
}
|
||||
return $template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load template from cache or create cache if it doesn't exists.
|
||||
*
|
||||
* @param string $tpl
|
||||
* @param int $opts
|
||||
* @return \Fenom\Render
|
||||
*/
|
||||
public function load($tpl, $opts)
|
||||
{
|
||||
$file_name = $this->_getCacheName($tpl, $opts);
|
||||
if (is_file($this->_compile_dir . "/" . $file_name)) {
|
||||
$fenom = $this->_fenom; // used in template
|
||||
$_tpl = include($this->_compile_dir . "/" . $file_name);
|
||||
/* @var \Fenom\Render $_tpl */
|
||||
if (!($this->_fenom->getOptions() & \Fenom::AUTO_RELOAD) || ($this->_fenom->getOptions() & \Fenom::AUTO_RELOAD) && $_tpl->isValid()) {
|
||||
return $_tpl;
|
||||
}
|
||||
}
|
||||
return $this->compile($tpl, true, $opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear compiles cache
|
||||
*/
|
||||
public function clearCompiles()
|
||||
{
|
||||
if (is_file($this->_compile_dir)) {
|
||||
unlink($this->_compile_dir);
|
||||
} elseif (is_dir($this->_compile_dir)) {
|
||||
$iterator = iterator_to_array(
|
||||
new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator($this->_compile_dir,
|
||||
\FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS),
|
||||
\RecursiveIteratorIterator::CHILD_FIRST
|
||||
)
|
||||
);
|
||||
foreach ($iterator as $file) {
|
||||
/* @var \splFileInfo $file */
|
||||
if ($file->isFile()) {
|
||||
if (strpos($file->getBasename(), ".") !== 0) {
|
||||
unlink($file->getRealPath());
|
||||
}
|
||||
} elseif ($file->isDir()) {
|
||||
rmdir($file->getRealPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -48,4 +48,39 @@ interface ProviderInterface
|
|||
* @return array|\Iterator
|
||||
*/
|
||||
public function getList();
|
||||
|
||||
/**
|
||||
* Clear provider compiles
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function clearCompiles();
|
||||
|
||||
/**
|
||||
* Compile and save template
|
||||
*
|
||||
* @param string $tpl
|
||||
* @param bool $store store template on disk
|
||||
* @param int $options
|
||||
* @throws \RuntimeException
|
||||
* @return \Fenom\Template
|
||||
*/
|
||||
public function compile($tpl, $store = true, $options = 0);
|
||||
|
||||
/**
|
||||
* Load template from cache or create cache if it doesn't exists.
|
||||
*
|
||||
* @param string $tpl
|
||||
* @param int $opts
|
||||
* @return \Fenom\Render
|
||||
*/
|
||||
public function load($tpl, $opts);
|
||||
|
||||
/**
|
||||
* Set Fenom engine
|
||||
*
|
||||
* @param \Fenom $fenom
|
||||
* @return mixed
|
||||
*/
|
||||
public function setFenom(\Fenom $fenom);
|
||||
}
|
||||
|
|
|
@ -50,10 +50,11 @@ class TestCase extends \PHPUnit_Framework_TestCase
|
|||
if (!file_exists(FENOM_RESOURCES . '/compile')) {
|
||||
mkdir(FENOM_RESOURCES . '/compile', 0777, true);
|
||||
} else {
|
||||
FS::clean(FENOM_RESOURCES . '/compile/');
|
||||
// FS::clean(FENOM_RESOURCES . '/compile/');
|
||||
}
|
||||
|
||||
$this->fenom = Fenom::factory(FENOM_RESOURCES . '/template', FENOM_RESOURCES . '/compile');
|
||||
$this->fenom = new Fenom(new Provider(FENOM_RESOURCES . '/template', FENOM_RESOURCES . '/compile'));
|
||||
$this->fenom->getProvider()->clearCompiles();
|
||||
$this->fenom->addModifier('dots', __CLASS__ . '::dots');
|
||||
$this->fenom->addModifier('concat', __CLASS__ . '::concat');
|
||||
$this->fenom->addModifier('append', __CLASS__ . '::append');
|
||||
|
@ -92,7 +93,7 @@ class TestCase extends \PHPUnit_Framework_TestCase
|
|||
if (!file_exists(FENOM_RESOURCES . '/template')) {
|
||||
mkdir(FENOM_RESOURCES . '/template', 0777, true);
|
||||
} else {
|
||||
FS::clean(FENOM_RESOURCES . '/template/');
|
||||
// FS::clean(FENOM_RESOURCES . '/template/');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ class ExtendsTemplateTest extends TestCase
|
|||
|
||||
public function _testSandbox()
|
||||
{
|
||||
$this->fenom = Fenom::factory(FENOM_RESOURCES . '/provider', FENOM_RESOURCES . '/compile');
|
||||
$this->fenom = new Fenom(new Provider(FENOM_RESOURCES . '/provider', FENOM_RESOURCES . '/compile'));
|
||||
try {
|
||||
print_r($this->fenom->getTemplate('use/child.tpl')->getBody());
|
||||
} catch (\Exception $e) {
|
||||
|
@ -145,7 +145,7 @@ class ExtendsTemplateTest extends TestCase
|
|||
*/
|
||||
public function testUse()
|
||||
{
|
||||
$this->fenom = Fenom::factory(FENOM_RESOURCES . '/provider', FENOM_RESOURCES . '/compile');
|
||||
$this->fenom = new Fenom(new Provider(FENOM_RESOURCES . '/provider', FENOM_RESOURCES . '/compile'));
|
||||
$this->assertSame("<html>\n block 1 blocks \n block 2 child \n</html>", $this->fenom->fetch('use/child.tpl'));
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ class ProviderTest extends TestCase
|
|||
$this->tpl("template1.tpl", 'Template 1 {$a}');
|
||||
$this->tpl("template2.tpl", 'Template 2 {$a}');
|
||||
$this->tpl("sub/template3.tpl", 'Template 3 {$a}');
|
||||
$this->provider = new Provider(FENOM_RESOURCES . '/template');
|
||||
$this->provider = new Provider(FENOM_RESOURCES . '/template', FENOM_RESOURCES . '/compile');
|
||||
clearstatcache();
|
||||
}
|
||||
|
||||
|
@ -92,6 +92,7 @@ class ProviderTest extends TestCase
|
|||
$this->assertFalse($this->provider->verify($templates));
|
||||
}
|
||||
|
||||
/* @TODO: Why do we need that tests?
|
||||
public function testGetAll()
|
||||
{
|
||||
$list = $this->provider->getList();
|
||||
|
@ -113,6 +114,6 @@ class ProviderTest extends TestCase
|
|||
$this->assertTrue(is_file(FENOM_RESOURCES . '/template/template2.tpl'));
|
||||
Provider::clean(FENOM_RESOURCES . '/template/');
|
||||
$this->assertFalse(is_file(FENOM_RESOURCES . '/template/template2.tpl'));
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
|
|
|
@ -22,8 +22,7 @@ class FenomTest extends \Fenom\TestCase
|
|||
|
||||
public function testCreating() {
|
||||
$time = $this->tpl('temp.tpl', 'Template 1 a');
|
||||
$fenom = new Fenom($provider = new \Fenom\Provider(FENOM_RESOURCES . '/template'));
|
||||
$fenom->setCompileDir(FENOM_RESOURCES . '/compile');
|
||||
$fenom = new Fenom($provider = new \Fenom\Provider(FENOM_RESOURCES . '/template', FENOM_RESOURCES . '/compile'));
|
||||
$this->assertInstanceOf('Fenom\Template', $tpl = $fenom->getTemplate('temp.tpl'));
|
||||
$this->assertSame($provider, $tpl->getProvider());
|
||||
$this->assertSame('temp.tpl', $tpl->getBaseName());
|
||||
|
@ -34,7 +33,7 @@ class FenomTest extends \Fenom\TestCase
|
|||
|
||||
public function testFactory() {
|
||||
$time = $this->tpl('temp.tpl', 'Template 1 a');
|
||||
$fenom = Fenom::factory($provider = new \Fenom\Provider(FENOM_RESOURCES . '/template'), FENOM_RESOURCES . '/compile', Fenom::AUTO_ESCAPE);
|
||||
$fenom = Fenom::factory($provider = new \Fenom\Provider(FENOM_RESOURCES . '/template', FENOM_RESOURCES . '/compile'), Fenom::AUTO_ESCAPE);
|
||||
$this->assertInstanceOf('Fenom\Template', $tpl = $fenom->getTemplate('temp.tpl'));
|
||||
$this->assertSame($provider, $tpl->getProvider());
|
||||
$this->assertSame('temp.tpl', $tpl->getBaseName());
|
||||
|
|
Loading…
Reference in New Issue