diff --git a/lib/Cake/Test/Case/View/Helper/HtmlHelperTest.php b/lib/Cake/Test/Case/View/Helper/HtmlHelperTest.php index 47481480c..7949ca9a5 100644 --- a/lib/Cake/Test/Case/View/Helper/HtmlHelperTest.php +++ b/lib/Cake/Test/Case/View/Helper/HtmlHelperTest.php @@ -655,11 +655,34 @@ class HtmlHelperTest extends CakeTestCase { ); $this->assertTags($result, $expected); - $this->View->expects($this->any()) + } + +/** + * test that script() works with blocks. + * + * @return void + */ + public function testScriptWithBlocks() { + $this->View->expects($this->at(0)) ->method('append') ->with('script', $this->matchesRegularExpression('/script_in_head.js/')); + + $this->View->expects($this->at(1)) + ->method('append') + ->with('script', $this->matchesRegularExpression('/bool_false.js/')); + + $this->View->expects($this->at(2)) + ->method('append') + ->with('headScripts', $this->matchesRegularExpression('/second_script.js/')); + $result = $this->Html->script('script_in_head', array('inline' => false)); $this->assertNull($result); + + $result = $this->Html->script('bool_false', false); + $this->assertNull($result); + + $result = $this->Html->script('second_script', array('block' => 'headScripts')); + $this->assertNull($result); } /** @@ -1249,12 +1272,25 @@ class HtmlHelperTest extends CakeTestCase { $this->assertTags($result, array('meta' => array('name' => 'ROBOTS', 'content' => 'ALL'))); - $this->View->expects($this->any()) + } + +/** + * Test the inline and block options for meta() + */ + public function testMetaWithBlocks() { + $this->View->expects($this->at(0)) ->method('append') - ->with('meta', $this->matchesRegularExpression('/^with('meta', $this->stringContains('ROBOTS')); + + $this->View->expects($this->at(1)) + ->method('append') + ->with('metaTags', $this->stringContains('favicon.ico')); $result = $this->Html->meta(array('name' => 'ROBOTS', 'content' => 'ALL'), null, array('inline' => false)); $this->assertNull($result); + + $result = $this->Html->meta('icon', 'favicon.ico', array('block' => 'metaTags')); + $this->assertNull($result); } /** diff --git a/lib/Cake/View/Helper/HtmlHelper.php b/lib/Cake/View/Helper/HtmlHelper.php index 691b49811..acc3b9921 100644 --- a/lib/Cake/View/Helper/HtmlHelper.php +++ b/lib/Cake/View/Helper/HtmlHelper.php @@ -218,9 +218,24 @@ class HtmlHelper extends AppHelper { /** * Creates a link to an external resource and handles basic meta tags * + * Create a meta tag that is output inline: + * + * `$this->Html->meta('icon', 'favicon.ico'); + * + * Append the meta tag to `$scripts_for_layout`: + * + * `$this->Html->meta('description', 'A great page', array('inline' => false));` + * + * Append the meta tag to custom view block: + * + * `$this->Html->meta('description', 'A great page', array('block' => 'metaTags'));` + * * ### Options * - * - `inline` Whether or not the link element should be output inline, or in scripts_for_layout. + * - `inline` Whether or not the link element should be output inline. Set to false to + * have the meta tag included in `$scripts_for_layout`, and appended to the 'meta' view block. + * - `block` Choose a custom block to append the meta tag to. Using this option + * will override the inline option. * * @param string $type The title of the external resource * @param mixed $url The address of the external resource or string for content attribute @@ -230,7 +245,10 @@ class HtmlHelper extends AppHelper { * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::meta */ public function meta($type, $url = null, $options = array()) { - $inline = isset($options['inline']) ? $options['inline'] : true; + $options += array('inline' => true, 'block' => null); + if (!$options['inline'] && empty($options['block'])) { + $options['block'] = __FUNCTION__; + } unset($options['inline']); if (!is_array($type)) { @@ -268,20 +286,20 @@ class HtmlHelper extends AppHelper { if (isset($options['link'])) { if (isset($options['rel']) && $options['rel'] === 'icon') { - $out = sprintf($this->_tags['metalink'], $options['link'], $this->_parseAttributes($options, array('link'), ' ', ' ')); + $out = sprintf($this->_tags['metalink'], $options['link'], $this->_parseAttributes($options, array('block', 'link'), ' ', ' ')); $options['rel'] = 'shortcut icon'; } else { $options['link'] = $this->url($options['link'], true); } - $out .= sprintf($this->_tags['metalink'], $options['link'], $this->_parseAttributes($options, array('link'), ' ', ' ')); + $out .= sprintf($this->_tags['metalink'], $options['link'], $this->_parseAttributes($options, array('block', 'link'), ' ', ' ')); } else { - $out = sprintf($this->_tags['meta'], $this->_parseAttributes($options, array('type'), ' ', ' ')); + $out = sprintf($this->_tags['meta'], $this->_parseAttributes($options, array('block', 'type'), ' ', ' ')); } - if ($inline) { + if (empty($options['block'])) { return $out; } else { - $this->_View->append('meta', $out); + $this->_View->append($options['block'], $out); } } @@ -377,9 +395,16 @@ class HtmlHelper extends AppHelper { * * `$this->Html->css('styles.css', null, array('inline' => false));` * + * Add the stylesheet to a custom block: + * + * `$this->Html->css('styles.css', null, array('block' => 'layoutCss'));` + * * ### Options * - * - `inline` If set to false, the generated tag appears in the head tag of the layout. Defaults to true + * - `inline` If set to false, the generated tag will be appended to the 'css' block, + * and included in the `$scripts_for_layout` layout variable. Defaults to true. + * - `block` Set the name of the block link/style tag will be appended to. This overrides the `inline` + * option. * * @param mixed $path The name of a CSS style sheet or an array containing names of * CSS stylesheets. If `$path` is prefixed with '/', the path will be relative to the webroot @@ -390,13 +415,18 @@ class HtmlHelper extends AppHelper { * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::css */ public function css($path, $rel = null, $options = array()) { - $options += array('inline' => true); + $options += array('block' => null, 'inline' => true); + if (!$options['inline'] && empty($options['block'])) { + $options['block'] = __FUNCTION__; + } + unset($options['inline']); + if (is_array($path)) { $out = ''; foreach ($path as $i) { $out .= "\n\t" . $this->css($i, $rel, $options); } - if ($options['inline']) { + if (empty($options['block'])) { return $out . "\n"; } return; @@ -433,10 +463,10 @@ class HtmlHelper extends AppHelper { $out = sprintf($this->_tags['css'], $rel, $url, $this->_parseAttributes($options, array('inline'), '', ' ')); } - if ($options['inline']) { + if (empty($options['block'])) { return $out; } else { - $this->_View->append(__FUNCTION__, $out); + $this->_View->append($options['block'], $out); } } @@ -461,10 +491,17 @@ class HtmlHelper extends AppHelper { * * `$this->Html->script('styles.js', null, array('inline' => false));` * + * Add the script file to a custom block: + * + * `$this->Html->script('styles.js', null, array('block' => 'bodyScript'));` + * * ### Options * - * - `inline` - Whether script should be output inline or into scripts_for_layout. - * - `once` - Whether or not the script should be checked for uniqueness. If true scripts will only be + * - `inline` Whether script should be output inline or into `$scripts_for_layout`. When set to false, + * the script tag will be appended to the 'script' view block as well as `$scripts_for_layout`. + * - `block` The name of the block you want the script appended to. Leave undefined to output inline. + * Using this option will override the inline option. + * - `once` Whether or not the script should be checked for uniqueness. If true scripts will only be * included once, use false to allow the same script to be included more than once per request. * * @param mixed $url String or array of javascript files to include @@ -478,13 +515,18 @@ class HtmlHelper extends AppHelper { list($inline, $options) = array($options, array()); $options['inline'] = $inline; } - $options = array_merge(array('inline' => true, 'once' => true), $options); + $options = array_merge(array('block' => null, 'inline' => true, 'once' => true), $options); + if (!$options['inline'] && empty($options['block'])) { + $options['block'] = __FUNCTION__; + } + unset($options['inline']); + if (is_array($url)) { $out = ''; foreach ($url as $i) { $out .= "\n\t" . $this->script($i, $options); } - if ($options['inline']) { + if (empty($options['block'])) { return $out . "\n"; } return null; @@ -507,13 +549,13 @@ class HtmlHelper extends AppHelper { $url = str_replace(JS_URL, 'cjs/', $url); } } - $attributes = $this->_parseAttributes($options, array('inline', 'once'), ' '); + $attributes = $this->_parseAttributes($options, array('block', 'once'), ' '); $out = sprintf($this->_tags['javascriptlink'], $url, $attributes); - if ($options['inline']) { + if (empty($options['block'])) { return $out; } else { - $this->_View->append(__FUNCTION__, $out); + $this->_View->append($options['block'], $out); } } diff --git a/lib/Cake/View/View.php b/lib/Cake/View/View.php index 0d967de96..691d0a390 100644 --- a/lib/Cake/View/View.php +++ b/lib/Cake/View/View.php @@ -536,7 +536,8 @@ class View extends Object { * block will create the block. * * Calling append() without a value will create a new capturing - * block that needs to be finished with View::end() + * block that needs to be finished with View::end(). The content + * of the new capturing context will be added to the existing block context. * * @param string $name Name of the block * @param string $value The content for the block.