diff --git a/cake/libs/view/helpers/html.php b/cake/libs/view/helpers/html.php
index 5347bd73c..d99156197 100644
--- a/cake/libs/view/helpers/html.php
+++ b/cake/libs/view/helpers/html.php
@@ -134,16 +134,23 @@ class HtmlHelper extends AppHelper {
* Breadcrumbs.
*
* @var array
- * @access private
+ * @access protected
*/
var $_crumbs = array();
/**
* Names of script files that have been included once
*
* @var array
- * @access public
+ * @access private
**/
var $__includedScripts = array();
+/**
+ * Options for the currently opened script block buffer if any.
+ *
+ * @var array
+ * @access protected
+ **/
+ var $_scriptBlockOptions = array();
/**
* Document type definitions
*
@@ -362,7 +369,11 @@ class HtmlHelper extends AppHelper {
$path = $this->webroot($path);
$url = $path;
- if (strpos($path, '?') === false && ((Configure::read('Asset.timestamp') === true && Configure::read() > 0) || Configure::read('Asset.timestamp') === 'force')) {
+ $timestampEnabled = (
+ (Configure::read('Asset.timestamp') === true && Configure::read() > 0) ||
+ Configure::read('Asset.timestamp') === 'force'
+ );
+ if (strpos($path, '?') === false && $timestampEnabled) {
$url .= '?' . @filemtime(WWW_ROOT . str_replace('/', DS, $path));
}
@@ -416,7 +427,7 @@ class HtmlHelper extends AppHelper {
}
if ($once && isset($this->__includedScripts[$url])) {
- return null;
+ return null;
}
$this->__includedScripts[$url] = true;
@@ -425,7 +436,6 @@ class HtmlHelper extends AppHelper {
$url = JS_URL . $url;
}
$url = $this->webroot($url);
-
if (strpos($url, '?') === false) {
if (strpos($url, '.js') === false) {
$url .= '.js';
@@ -433,7 +443,7 @@ class HtmlHelper extends AppHelper {
}
$timestampEnabled = (
- (Configure::read('Asset.timestamp') === true && Configure::read() > 0) ||
+ (Configure::read('Asset.timestamp') === true && Configure::read('debug') > 0) ||
Configure::read('Asset.timestamp') === 'force'
);
@@ -475,6 +485,39 @@ class HtmlHelper extends AppHelper {
return null;
}
}
+/**
+ * Begin a script block that captures output until HtmlHelper::scriptEnd()
+ * is called. This capturing block will capture all output between the methods
+ * and create a scriptBlock from it.
+ *
+ * ### Options
+ *
+ * - `safe` Whether the code block should contain a CDATA
+ * - `inline` Should the generated script tag be output inline or in `$scripts_for_layout`
+ *
+ * @param array $options Options for the code block.
+ * @return void
+ **/
+ function scriptStart($options = array()) {
+ $defaultOptions = array('safe' => true, 'inline' => true);
+ $options = array_merge($defaultOptions, $options);
+ $this->_scriptBlockOptions = $options;
+ ob_start();
+ return null;
+ }
+/**
+ * End a Buffered section of Javascript capturing.
+ * Generates a script tag inline or in `$scripts_for_layout` depending on the settings
+ * used when the scriptblock was started
+ *
+ * @return mixed depending on the settings of scriptStart() either a script tag or null
+ **/
+ function scriptEnd() {
+ $buffer = ob_get_clean();
+ $options = $this->_scriptBlockOptions;
+ $this->_scriptBlockOptions = array();
+ return $this->scriptBlock($buffer, $options);
+ }
/**
* Builds CSS style data from an array of CSS properties
*
@@ -538,7 +581,6 @@ class HtmlHelper extends AppHelper {
$path = $this->webroot($path);
} elseif (strpos($path, '://') === false) {
$path = $this->webroot(IMAGES_URL . $path);
-
if ((Configure::read('Asset.timestamp') == true && Configure::read() > 0) || Configure::read('Asset.timestamp') === 'force') {
$path .= '?' . @filemtime(str_replace('/', DS, WWW_ROOT . $path));
}
diff --git a/cake/tests/cases/libs/view/helpers/html.test.php b/cake/tests/cases/libs/view/helpers/html.test.php
index 92cef1f4e..ac43bb45c 100644
--- a/cake/tests/cases/libs/view/helpers/html.test.php
+++ b/cake/tests/cases/libs/view/helpers/html.test.php
@@ -250,7 +250,7 @@ class HtmlHelperTest extends CakeTestCase {
);
$this->assertTags($result, $expected);
- Configure::write('Asset.timestamp', true);
+ Configure::write('Asset.timestamp', 'force');
$result = $this->Html->link($this->Html->image('test.gif'), '#', array(), false, false, false);
$expected = array(
@@ -289,7 +289,7 @@ class HtmlHelperTest extends CakeTestCase {
$result = $this->Html->image('/test/view/1.gif');
$this->assertTags($result, array('img' => array('src' => '/test/view/1.gif', 'alt' => '')));
- Configure::write('Asset.timestamp', true);
+ Configure::write('Asset.timestamp', 'force');
$result = $this->Html->image('cake.icon.gif');
$this->assertTags($result, array('img' => array('src' => 'preg:/img\/cake\.icon\.gif\?\d+/', 'alt' => '')));
@@ -370,6 +370,7 @@ class HtmlHelperTest extends CakeTestCase {
$result = $this->Html->css('cake.generic');
$expected['link']['href'] = 'preg:/.*ccss\/cake\.generic\.css/';
$this->assertTags($result, $expected);
+
Configure::write('Asset.filter.css', false);
$result = explode("\n", trim($this->Html->css(array('cake.generic', 'vendor.generic'))));
@@ -378,7 +379,8 @@ class HtmlHelperTest extends CakeTestCase {
$expected['link']['href'] = 'preg:/.*css\/vendor\.generic\.css/';
$this->assertTags($result[1], $expected);
$this->assertEqual(count($result), 2);
-
+
+ Configure::write('debug', 2);
Configure::write('Asset.timestamp', true);
Configure::write('Asset.filter.css', 'css.php');
@@ -423,10 +425,13 @@ class HtmlHelperTest extends CakeTestCase {
* @return void
**/
function testScriptTimestamping() {
- if ($this->skipIf(!is_writable(JS), 'webroot/js is not Writable, timestamp testing has been skipped')) {
+ $skip = $this->skipIf(!is_writable(JS), 'webroot/js is not Writable, timestamp testing has been skipped');
+ if ($skip) {
return;
}
+ Configure::write('debug', 2);
Configure::write('Asset.timestamp', true);
+
touch(WWW_ROOT . 'js' . DS. '__cake_js_test.js');
$timestamp = substr(strtotime('now'), 0, 8);
@@ -434,15 +439,10 @@ class HtmlHelperTest extends CakeTestCase {
$this->assertPattern('/__cake_js_test.js\?' . $timestamp . '[0-9]{2}"/', $result, 'Timestamp value not found %s');
Configure::write('debug', 0);
- $result = $this->Html->script('__cake_js_test', true, false);
- $this->assertPattern('/__cake_js_test.js"/', $result);
-
Configure::write('Asset.timestamp', 'force');
$result = $this->Html->script('__cake_js_test', true, false);
$this->assertPattern('/__cake_js_test.js\?' . $timestamp . '[0-9]{2}"/', $result, 'Timestamp value not found %s');
-
unlink(WWW_ROOT . 'js' . DS. '__cake_js_test.js');
- Configure::write('debug', 2);
Configure::write('Asset.timestamp', false);
}
/**
@@ -529,6 +529,52 @@ class HtmlHelperTest extends CakeTestCase {
$result = $this->Html->scriptBlock('window.foo = 2;', array('inline' => false));
$this->assertNull($result);
}
+/**
+ * test script tag output buffering when using scriptStart() and scriptEnd();
+ *
+ * @return void
+ **/
+ function testScriptStartAndScriptEnd() {
+ $result = $this->Html->scriptStart(array('safe' => true));
+ $this->assertNull($result);
+ echo 'this is some javascript';
+
+ $result = $this->Html->scriptEnd();
+ $expected = array(
+ 'script' => array('type' => 'text/javascript'),
+ $this->cDataStart,
+ 'this is some javascript',
+ $this->cDataEnd,
+ '/script'
+ );
+ $this->assertTags($result, $expected);
+
+
+ $result = $this->Html->scriptStart(array('safe' => false));
+ $this->assertNull($result);
+ echo 'this is some javascript';
+
+ $result = $this->Html->scriptEnd();
+ $expected = array(
+ 'script' => array('type' => 'text/javascript'),
+ 'this is some javascript',
+ '/script'
+ );
+ $this->assertTags($result, $expected);
+
+ ClassRegistry::removeObject('view');
+ $View =& new HtmlHelperMockView();
+
+ $View->expectOnce('addScript');
+ ClassRegistry::addObject('view', $View);
+
+ $result = $this->Html->scriptStart(array('safe' => false, 'inline' => false));
+ $this->assertNull($result);
+ echo 'this is some javascript';
+
+ $result = $this->Html->scriptEnd();
+ $this->assertNull($result);
+ }
/**
* testCharsetTag method
*