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
This commit is contained in:
gwoo 2007-12-22 01:37:46 +00:00
parent 5e7f3a8287
commit 98f454bc8a
7 changed files with 300 additions and 30 deletions

View file

@ -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);
$assets = array('js' => 'text/javascript', 'css' => 'text/css');
$isAsset = false;
foreach ($assets as $type => $contentType) {
if (strpos($url, $type . '/') !== false) {
$isAsset = true;
break;
}
}
if (in_array($requestPath[0], array_keys($folders))) {
if (file_exists(VENDORS . join(DS, $requestPath))) {
$fileModified = filemtime(VENDORS . join(DS, $requestPath));
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: ' . $folders[$requestPath[0]]);
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 (VENDORS . join(DS, $requestPath));
exit();
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;
}
}
}

View file

@ -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 = '<!--cachetime:' . $cacheTime . '--><?php';
if (empty($this->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();

View file

@ -486,7 +486,6 @@ class View extends Object {
}
$out = str_replace('<!--cachetime:'.$match['1'].'-->', '', $out);
echo $out;
die();
}
}
}

View file

@ -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;
}

View file

@ -0,0 +1 @@
this is the test plugin asset css file

View file

@ -0,0 +1 @@
this is the test asset css file

View file

@ -0,0 +1,154 @@
<?php
/* SVN FILE: $Id$ */
/**
*
* PHP versions 4 and 5
*
* CakePHP(tm) : Rapid Development Framework <http://www.cakephp.org/>
* 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
*/
?>
<?php
if(Configure::read() > 0):
Debugger::checkSessionKey();
endif;
?>
<p>
<cake:nocache>
<span class="notice">
<?php
__('Your tmp directory is ');
if (is_writable(TMP)):
__('writable.');
else:
__('NOT writable.');
endif;
?>
</span>
</cake:nocache>
</p>
<p>
<span class="notice">
<?php
__('Your cache is ');
if (Cache::isInitialized()):
__('set up and initialized properly.');
$settings = Cache::settings();
echo '<p>' . $settings['class'];
__(' is being used to cache, to change this edit config/core.php ');
echo '</p>';
echo 'Settings: <ul>';
foreach ($settings as $name => $value):
echo '<li>' . $name . ': ' . $value . '</li>';
endforeach;
echo '</ul>';
else:
__('NOT working.');
echo '<br />';
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;
?>
</span>
</p>
<p>
<span class="notice">
<?php
__('Your database configuration file is ');
$filePresent = null;
if (file_exists(CONFIGS.'database.php')):
__('present.');
$filePresent = true;
else:
__('NOT present.');
echo '<br/>';
__('Rename config/database.php.default to config/database.php');
endif;
?>
</span>
</p>
<?php
if (!empty($filePresent)):
uses('model' . DS . 'connection_manager');
$db = ConnectionManager::getInstance();
$connected = $db->getDataSource('default');
?>
<p>
<span class="notice">
<?php
__('Cake');
if ($connected->isConnected()):
__(' is able to ');
else:
__(' is NOT able to ');
endif;
__('connect to the database.');
?>
</span>
</p>
<?php endif; ?>
<h2><?php echo sprintf(__('Release Notes for CakePHP %s.', true), Configure::version()); ?></h2>
<a href="https://trac.cakephp.org/wiki/notes/1.2.x.x"><?php __('Read the release notes and get the latest version'); ?> </a>
<h2><?php __('Editing this Page'); ?></h2>
<p>
<?php __('To change the content of this page, create: /app/views/pages/home.ctp.'); ?><br />
<?php __('To change its layout, create: /app/views/layouts/default.ctp.'); ?><br />
<a href="http://manual.cakephp.org/"><?php __('See the views section of the manual for more info.'); ?> </a><br />
<?php __('You can also add some CSS styles for your pages at: app/webroot/css/.'); ?>
</p>
<h2><?php __('Getting Started'); ?></h2>
<p>
<a href="http://manual.cakephp.org/appendix/blog_tutorial"><?php __('The 15 min Blog Tutorial'); ?></a><br />
<a href="http://www-128.ibm.com/developerworks/edu/os-dw-os-php-cake1.html"><?php __('Cook up Web sites fast with CakePHP'); ?></a><br />
<a href="http://www-128.ibm.com/developerworks/edu/os-dw-os-php-wiki1.html"><?php __('Create an interactive production wiki using PHP'); ?></a>
</p>
<h2><?php __('More about Cake'); ?></h2>
<p>
<?php __('CakePHP is a rapid development framework for PHP which uses commonly known design patterns like Active Record, Association Data Mapping, Front Controller and MVC.'); ?>
</p>
<p>
<?php __('Our primary goal is to provide a structured framework that enables PHP users at all levels to rapidly develop robust web applications, without any loss to flexibility.'); ?>
</p>
<ul>
<li><a href="http://www.cakefoundation.org/"><?php __('Cake Software Foundation'); ?> </a>
<ul><li><?php __('Promoting development related to CakePHP'); ?></li></ul></li>
<li><a href="http://bakery.cakephp.org"><?php __('The Bakery'); ?> </a>
<ul><li><?php __('Everything CakePHP'); ?></li></ul></li>
<li><a href="http://astore.amazon.com/cakesoftwaref-20/"><?php __('Book Store'); ?> </a>
<ul><li><?php __('Recommended Software Books'); ?></li></ul></li>
<li><a href="http://www.cafepress.com/cakefoundation"><?php __('CakeSchwag'); ?> </a>
<ul><li><?php __('Get your own CakePHP gear - Doughnate to Cake'); ?></li></ul></li>
<li><a href="http://www.cakephp.org"><?php __('CakePHP'); ?> </a>
<ul><li><?php __('The Rapid Development Framework'); ?></li></ul></li>
<li><a href="http://manual.cakephp.org"><?php __('CakePHP Manual'); ?> </a>
<ul><li><?php __('Your Rapid Development Cookbook'); ?></li></ul></li>
<li><a href="http://api.cakephp.org"><?php __('CakePHP API'); ?> </a>
<ul><li><?php __('Docblock Your Best Friend'); ?></li></ul></li>
<li><a href="http://www.cakeforge.org"><?php __('CakeForge'); ?> </a>
<ul><li><?php __('Open Development for CakePHP'); ?></li></ul></li>
<li><a href="https://trac.cakephp.org/"><?php __('CakePHP Trac'); ?> </a>
<ul><li><?php __('For the Development of CakePHP (Tickets, SVN browser, Roadmap, Changelogs)'); ?></li></ul></li>
<li><a href="http://groups-beta.google.com/group/cake-php"><?php __('CakePHP Google Group'); ?> </a>
<ul><li><?php __('Community mailing list'); ?></li></ul></li>
<li><a href="irc://irc.freenode.net/cakephp">irc.freenode.net #cakephp</a>
<ul><li><?php __('Live chat about CakePHP'); ?></li></ul></li>
</ul>