From 617fc7324cd63c89c43e51c20e7332e7b73568c1 Mon Sep 17 00:00:00 2001 From: bzick Date: Sat, 13 Jul 2013 12:00:19 +0400 Subject: [PATCH] Improve providers. Renders now use bulk checks via ::verify --- src/Fenom.php | 2 +- src/Fenom/Provider.php | 44 ++++++++++++++++--------- src/Fenom/ProviderInterface.php | 12 ++++--- src/Fenom/Render.php | 20 ++++++----- tests/TestCase.php | 4 +++ tests/cases/Fenom/ProviderTest.php | 53 +++++++++++++++++++++++------- 6 files changed, 93 insertions(+), 42 deletions(-) diff --git a/src/Fenom.php b/src/Fenom.php index 55f09ed..e1da263 100644 --- a/src/Fenom.php +++ b/src/Fenom.php @@ -246,6 +246,7 @@ class Fenom { throw new InvalidArgumentException("Source must be a valid path or provider object"); } $fenom = new static($provider); + /* @var Fenom $fenom */ $fenom->setCompileDir($compile_dir); if($options) { $fenom->setOptions($options); @@ -595,7 +596,6 @@ class Fenom { * @param $callback * @param float $chunk * @return \Fenom\Render - * @example $fenom->pipe("products.yml.tpl", $iterators, [new SplFileObject("/tmp/products.yml"), "fwrite"], 512*1024) */ public function pipe($template, array $vars, $callback, $chunk = 1e6) { ob_start($callback, $chunk, true); diff --git a/src/Fenom/Provider.php b/src/Fenom/Provider.php index f99e158..dc3812a 100644 --- a/src/Fenom/Provider.php +++ b/src/Fenom/Provider.php @@ -71,9 +71,9 @@ class Provider implements ProviderInterface { } /** - * + * Get source and mtime of template by name * @param string $tpl - * @param int $time + * @param int $time load last modified time * @return string */ public function getSource($tpl, &$time) { @@ -83,13 +83,37 @@ class Provider implements ProviderInterface { return file_get_contents($tpl); } + /** + * Get last modified of template by name + * @param string $tpl + * @return int + */ public function getLastModified($tpl) { clearstatcache(null, $tpl = $this->_getTemplatePath($tpl)); return filemtime($tpl); } - public function getList() { - + /** + * Get all names of templates from provider. + * + * @param string $extension all templates must have this extension, default .tpl + * @return array|\Iterator + */ + public function getList($extension = "tpl") { + $list = array(); + $iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($this->_path, + \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS), + \RecursiveIteratorIterator::CHILD_FIRST + ); + $path_len = strlen($this->_path); + foreach($iterator as $file) { + /* @var \SplFileInfo $file */ + if($file->isFile() && $file->getExtension() == $extension) { + $list[] = substr($file->getPathname(), $path_len + 1); + } + } + return $list; } /** @@ -114,18 +138,6 @@ class Provider implements ProviderInterface { return file_exists($this->_path."/".$tpl); } - /** - * @param array $tpls - * @return array - */ - public function getLastModifiedBatch($tpls) { - $tpls = array_flip($tpls); - foreach($tpls as $tpl => &$time) { - $time = $this->getLastModified($tpl); - } - return $tpls; - } - /** * Verify templates (check change time) * diff --git a/src/Fenom/ProviderInterface.php b/src/Fenom/ProviderInterface.php index a8f2978..b770c62 100644 --- a/src/Fenom/ProviderInterface.php +++ b/src/Fenom/ProviderInterface.php @@ -10,7 +10,7 @@ namespace Fenom; /** - * Template provider interface + * Interface of templates provider * @package Fenom * @author Ivan Shalganov */ @@ -20,6 +20,7 @@ interface ProviderInterface { * @return bool */ public function templateExists($tpl); + /** * @param string $tpl * @param int $time @@ -34,15 +35,16 @@ interface ProviderInterface { public function getLastModified($tpl); /** - * Verify templates by change time + * Verify templates (check mtime) * - * @param array $templates [template_name => modified, ...] By conversation you may trust the template's name - * @return bool + * @param array $templates [template_name => modified, ...] By conversation, you may trust the template's name + * @return bool if true - all templates are valid else some templates are invalid */ public function verify(array $templates); /** - * @return array + * Get all names of template from provider + * @return array|\Iterator */ public function getList(); } diff --git a/src/Fenom/Render.php b/src/Fenom/Render.php index 903faef..d053a88 100644 --- a/src/Fenom/Render.php +++ b/src/Fenom/Render.php @@ -76,7 +76,7 @@ class Render extends \ArrayObject { $this->_fenom = $fenom; $props += self::$_props; $this->_name = $props["name"]; - $this->_provider = $this->_fenom->getProvider($props["scm"]); +// $this->_provider = $this->_fenom->getProvider($props["scm"]); $this->_scm = $props["scm"]; $this->_time = $props["time"]; $this->_depends = $props["depends"]; @@ -100,7 +100,7 @@ class Render extends \ArrayObject { } public function getProvider() { - return $this->_provider; + return $this->_fenom->getProvider($this->_scm); } public function getBaseName() { @@ -136,14 +136,18 @@ class Render extends \ArrayObject { * @return bool */ public function isValid() { - $provider = $this->_fenom->getProvider(strstr($this->_name, ":"), true); - if($provider->getLastModified($this->_name) >= $this->_time) { - return false; - } - foreach($this->_depends as $tpl => $time) { - if($this->_fenom->getTemplate($tpl)->getTime() !== $time) { + if(count($this->_depends) === 1) { // if no external dependencies, only self + $provider = $this->_fenom->getProvider($this->_scm); + if($provider->getLastModified($this->_name) !== $this->_time) { return false; } + } else { + foreach($this->_depends as $scm => $templates) { + $provider = $this->_fenom->getProvider($scm); + if(!$provider->verify($templates)) { + return false; + } + } } return true; } diff --git a/tests/TestCase.php b/tests/TestCase.php index aeabfdb..d2da880 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -55,6 +55,10 @@ class TestCase extends \PHPUnit_Framework_TestCase { } public function tpl($name, $code) { + $dir = dirname($name); + if($dir != "." && !is_dir(FENOM_RESOURCES.'/template/'.$dir)) { + mkdir(FENOM_RESOURCES.'/template/'.$dir, 0777, true); + } file_put_contents(FENOM_RESOURCES.'/template/'.$name, $code); } diff --git a/tests/cases/Fenom/ProviderTest.php b/tests/cases/Fenom/ProviderTest.php index fcd336a..d416adc 100644 --- a/tests/cases/Fenom/ProviderTest.php +++ b/tests/cases/Fenom/ProviderTest.php @@ -1,8 +1,9 @@ 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'); + clearstatcache(); } public function testIsTemplateExists() { + clearstatcache(); $this->assertTrue($this->provider->templateExists("template1.tpl")); $this->assertFalse($this->provider->templateExists("unexists.tpl")); } public function testGetSource() { + clearstatcache(); $src = $this->provider->getSource("template1.tpl", $time); clearstatcache(); $this->assertEquals(file_get_contents(FENOM_RESOURCES.'/template/template1.tpl'), $src); @@ -47,21 +52,45 @@ class FSProviderTest extends \Fenom\TestCase { $this->provider->getLastModified("unexists.tpl"); } - public function testGetLastModifiedBatch() { - $times = $this->provider->getLastModifiedBatch($tpls = array("template1.tpl", "template2.tpl")); - $this->assertSame($tpls, array_keys($times)); + public function testVerify() { + $templates = array( + "template1.tpl" => filemtime(FENOM_RESOURCES.'/template/template1.tpl'), + "template2.tpl" => filemtime(FENOM_RESOURCES.'/template/template2.tpl') + ); clearstatcache(); - foreach($times as $template => $time) { - $this->assertEquals(filemtime(FENOM_RESOURCES."/template/$template"), $time); - } + $this->assertTrue($this->provider->verify($templates)); + clearstatcache(); + $templates = array( + "template2.tpl" => filemtime(FENOM_RESOURCES.'/template/template2.tpl'), + "template1.tpl" => filemtime(FENOM_RESOURCES.'/template/template1.tpl') + ); + clearstatcache(); + $this->assertTrue($this->provider->verify($templates)); } - /** - * @expectedException \RuntimeException - */ - public function testGetLastModifiedBatchInvalid() { - $this->provider->getLastModifiedBatch(array("template1.tpl", "unexists.tpl", "parent.tpl")); + public function testVerifyInvalid() { + $templates = array( + "template1.tpl" => filemtime(FENOM_RESOURCES.'/template/template1.tpl'), + "template2.tpl" => filemtime(FENOM_RESOURCES.'/template/template2.tpl') + 1 + ); + clearstatcache(); + $this->assertFalse($this->provider->verify($templates)); + clearstatcache(); + $templates = array( + "template1.tpl" => filemtime(FENOM_RESOURCES.'/template/template1.tpl'), + "unexists.tpl" => 1234567890 + ); + $this->assertFalse($this->provider->verify($templates)); + } + public function testGetAll() { + $list = $this->provider->getList(); + sort($list); + $this->assertSame(array( + "sub/template3.tpl", + "template1.tpl", + "template2.tpl" + ), $list); } }