From 98f454bc8aa4285faa424a9b5e7d94aac61226e4 Mon Sep 17 00:00:00 2001
From: gwoo
Date: Sat, 22 Dec 2007 01:37:46 +0000
Subject: [PATCH] updating asset handling, closes #3149 To use compression for
css and js files in vendors use Configure::write('Asset.compress', true);
Also, closes #1897 serving css and js from plugin vendors folder for paths
within that plugin. Tests added.
git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6189 3807eeeb-6ff5-0310-8944-8be069107fe0
---
cake/dispatcher.php | 80 +++++++--
cake/libs/view/helpers/cache.php | 20 ++-
cake/libs/view/view.php | 1 -
cake/tests/cases/dispatcher.test.php | 73 ++++++++-
.../vendors/css/test_plugin_asset.css | 1 +
.../tests/test_app/vendors/css/test_asset.css | 1 +
.../views/posts/test_nocache_tags.ctp | 154 ++++++++++++++++++
7 files changed, 300 insertions(+), 30 deletions(-)
create mode 100644 cake/tests/test_app/plugins/test_plugin/vendors/css/test_plugin_asset.css
create mode 100644 cake/tests/test_app/vendors/css/test_asset.css
create mode 100644 cake/tests/test_app/views/posts/test_nocache_tags.ctp
diff --git a/cake/dispatcher.php b/cake/dispatcher.php
index 05a421ce6..3ead40f78 100644
--- a/cake/dispatcher.php
+++ b/cake/dispatcher.php
@@ -30,8 +30,7 @@
/**
* List of helpers to include
*/
-App::import('Core', 'Router');
-App::import('Core', 'Controller');
+App::import('Core', array('Router', 'Controller'));
/**
* Dispatcher translates URLs to controller-action-paramter triads.
*
@@ -125,7 +124,11 @@ class Dispatcher extends Object {
$url = $this->getUrl();
$this->here = $this->base . '/' . $url;
- $this->cached($url);
+
+ if ($this->cached($url) && Configure::read() < 1) {
+ exit();
+ }
+
$this->params = array_merge($this->parseParams($url), $additionalParams);
$controller = $this->__getController();
@@ -625,26 +628,66 @@ class Dispatcher extends Object {
exit();
}
- $folders = array('js' => 'text/javascript', 'css' => 'text/css');
- $requestPath = explode('/', $url);
-
- if (in_array($requestPath[0], array_keys($folders))) {
- if (file_exists(VENDORS . join(DS, $requestPath))) {
- $fileModified = filemtime(VENDORS . join(DS, $requestPath));
- header("Date: " . date("D, j M Y G:i:s ", $fileModified) . 'GMT');
- header('Content-type: ' . $folders[$requestPath[0]]);
- header("Expires: " . gmdate("D, j M Y H:i:s", time() + DAY) . " GMT");
- header("Cache-Control: cache");
- header("Pragma: cache");
- include (VENDORS . join(DS, $requestPath));
- exit();
+ $assets = array('js' => 'text/javascript', 'css' => 'text/css');
+ $isAsset = false;
+ foreach ($assets as $type => $contentType) {
+ if (strpos($url, $type . '/') !== false) {
+ $isAsset = true;
+ break;
}
}
+ if ($isAsset === true) {
+ $ob = @ini_get("zlib.output_compression") && extension_loaded("zlib") && (strpos(env('HTTP_ACCEPT_ENCODING'), 'gzip') !== false);
+
+ if ($ob && Configure::read('Asset.compress')) {
+ ob_start();
+ ob_start('ob_gzhandler');
+ }
+
+ $assetFile = null;
+ $paths = array();
+ $vendorPaths = Configure::read('vendorPaths');
+
+ if ($this->plugin !== null) {
+ $url = str_replace($this->plugin . '/', '', $url);
+ $pluginPaths = Configure::read('pluginPaths');
+ $count = count($pluginPaths);
+ for ($i = 0; $i < $count; $i++) {
+ $paths[] = $pluginPaths[$i] . $this->plugin . DS . 'vendors' . DS;
+ }
+ }
+
+ $paths = array_merge($paths, $vendorPaths);
+
+ foreach ($paths as $path) {
+ if (is_file($path . $url) && file_exists($path . $url)) {
+ $assetFile = $path . $url;
+ break;
+ }
+ }
+
+ if ($assetFile !== null) {
+ $fileModified = filemtime($assetFile);
+ header("Date: " . date("D, j M Y G:i:s ", $fileModified) . 'GMT');
+ header('Content-type: ' . $assets[$type]);
+ header("Expires: " . gmdate("D, j M Y H:i:s", time() + DAY) . " GMT");
+ header("Cache-Control: cache");
+ header("Pragma: cache");
+ include ($assetFile);
+
+ if(Configure::read('Asset.compress')) {
+ header("Content-length: " . ob_get_length());
+ ob_end_flush();
+ }
+ return true;
+ }
+ }
+
if (Configure::read('Cache.check') === true) {
- $filename = CACHE . 'views' . DS . convertSlash($this->here) . '.php';
+ $filename = CACHE . 'views' . DS . Inflector::slug($this->here) . '.php';
if (!file_exists($filename)) {
- $filename = CACHE . 'views' . DS . convertSlash($this->here) . '_index.php';
+ $filename = CACHE . 'views' . DS . Inflector::slug($this->here) . '_index.php';
}
if (file_exists($filename)) {
if (!class_exists('View')) {
@@ -654,6 +697,7 @@ class Dispatcher extends Object {
$controller = null;
$view = new View($controller);
$view->renderCache($filename, getMicrotime());
+ return true;
}
}
}
diff --git a/cake/libs/view/helpers/cache.php b/cake/libs/view/helpers/cache.php
index fae916a1d..a213505be 100644
--- a/cake/libs/view/helpers/cache.php
+++ b/cake/libs/view/helpers/cache.php
@@ -58,6 +58,14 @@ class CacheHelper extends AppHelper {
* @access public
*/
var $view;
+/**
+ * cache action time
+ *
+ * @var object
+ * @access public
+ */
+ var $cacheAction;
+
/**
* Main method used to cache a view
*
@@ -75,7 +83,7 @@ class CacheHelper extends AppHelper {
$match = str_replace('/' . $this->controllerName . '/', '', $match);
$check = str_replace($replace, '', $check);
$check = str_replace('_' . $this->controllerName . '_', '', $check);
- $check = convertSlash($check);
+ $check = Inflector::slug($check);
$check = preg_replace('/^_+/', '', $check);
$keys = str_replace('/', '_', array_keys($this->cacheAction));
$found = array_keys($this->cacheAction);
@@ -202,7 +210,7 @@ class CacheHelper extends AppHelper {
$cacheTime = strtotime($timestamp, $now);
}
- $cache = convertSlash($this->here);
+ $cache = Inflector::slug($this->here);
if (empty($cache)) {
return;
}
@@ -211,8 +219,8 @@ class CacheHelper extends AppHelper {
$file = 'plugin)) {
$file .= '
- loadController(\'' . $this->controllerName. '\');
- loadModels();
+ App::import(\'Controller\', \'' . $this->controllerName. '\');
+ App::import(\'Model\');
';
} else {
$file .= '
@@ -223,8 +231,8 @@ class CacheHelper extends AppHelper {
require(\''.CAKE . 'app_controller.php\');
}
}
- loadController(\'' . $this->plugin . '.' . $this->controllerName . '\');
- loadPluginModels(\''.$this->plugin.'\');
+ App::import(\'Controller\', \'' . $this->plugin . '.' . $this->controllerName. '\');
+ App::import(\'Model\', \''.$this->plugin.'\');
';
}
$file .= '$this->controller = new ' . $this->controllerName . 'Controller();
diff --git a/cake/libs/view/view.php b/cake/libs/view/view.php
index 90846314c..6064f45ad 100644
--- a/cake/libs/view/view.php
+++ b/cake/libs/view/view.php
@@ -486,7 +486,6 @@ class View extends Object {
}
$out = str_replace('', '', $out);
echo $out;
- die();
}
}
}
diff --git a/cake/tests/cases/dispatcher.test.php b/cake/tests/cases/dispatcher.test.php
index 5c312e198..68827828b 100644
--- a/cake/tests/cases/dispatcher.test.php
+++ b/cake/tests/cases/dispatcher.test.php
@@ -153,15 +153,17 @@ class TestCachedPagesController extends AppController {
var $helpers = array('Cache');
- var $cacheAction = array('index'=> '+2 sec', 'nocache'=>'+2 sec');
+ var $cacheAction = array('index'=> '+2 sec', 'test_nocache_tags'=>'+2 sec');
+
+ var $viewPath = 'posts';
function index() {
- $this->render(null, null, LIBS . 'view' . DS . 'templates' . DS . 'pages' . DS . 'home.ctp');
+ $this->render();
}
- function nocache() {
+ function test_nocache_tags() {
//$this->cacheAction = '+2 sec';
- $this->render(null, null, CAKE . 'tests' . DS . 'cases' . DS . 'libs' . DS . 'view' . DS . 'templates' . DS . 'nocache.ctp');
+ $this->render();
}
}
/**
@@ -179,7 +181,6 @@ class DispatcherTest extends UnitTestCase {
Configure::write('App.baseUrl', false);
Configure::write('App.dir', 'app');
Configure::write('App.webroot', 'webroot');
-
}
function testParseParamsWithoutZerosAndEmptyPost() {
@@ -750,6 +751,68 @@ class DispatcherTest extends UnitTestCase {
$this->assertIdentical($expected, $controller->params['pass']);
}
+ function testStaticAssets() {
+ $Dispatcher =& new TestDispatcher();
+
+ Configure::write('pluginPaths', array(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'plugins' . DS));
+ Configure::write('vendorPaths', array(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'vendors'. DS));
+
+ Configure::write('debug', 0);
+ restore_error_handler();
+ ob_start();
+ $Dispatcher->cached('css/test_asset.css');
+ $result = ob_get_clean();
+ set_error_handler('simpleTestErrorHandler');
+ $this->assertEqual('this is the test asset css file', $result);
+
+ Configure::write('debug', 0);
+ $Dispatcher->plugin = 'test_plugin';
+ restore_error_handler();
+ ob_start();
+ $Dispatcher->cached('/test_plugin/css/test_plugin_asset.css');
+ $result = ob_get_clean();
+ set_error_handler('simpleTestErrorHandler');
+ $this->assertEqual('this is the test plugin asset css file', $result);
+
+ }
+
+ function testFullPageCachingDispatch() {
+ Configure::write('Cache.check', true);
+ Configure::write('debug', 2);
+ $_POST = array();
+ $_SERVER['PHP_SELF'] = '/cake/repo/branches/1.2.x.x/index.php';
+
+ Router::reload();
+
+ Configure::write('viewPaths', array(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'views'. DS));
+
+ $dispatcher =& new Dispatcher();
+ $dispatcher->base = false;
+
+ $url = 'test_cached_pages/index';
+ restore_error_handler();
+
+ ob_start();
+ $out = $dispatcher->dispatch($url, array('return' => 1));
+ $out = ob_get_clean();
+
+ $controller = null;
+ $filename = CACHE . 'views' . DS . Inflector::slug($dispatcher->here) . '.php';
+ $view = new View($controller);
+ ob_start();
+ $view->renderCache($filename, getMicrotime());
+ $cached = ob_get_clean();
+
+ set_error_handler('simpleTestErrorHandler');
+
+ $result = str_replace(array("\t", "\r\n", "\n"), "", $out);
+ $cached = preg_replace('//', '', $cached);
+ $expected = str_replace(array("\t", "\r\n", "\n"), "", $cached);
+
+ $this->assertEqual($result, $expected);
+ unlink($filename);
+ }
+
function tearDown() {
$_GET = $this->_get;
}
diff --git a/cake/tests/test_app/plugins/test_plugin/vendors/css/test_plugin_asset.css b/cake/tests/test_app/plugins/test_plugin/vendors/css/test_plugin_asset.css
new file mode 100644
index 000000000..ac6fe0de6
--- /dev/null
+++ b/cake/tests/test_app/plugins/test_plugin/vendors/css/test_plugin_asset.css
@@ -0,0 +1 @@
+this is the test plugin asset css file
\ No newline at end of file
diff --git a/cake/tests/test_app/vendors/css/test_asset.css b/cake/tests/test_app/vendors/css/test_asset.css
new file mode 100644
index 000000000..e8b09dd29
--- /dev/null
+++ b/cake/tests/test_app/vendors/css/test_asset.css
@@ -0,0 +1 @@
+this is the test asset css file
\ No newline at end of file
diff --git a/cake/tests/test_app/views/posts/test_nocache_tags.ctp b/cake/tests/test_app/views/posts/test_nocache_tags.ctp
new file mode 100644
index 000000000..e24d8702b
--- /dev/null
+++ b/cake/tests/test_app/views/posts/test_nocache_tags.ctp
@@ -0,0 +1,154 @@
+
+ * Copyright 2005-2007, Cake Software Foundation, Inc.
+ * 1785 E. Sahara Avenue, Suite 490-204
+ * Las Vegas, Nevada 89104
+ *
+ * Licensed under The MIT License
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @filesource
+ * @copyright Copyright 2005-2007, Cake Software Foundation, Inc.
+ * @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
+ * @package cake
+ * @subpackage cake.cake.libs.view.templates.pages
+ * @since CakePHP(tm) v 0.10.0.1076
+ * @version $Revision$
+ * @modifiedby $LastChangedBy$
+ * @lastmodified $Date$
+ * @license http://www.opensource.org/licenses/mit-license.php The MIT License
+ */
+?>
+ 0):
+ Debugger::checkSessionKey();
+endif;
+?>
+
+
+
+
+
+
+
+
+
+ ' . $settings['class'];
+ __(' is being used to cache, to change this edit config/core.php ');
+ echo '
';
+
+ echo 'Settings: ';
+ foreach ($settings as $name => $value):
+ echo '- ' . $name . ': ' . $value . '
';
+ endforeach;
+ echo '
';
+
+ else:
+ __('NOT working.');
+ echo '
';
+ if (is_writable(TMP)):
+ __('Edit: config/core.php to insure you have the newset version of this file and the variable $cakeCache set properly');
+ endif;
+ endif;
+ ?>
+
+
+
+
+ ';
+ __('Rename config/database.php.default to config/database.php');
+ endif;
+ ?>
+
+
+getDataSource('default');
+?>
+
+
+ isConnected()):
+ __(' is able to ');
+ else:
+ __(' is NOT able to ');
+ endif;
+ __('connect to the database.');
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file