diff --git a/Console/Command/AssetCompressShell.php b/Console/Command/AssetCompressShell.php index 608e5e97..c7659511 100644 --- a/Console/Command/AssetCompressShell.php +++ b/Console/Command/AssetCompressShell.php @@ -113,11 +113,25 @@ protected function _clearBuilds($ext) { $this->err('No ' . $ext . ' build files defined, skipping'); return; } + $this->_clearPath(TMP, $themes, $targets); + $path = $this->_Config->cachePath($ext); if (!file_exists($path)) { $this->err('Build directory ' . $path . ' for ' . $ext . ' does not exist.'); return; } + $this->_clearPath($path, $themes, $targets); + } + +/** + * Clear a path of build targets. + * + * @param string $path The path to clear. + * @param array $themes The themes to clear. + * @param array $targets The build targets to clear. + * @return void + */ + protected function _clearPath($path, $themes, $targets) { $dir = new DirectoryIterator($path); foreach ($dir as $file) { $name = $base = $file->getFilename(); diff --git a/Routing/Filter/AssetCompressor.php b/Routing/Filter/AssetCompressor.php index 73e5f6f2..ca66e17d 100644 --- a/Routing/Filter/AssetCompressor.php +++ b/Routing/Filter/AssetCompressor.php @@ -4,6 +4,7 @@ App::uses('AssetConfig', 'AssetCompress.Lib'); App::uses('AssetCompiler', 'AssetCompress.Lib'); App::uses('AssetCache', 'AssetCompress.Lib'); +App::uses('Folder', 'Utility'); class AssetCompressor extends DispatcherFilter { @@ -29,10 +30,12 @@ class AssetCompressor extends DispatcherFilter { * @return CakeResponse if the client is requesting a recognized asset, null otherwise */ public function beforeDispatch(CakeEvent $event) { - $url = $event->data['request']->url; - $Config = $this->_getConfig(); + $request = $event->data['request']; + $response = $event->data['response']; + $url = $request->url; + $config = $this->_getConfig(); $production = !Configure::read('debug'); - if ($production && !$Config->general('alwaysEnableController')) { + if ($production && !$config->general('alwaysEnableController')) { return; } @@ -41,37 +44,47 @@ public function beforeDispatch(CakeEvent $event) { return; } - if (isset($event->data['request']->query['theme'])) { - $Config->theme($event->data['request']->query['theme']); + if (isset($request->query['theme'])) { + $config->theme($event->data['request']->query['theme']); } // Dynamically defined build file. Disabled in production for // hopefully obvious reasons. - if ($Config->files($build) === array()) { + if ($config->files($build) === array()) { $files = array(); - if (isset($event->data['request']->query['file'])) { - $files = $event->data['request']->query['file']; + if (isset($request->query['file'])) { + $files = $request->query['file']; } - $Config->files($build, $files); + $config->files($build, $files); } + // Use the TMP dir for dev builds. + // This is to avoid permissions issues with the configured paths. + $cachePath = CACHE . 'asset_compress' . DS; + $folder = new Folder($cachePath, true); + $folder->chmod($cachePath, 0777); + + $ext = $config->getExt($build); + $config->cachePath($ext, $cachePath); + $config->set("$ext.timestamp", false); + try { - $Compiler = new AssetCompiler($Config); - $mtime = $Compiler->getLastModified($build); - $event->data['response']->modified($mtime); - if ($event->data['response']->checkNotModified($event->data['request'])) { - $event->stopPropagation(); - return $event->data['response']; + $compiler = new AssetCompiler($config); + $cache = new AssetCache($config); + if ($cache->isFresh($build)) { + $contents = file_get_contents($cachePath . $build); + } else { + $contents = $compiler->generate($build); + $cache->write($build, $contents); } - $contents = $Compiler->generate($build); } catch (Exception $e) { throw new NotFoundException($e->getMessage()); } - $event->data['response']->type($Config->getExt($build)); - $event->data['response']->body($contents); + $response->type($config->getExt($build)); + $response->body($contents); $event->stopPropagation(); - return $event->data['response']; + return $response; } /** diff --git a/Test/Case/Routing/Filter/AssetCompressorTest.php b/Test/Case/Routing/Filter/AssetCompressorTest.php index 5da8f9e3..ad9910cf 100644 --- a/Test/Case/Routing/Filter/AssetCompressorTest.php +++ b/Test/Case/Routing/Filter/AssetCompressorTest.php @@ -70,20 +70,39 @@ public function testPluginIniBuildFile() { $this->assertTrue($event->isStopped()); } - public function testDynamicBuildFileCheckNotModified() { - $this->response - ->expects($this->once())->method('checkNotModified') - ->with($this->request) - ->will($this->returnValue(true)); +/** + * test that predefined builds get cached to disk. + * + * @return void + */ + public function testBuildFileIsCached() { + $this->request->url = 'cache_js/libs.js'; + $data = array('request' => $this->request, 'response' => $this->response); + $event = new CakeEvent('Dispatcher.beforeDispatch', $this, $data); + $this->assertSame($this->response, $this->Compressor->beforeDispatch($event)); + $this->assertContains('BaseClass', $this->response->body()); + $this->assertTrue($event->isStopped()); + $this->assertTrue(file_exists(CACHE . 'asset_compress' . DS . 'libs.js'), 'Cache file was created.'); + unlink(CACHE . 'asset_compress' . DS . 'libs.js'); + } + +/** + * test that dynamic builds get cached to disk. + * + * @return void + */ + public function testDynamicBuildFileIsCached() { $this->request->url = 'cache_js/dynamic.js'; $this->request->query['file'] = array('library_file.js', 'lots_of_comments.js'); $data = array('request' => $this->request, 'response' => $this->response); $event = new CakeEvent('Dispatcher.beforeDispatch', $this, $data); $this->assertSame($this->response, $this->Compressor->beforeDispatch($event)); - $this->assertEquals('', $this->response->body()); + $this->assertNotEquals('', $this->response->body()); $this->assertTrue($event->isStopped()); + $this->assertTrue(file_exists(CACHE . 'asset_compress' . DS . 'dynamic.js'), 'Cache file was created.'); + unlink(CACHE . 'asset_compress' . DS . 'dynamic.js'); } /**