Skip to content

Commit

Permalink
Added HtmlHelper::video() for html5 video element generation. Extract…
Browse files Browse the repository at this point in the history
…ed asset url generation code to new function Helper::assetUrl().
  • Loading branch information
ADmad committed Feb 5, 2012
1 parent 12bf134 commit 2222007
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 22 deletions.
38 changes: 38 additions & 0 deletions lib/Cake/Test/Case/View/Helper/HtmlHelperTest.php
Expand Up @@ -1491,6 +1491,44 @@ public function testPara() {
$this->assertTags($result, array('p' => array('class' => 'class-name'), '<text>', '/p'));
}

/**
* testVideo method
*
* @return void
*/
public function testVideo() {
$result = $this->Html->video('video.webm');
$expected = array('video' => array('src' => 'files/video.webm'));
$this->assertTags($result, $expected);

$result = $this->Html->video('video.webm', array(
'text' => 'Your browser does not support the HTML5 Video element.'
));
$expected = array('video' => array('src' => 'files/video.webm'), 'Your browser does not support the HTML5 Video element.', '/video');
$this->assertTags($result, $expected);

$result = $this->Html->video('video.webm', array('autoload', 'muted' => 'muted'));
$expected = array('video' => array(
'src' => 'files/video.webm',
'autoload' => 'autoload',
'muted' => 'muted'
));
$this->assertTags($result, $expected);

$result = $this->Html->video(
array('video.webm', array('src' => 'video.ogv', 'type' => "video/ogg; codecs='theora, vorbis'")),
array('pathPrefix' => 'videos/', 'poster' => 'poster.jpg', 'text' => 'Your browser does not support the HTML5 Video element.')
);
$expected = array(
'video' => array('poster' => IMAGES_URL . 'poster.jpg'),
array('source' => array('src' => 'videos/video.webm', 'type' => 'video/webm')),
array('source' => array('src' => 'videos/video.ogv', 'type' => 'video/ogg; codecs='theora, vorbis'')),
'Your browser does not support the HTML5 Video element.',
'/video'
);
$this->assertTags($result, $expected);
}

/**
* testCrumbList method
*
Expand Down
36 changes: 32 additions & 4 deletions lib/Cake/View/Helper.php
Expand Up @@ -259,6 +259,34 @@ public function webroot($file) {
return $webPath . $asset[1];
}

/**
* Generate url for given asset file. Depending on options passed provides full url with domain name.
* Also calls Helper::assetTimestamp() to add timestamp to local files
*
* @param string|array Path string or url array
* @param array $options Options array. Possible keys:
* `fullBase` Return full url with domain name
* `pathPrefix` Path prefix for relative urls
* @return string Generated url
*/
public function assetUrl($path, array $options) {
if (is_array($path)) {
$path = $this->url($path);
} elseif (strpos($path, '://') === false) {
if (!empty($options['pathPrefix']) && $path[0] !== '/') {
$path = $options['pathPrefix'] . $path;
}
$path = $this->assetTimestamp($this->webroot($path));
}

if (!empty($options['fullBase'])) {
$path = $this->url('/', true) . $path;
unset($options['fullBase']);
}

return $path;
}

/**
* Adds a timestamp to a file based resource based on the value of `Asset.timestamp` in
* Configure. If Asset.timestamp is true and debug > 0, or Asset.timestamp == 'force'
Expand Down Expand Up @@ -446,10 +474,10 @@ public function setEntity($entity, $setScope = false) {

// 0.name, 0.created.month style inputs. Excludes inputs with the modelScope in them.
if (
$count >= 2 &&
is_numeric($parts[0]) &&
!is_numeric($parts[1]) &&
$this->_modelScope &&
$count >= 2 &&
is_numeric($parts[0]) &&
!is_numeric($parts[1]) &&
$this->_modelScope &&
strpos($entity, $this->_modelScope) === false
) {
$entity = $this->_modelScope . '.' . $entity;
Expand Down
106 changes: 88 additions & 18 deletions lib/Cake/View/Helper/HtmlHelper.php
Expand Up @@ -18,6 +18,7 @@
*/

App::uses('AppHelper', 'View/Helper');
App::uses('CakeResponse', 'Network');

/**
* Html Helper class for easy use of HTML widgets.
Expand Down Expand Up @@ -101,7 +102,8 @@ class HtmlHelper extends AppHelper {
*/
protected $_minimizedAttributes = array(
'compact', 'checked', 'declare', 'readonly', 'disabled', 'selected',
'defer', 'ismap', 'nohref', 'noshade', 'nowrap', 'multiple', 'noresize'
'defer', 'ismap', 'nohref', 'noshade', 'nowrap', 'multiple', 'noresize',
'autoplay', 'preload', 'controls', 'loop', 'muted'
);

/**
Expand Down Expand Up @@ -566,13 +568,13 @@ public function script($url, $options = array()) {
* ### Options
*
* - `safe` (boolean) Whether or not the $script should be wrapped in <![CDATA[ ]]>
* - `inline` (boolean) Whether or not the $script should be added to
* - `inline` (boolean) Whether or not the $script should be added to
* `$scripts_for_layout` / `script` block, or output inline. (Deprecated, use `block` instead)
* - `block` Which block you want this script block appended to.
* Defaults to `script`.
*
* @param string $script The script to wrap
* @param array $options The options to use. Options not listed above will be
* @param array $options The options to use. Options not listed above will be
* treated as HTML attributes.
* @return mixed string or null depending on the value of `$options['block']`
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::scriptBlock
Expand Down Expand Up @@ -765,28 +767,16 @@ public function getCrumbList($options = array()) {
*
* - `url` If provided an image link will be generated and the link will point at
* `$options['url']`.
* - `fullBase` If provided the src attribute will get a full addres (non-relative url) for
* the image file.
* - `fullBase` If true the src attribute will get a full address for the image file.
*
* @param string $path Path to the image file, relative to the app/webroot/img/ directory.
* @param array $options Array of HTML attributes. See above for special options.
* @return string completed img tag
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::image
*/
public function image($path, $options = array()) {
if (is_array($path)) {
$path = $this->url($path);
} elseif (strpos($path, '://') === false) {
if ($path[0] !== '/') {
$path = IMAGES_URL . $path;
}
$path = $this->assetTimestamp($this->webroot($path));
}

if (!empty($options['fullBase'])) {
$path = $this->url('/', true) . $path;
unset($options['fullBase']);
}
$path = $this->assetUrl($path, $options + array('pathPrefix' => IMAGES_URL));
$options = array_diff_key($options, array('fullBase' => '', 'pathPrefix' => ''));

if (!isset($options['alt'])) {
$options['alt'] = '';
Expand Down Expand Up @@ -977,6 +967,86 @@ public function para($class, $text, $options = array()) {
return sprintf($this->_tags[$tag], $this->_parseAttributes($options, null, ' ', ''), $text);
}

/**
* Returns a VIDEO element
*
* ### Usage
*
* Using single video file:
*
* `echo $this->Html->video('video.mp4', array('fullBase' => true, 'text' => 'Fallback text'));`
*
* Outputs:
*
* `<video src="http://www.somehost.com/files/video.mp4">Fallback text</video>`
*
* Using multiple video files:
*
* {{{
* echo $this->Html->video(
* array('video.mp4', array('src' => 'video.ogg', 'type' => "video/ogg; codecs='theora, vorbis'")),
* array('autoplay')
* );
* }}}
*
* Outputs:
*
* {{{
* <video autoplay="autoplay">
* <source src="/files/video.mp4" type="video/mp4"/>
* <source src="/files/video.ogg" type="video/ogg; codecs='theora, vorbis'"/>
* </video>
* }}}
*
* ### Options
*
* - `text` Text to include inside the video tag
* - `pathPrefix` Path prefix to use for relative urls, defaults to 'files/'
* - `fullBase` If provided the src attribute will get a full address including domain name
*
* @param string|array $path Path to the video file, relative to the webroot/{$options['pathPrefix']} directory.
* Or an array where each item itself can be a path string or an associate array containing keys `src` and `type`
* @param array $options Array of HTML attributes, and special options above.
* @return string Generated video tag
*/
public function video($path, $options = array()) {
$options += array('pathPrefix' => 'files/', 'text' => '');

if (is_array($path)) {
$response = null;
$sourceTags = '';
foreach ($path as $source) {
if (is_string($source)) {
$source = array(
'src' => $source,
);
}
if (!isset($source['type'])) {
if ($response === null) {
$response = new CakeResponse();
}
$source['type'] = $response->getMimeType(pathinfo($source['src'], PATHINFO_EXTENSION));
}
$source['src'] = $this->assetUrl($source['src'], $options);
$sourceTags .= $this->useTag('tagselfclosing', 'source', $source);
}
$options['text'] = $sourceTags . $options['text'];
unset($options['fullBase']);
} else {
$path = $this->assetUrl($path, $options);
$options['src'] = $path;
}

if (isset($options['poster'])) {
$options['poster'] = $this->assetUrl($options['poster'], array('pathPrefix' => IMAGES_URL) + $options);
}

$text = $options['text'];

$options = array_diff_key($options, array('fullBase' => '', 'pathPrefix' => '', 'text' => ''));
return $this->tag('video', $text, $options);
}

/**
* Build a nested list (UL/OL) out of an associative array.
*
Expand Down

0 comments on commit 2222007

Please sign in to comment.