CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Reporting Security Issues
    • Privacy Policy
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Get Involved
    • Issues (GitHub)
    • Bakery
    • Featured Resources
    • Training
    • Meetups
    • My CakePHP
    • CakeFest
    • Newsletter
    • Linkedin
    • YouTube
    • Facebook
    • Twitter
    • Mastodon
    • Help & Support
    • Forum
    • Stack Overflow
    • Slack
    • Paid Support
CakePHP

C CakePHP 2.6 API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 2.6
      • 4.2
      • 4.1
      • 4.0
      • 3.9
      • 3.8
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Packages

  • Cake
    • Cache
      • Engine
    • Configure
    • Console
      • Command
        • Task
    • Controller
      • Component
        • Acl
        • Auth
    • Core
    • Error
    • Event
    • I18n
    • Log
      • Engine
    • Model
      • Behavior
      • Datasource
        • Database
        • Session
      • Validator
    • Network
      • Email
      • Http
    • Routing
      • Filter
      • Route
    • TestSuite
      • Coverage
      • Fixture
      • Reporter
    • Utility
    • View
      • Helper

Classes

  • CacheHelper
  • FormHelper
  • HtmlHelper
  • JqueryEngineHelper
  • JsBaseEngineHelper
  • JsHelper
  • MootoolsEngineHelper
  • NumberHelper
  • PaginatorHelper
  • PrototypeEngineHelper
  • RssHelper
  • SessionHelper
  • TextHelper
  • TimeHelper
   1: <?php
   2: /**
   3:  * Html Helper class file.
   4:  *
   5:  * Simplifies the construction of HTML elements.
   6:  *
   7:  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
   8:  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
   9:  *
  10:  * Licensed under The MIT License
  11:  * For full copyright and license information, please see the LICENSE.txt
  12:  * Redistributions of files must retain the above copyright notice.
  13:  *
  14:  * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  15:  * @link          http://cakephp.org CakePHP(tm) Project
  16:  * @package       Cake.View.Helper
  17:  * @since         CakePHP(tm) v 0.9.1
  18:  * @license       http://www.opensource.org/licenses/mit-license.php MIT License
  19:  */
  20: 
  21: App::uses('AppHelper', 'View/Helper');
  22: App::uses('CakeResponse', 'Network');
  23: 
  24: /**
  25:  * Html Helper class for easy use of HTML widgets.
  26:  *
  27:  * HtmlHelper encloses all methods needed while working with HTML pages.
  28:  *
  29:  * @package       Cake.View.Helper
  30:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html
  31:  */
  32: class HtmlHelper extends AppHelper {
  33: 
  34: /**
  35:  * Reference to the Response object
  36:  *
  37:  * @var CakeResponse
  38:  */
  39:     public $response;
  40: 
  41: /**
  42:  * html tags used by this helper.
  43:  *
  44:  * @var array
  45:  */
  46:     protected $_tags = array(
  47:         'meta' => '<meta%s/>',
  48:         'metalink' => '<link href="%s"%s/>',
  49:         'link' => '<a href="%s"%s>%s</a>',
  50:         'mailto' => '<a href="mailto:%s"%s>%s</a>',
  51:         'form' => '<form action="%s"%s>',
  52:         'formend' => '</form>',
  53:         'input' => '<input name="%s"%s/>',
  54:         'textarea' => '<textarea name="%s"%s>%s</textarea>',
  55:         'hidden' => '<input type="hidden" name="%s"%s/>',
  56:         'checkbox' => '<input type="checkbox" name="%s"%s/>',
  57:         'checkboxmultiple' => '<input type="checkbox" name="%s[]"%s />',
  58:         'radio' => '<input type="radio" name="%s" id="%s"%s />%s',
  59:         'selectstart' => '<select name="%s"%s>',
  60:         'selectmultiplestart' => '<select name="%s[]"%s>',
  61:         'selectempty' => '<option value=""%s>&nbsp;</option>',
  62:         'selectoption' => '<option value="%s"%s>%s</option>',
  63:         'selectend' => '</select>',
  64:         'optiongroup' => '<optgroup label="%s"%s>',
  65:         'optiongroupend' => '</optgroup>',
  66:         'checkboxmultiplestart' => '',
  67:         'checkboxmultipleend' => '',
  68:         'password' => '<input type="password" name="%s"%s/>',
  69:         'file' => '<input type="file" name="%s"%s/>',
  70:         'file_no_model' => '<input type="file" name="%s"%s/>',
  71:         'submit' => '<input%s/>',
  72:         'submitimage' => '<input type="image" src="%s"%s/>',
  73:         'button' => '<button%s>%s</button>',
  74:         'image' => '<img src="%s"%s/>',
  75:         'tableheader' => '<th%s>%s</th>',
  76:         'tableheaderrow' => '<tr%s>%s</tr>',
  77:         'tablecell' => '<td%s>%s</td>',
  78:         'tablerow' => '<tr%s>%s</tr>',
  79:         'block' => '<div%s>%s</div>',
  80:         'blockstart' => '<div%s>',
  81:         'blockend' => '</div>',
  82:         'hiddenblock' => '<div style="display:none;">%s</div>',
  83:         'tag' => '<%s%s>%s</%s>',
  84:         'tagstart' => '<%s%s>',
  85:         'tagend' => '</%s>',
  86:         'tagselfclosing' => '<%s%s/>',
  87:         'para' => '<p%s>%s</p>',
  88:         'parastart' => '<p%s>',
  89:         'label' => '<label for="%s"%s>%s</label>',
  90:         'fieldset' => '<fieldset%s>%s</fieldset>',
  91:         'fieldsetstart' => '<fieldset><legend>%s</legend>',
  92:         'fieldsetend' => '</fieldset>',
  93:         'legend' => '<legend>%s</legend>',
  94:         'css' => '<link rel="%s" type="text/css" href="%s"%s/>',
  95:         'style' => '<style type="text/css"%s>%s</style>',
  96:         'charset' => '<meta http-equiv="Content-Type" content="text/html; charset=%s" />',
  97:         'ul' => '<ul%s>%s</ul>',
  98:         'ol' => '<ol%s>%s</ol>',
  99:         'li' => '<li%s>%s</li>',
 100:         'error' => '<div%s>%s</div>',
 101:         'javascriptblock' => '<script%s>%s</script>',
 102:         'javascriptstart' => '<script>',
 103:         'javascriptlink' => '<script type="text/javascript" src="%s"%s></script>',
 104:         'javascriptend' => '</script>'
 105:     );
 106: 
 107: /**
 108:  * Breadcrumbs.
 109:  *
 110:  * @var array
 111:  */
 112:     protected $_crumbs = array();
 113: 
 114: /**
 115:  * Names of script & css files that have been included once
 116:  *
 117:  * @var array
 118:  */
 119:     protected $_includedAssets = array();
 120: 
 121: /**
 122:  * Options for the currently opened script block buffer if any.
 123:  *
 124:  * @var array
 125:  */
 126:     protected $_scriptBlockOptions = array();
 127: 
 128: /**
 129:  * Document type definitions
 130:  *
 131:  * @var array
 132:  */
 133:     protected $_docTypes = array(
 134:         'html4-strict' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">',
 135:         'html4-trans' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
 136:         'html4-frame' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">',
 137:         'html5' => '<!DOCTYPE html>',
 138:         'xhtml-strict' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
 139:         'xhtml-trans' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
 140:         'xhtml-frame' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
 141:         'xhtml11' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'
 142:     );
 143: 
 144: /**
 145:  * Constructor
 146:  *
 147:  * ### Settings
 148:  *
 149:  * - `configFile` A file containing an array of tags you wish to redefine.
 150:  *
 151:  * ### Customizing tag sets
 152:  *
 153:  * Using the `configFile` option you can redefine the tag HtmlHelper will use.
 154:  * The file named should be compatible with HtmlHelper::loadConfig().
 155:  *
 156:  * @param View $View The View this helper is being attached to.
 157:  * @param array $settings Configuration settings for the helper.
 158:  */
 159:     public function __construct(View $View, $settings = array()) {
 160:         parent::__construct($View, $settings);
 161:         if (is_object($this->_View->response)) {
 162:             $this->response = $this->_View->response;
 163:         } else {
 164:             $this->response = new CakeResponse();
 165:         }
 166:         if (!empty($settings['configFile'])) {
 167:             $this->loadConfig($settings['configFile']);
 168:         }
 169:     }
 170: 
 171: /**
 172:  * Adds a link to the breadcrumbs array.
 173:  *
 174:  * @param string $name Text for link
 175:  * @param string $link URL for link (if empty it won't be a link)
 176:  * @param string|array $options Link attributes e.g. array('id' => 'selected')
 177:  * @return $this
 178:  * @see HtmlHelper::link() for details on $options that can be used.
 179:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#creating-breadcrumb-trails-with-htmlhelper
 180:  */
 181:     public function addCrumb($name, $link = null, $options = null) {
 182:         $this->_crumbs[] = array($name, $link, $options);
 183:         return $this;
 184:     }
 185: 
 186: /**
 187:  * Returns a doctype string.
 188:  *
 189:  * Possible doctypes:
 190:  *
 191:  *  - html4-strict:  HTML4 Strict.
 192:  *  - html4-trans:  HTML4 Transitional.
 193:  *  - html4-frame:  HTML4 Frameset.
 194:  *  - html5: HTML5. Default value.
 195:  *  - xhtml-strict: XHTML1 Strict.
 196:  *  - xhtml-trans: XHTML1 Transitional.
 197:  *  - xhtml-frame: XHTML1 Frameset.
 198:  *  - xhtml11: XHTML1.1.
 199:  *
 200:  * @param string $type Doctype to use.
 201:  * @return string|null Doctype string
 202:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::docType
 203:  */
 204:     public function docType($type = 'html5') {
 205:         if (isset($this->_docTypes[$type])) {
 206:             return $this->_docTypes[$type];
 207:         }
 208:         return null;
 209:     }
 210: 
 211: /**
 212:  * Creates a link to an external resource and handles basic meta tags
 213:  *
 214:  * Create a meta tag that is output inline:
 215:  *
 216:  * `$this->Html->meta('icon', 'favicon.ico');
 217:  *
 218:  * Append the meta tag to `$scripts_for_layout`:
 219:  *
 220:  * `$this->Html->meta('description', 'A great page', array('inline' => false));`
 221:  *
 222:  * Append the meta tag to custom view block:
 223:  *
 224:  * `$this->Html->meta('description', 'A great page', array('block' => 'metaTags'));`
 225:  *
 226:  * ### Options
 227:  *
 228:  * - `inline` Whether or not the link element should be output inline. Set to false to
 229:  *   have the meta tag included in `$scripts_for_layout`, and appended to the 'meta' view block.
 230:  * - `block` Choose a custom block to append the meta tag to. Using this option
 231:  *   will override the inline option.
 232:  *
 233:  * @param string $type The title of the external resource
 234:  * @param string|array $url The address of the external resource or string for content attribute
 235:  * @param array $options Other attributes for the generated tag. If the type attribute is html,
 236:  *    rss, atom, or icon, the mime-type is returned.
 237:  * @return string A completed `<link />` element.
 238:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::meta
 239:  */
 240:     public function meta($type, $url = null, $options = array()) {
 241:         $options += array('inline' => true, 'block' => null);
 242:         if (!$options['inline'] && empty($options['block'])) {
 243:             $options['block'] = __FUNCTION__;
 244:         }
 245:         unset($options['inline']);
 246: 
 247:         if (!is_array($type)) {
 248:             $types = array(
 249:                 'rss' => array('type' => 'application/rss+xml', 'rel' => 'alternate', 'title' => $type, 'link' => $url),
 250:                 'atom' => array('type' => 'application/atom+xml', 'title' => $type, 'link' => $url),
 251:                 'icon' => array('type' => 'image/x-icon', 'rel' => 'icon', 'link' => $url),
 252:                 'keywords' => array('name' => 'keywords', 'content' => $url),
 253:                 'description' => array('name' => 'description', 'content' => $url),
 254:             );
 255: 
 256:             if ($type === 'icon' && $url === null) {
 257:                 $types['icon']['link'] = 'favicon.ico';
 258:             }
 259: 
 260:             if (isset($types[$type])) {
 261:                 $type = $types[$type];
 262:             } elseif (!isset($options['type']) && $url !== null) {
 263:                 if (is_array($url) && isset($url['ext'])) {
 264:                     $type = $types[$url['ext']];
 265:                 } else {
 266:                     $type = $types['rss'];
 267:                 }
 268:             } elseif (isset($options['type']) && isset($types[$options['type']])) {
 269:                 $type = $types[$options['type']];
 270:                 unset($options['type']);
 271:             } else {
 272:                 $type = array();
 273:             }
 274:         }
 275: 
 276:         $options += $type;
 277:         $out = null;
 278: 
 279:         if (isset($options['link'])) {
 280:             $options['link'] = $this->assetUrl($options['link']);
 281:             if (isset($options['rel']) && $options['rel'] === 'icon') {
 282:                 $out = sprintf($this->_tags['metalink'], $options['link'], $this->_parseAttributes($options, array('block', 'link')));
 283:                 $options['rel'] = 'shortcut icon';
 284:             }
 285:             $out .= sprintf($this->_tags['metalink'], $options['link'], $this->_parseAttributes($options, array('block', 'link')));
 286:         } else {
 287:             $out = sprintf($this->_tags['meta'], $this->_parseAttributes($options, array('block', 'type')));
 288:         }
 289: 
 290:         if (empty($options['block'])) {
 291:             return $out;
 292:         }
 293:         $this->_View->append($options['block'], $out);
 294:     }
 295: 
 296: /**
 297:  * Returns a charset META-tag.
 298:  *
 299:  * @param string $charset The character set to be used in the meta tag. If empty,
 300:  *  The App.encoding value will be used. Example: "utf-8".
 301:  * @return string A meta tag containing the specified character set.
 302:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::charset
 303:  */
 304:     public function charset($charset = null) {
 305:         if (empty($charset)) {
 306:             $charset = strtolower(Configure::read('App.encoding'));
 307:         }
 308:         return sprintf($this->_tags['charset'], (!empty($charset) ? $charset : 'utf-8'));
 309:     }
 310: 
 311: /**
 312:  * Creates an HTML link.
 313:  *
 314:  * If $url starts with "http://" this is treated as an external link. Else,
 315:  * it is treated as a path to controller/action and parsed with the
 316:  * HtmlHelper::url() method.
 317:  *
 318:  * If the $url is empty, $title is used instead.
 319:  *
 320:  * ### Options
 321:  *
 322:  * - `escape` Set to false to disable escaping of title and attributes.
 323:  * - `escapeTitle` Set to false to disable escaping of title. (Takes precedence over value of `escape`)
 324:  * - `confirm` JavaScript confirmation message.
 325:  *
 326:  * @param string $title The content to be wrapped by <a> tags.
 327:  * @param string|array $url Cake-relative URL or array of URL parameters, or external URL (starts with http://)
 328:  * @param array $options Array of options and HTML attributes.
 329:  * @param string $confirmMessage JavaScript confirmation message. This
 330:  *   argument is deprecated as of 2.6. Use `confirm` key in $options instead.
 331:  * @return string An `<a />` element.
 332:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::link
 333:  */
 334:     public function link($title, $url = null, $options = array(), $confirmMessage = false) {
 335:         $escapeTitle = true;
 336:         if ($url !== null) {
 337:             $url = $this->url($url);
 338:         } else {
 339:             $url = $this->url($title);
 340:             $title = htmlspecialchars_decode($url, ENT_QUOTES);
 341:             $title = h(urldecode($title));
 342:             $escapeTitle = false;
 343:         }
 344: 
 345:         if (isset($options['escapeTitle'])) {
 346:             $escapeTitle = $options['escapeTitle'];
 347:             unset($options['escapeTitle']);
 348:         } elseif (isset($options['escape'])) {
 349:             $escapeTitle = $options['escape'];
 350:         }
 351: 
 352:         if ($escapeTitle === true) {
 353:             $title = h($title);
 354:         } elseif (is_string($escapeTitle)) {
 355:             $title = htmlentities($title, ENT_QUOTES, $escapeTitle);
 356:         }
 357: 
 358:         if (!empty($options['confirm'])) {
 359:             $confirmMessage = $options['confirm'];
 360:             unset($options['confirm']);
 361:         }
 362:         if ($confirmMessage) {
 363:             $options['onclick'] = $this->_confirm($confirmMessage, 'return true;', 'return false;', $options);
 364:         } elseif (isset($options['default']) && !$options['default']) {
 365:             if (isset($options['onclick'])) {
 366:                 $options['onclick'] .= ' ';
 367:             } else {
 368:                 $options['onclick'] = '';
 369:             }
 370:             $options['onclick'] .= 'event.returnValue = false; return false;';
 371:             unset($options['default']);
 372:         }
 373:         return sprintf($this->_tags['link'], $url, $this->_parseAttributes($options), $title);
 374:     }
 375: 
 376: /**
 377:  * Creates a link element for CSS stylesheets.
 378:  *
 379:  * ### Usage
 380:  *
 381:  * Include one CSS file:
 382:  *
 383:  * `echo $this->Html->css('styles.css');`
 384:  *
 385:  * Include multiple CSS files:
 386:  *
 387:  * `echo $this->Html->css(array('one.css', 'two.css'));`
 388:  *
 389:  * Add the stylesheet to the `$scripts_for_layout` layout var:
 390:  *
 391:  * `$this->Html->css('styles.css', array('inline' => false));`
 392:  *
 393:  * Add the stylesheet to a custom block:
 394:  *
 395:  * `$this->Html->css('styles.css', array('block' => 'layoutCss'));`
 396:  *
 397:  * ### Options
 398:  *
 399:  * - `inline` If set to false, the generated tag will be appended to the 'css' block,
 400:  *   and included in the `$scripts_for_layout` layout variable. Defaults to true.
 401:  * - `once` Whether or not the css file should be checked for uniqueness. If true css
 402:  *   files  will only be included once, use false to allow the same
 403:  *   css to be included more than once per request.
 404:  * - `block` Set the name of the block link/style tag will be appended to.
 405:  *   This overrides the `inline` option.
 406:  * - `plugin` False value will prevent parsing path as a plugin
 407:  * - `rel` Defaults to 'stylesheet'. If equal to 'import' the stylesheet will be imported.
 408:  * - `fullBase` If true the URL will get a full address for the css file.
 409:  *
 410:  * @param string|array $path The name of a CSS style sheet or an array containing names of
 411:  *   CSS stylesheets. If `$path` is prefixed with '/', the path will be relative to the webroot
 412:  *   of your application. Otherwise, the path will be relative to your CSS path, usually webroot/css.
 413:  * @param array $options Array of options and HTML arguments.
 414:  * @return string CSS <link /> or <style /> tag, depending on the type of link.
 415:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::css
 416:  */
 417:     public function css($path, $options = array()) {
 418:         if (!is_array($options)) {
 419:             $rel = $options;
 420:             $options = array();
 421:             if ($rel) {
 422:                 $options['rel'] = $rel;
 423:             }
 424:             if (func_num_args() > 2) {
 425:                 $options = func_get_arg(2) + $options;
 426:             }
 427:             unset($rel);
 428:         }
 429: 
 430:         $options += array(
 431:             'block' => null,
 432:             'inline' => true,
 433:             'once' => false,
 434:             'rel' => 'stylesheet'
 435:         );
 436:         if (!$options['inline'] && empty($options['block'])) {
 437:             $options['block'] = __FUNCTION__;
 438:         }
 439:         unset($options['inline']);
 440: 
 441:         if (is_array($path)) {
 442:             $out = '';
 443:             foreach ($path as $i) {
 444:                 $out .= "\n\t" . $this->css($i, $options);
 445:             }
 446:             if (empty($options['block'])) {
 447:                 return $out . "\n";
 448:             }
 449:             return;
 450:         }
 451: 
 452:         if ($options['once'] && isset($this->_includedAssets[__METHOD__][$path])) {
 453:             return '';
 454:         }
 455:         unset($options['once']);
 456:         $this->_includedAssets[__METHOD__][$path] = true;
 457: 
 458:         if (strpos($path, '//') !== false) {
 459:             $url = $path;
 460:         } else {
 461:             $url = $this->assetUrl($path, $options + array('pathPrefix' => Configure::read('App.cssBaseUrl'), 'ext' => '.css'));
 462:             $options = array_diff_key($options, array('fullBase' => null, 'pathPrefix' => null));
 463: 
 464:             if (Configure::read('Asset.filter.css')) {
 465:                 $pos = strpos($url, Configure::read('App.cssBaseUrl'));
 466:                 if ($pos !== false) {
 467:                     $url = substr($url, 0, $pos) . 'ccss/' . substr($url, $pos + strlen(Configure::read('App.cssBaseUrl')));
 468:                 }
 469:             }
 470:         }
 471: 
 472:         if ($options['rel'] === 'import') {
 473:             $out = sprintf(
 474:                 $this->_tags['style'],
 475:                 $this->_parseAttributes($options, array('rel', 'block')),
 476:                 '@import url(' . $url . ');'
 477:             );
 478:         } else {
 479:             $out = sprintf(
 480:                 $this->_tags['css'],
 481:                 $options['rel'],
 482:                 $url,
 483:                 $this->_parseAttributes($options, array('rel', 'block'))
 484:             );
 485:         }
 486: 
 487:         if (empty($options['block'])) {
 488:             return $out;
 489:         }
 490:         $this->_View->append($options['block'], $out);
 491:     }
 492: 
 493: /**
 494:  * Returns one or many `<script>` tags depending on the number of scripts given.
 495:  *
 496:  * If the filename is prefixed with "/", the path will be relative to the base path of your
 497:  * application. Otherwise, the path will be relative to your JavaScript path, usually webroot/js.
 498:  *
 499:  * ### Usage
 500:  *
 501:  * Include one script file:
 502:  *
 503:  * `echo $this->Html->script('styles.js');`
 504:  *
 505:  * Include multiple script files:
 506:  *
 507:  * `echo $this->Html->script(array('one.js', 'two.js'));`
 508:  *
 509:  * Add the script file to the `$scripts_for_layout` layout var:
 510:  *
 511:  * `$this->Html->script('styles.js', array('inline' => false));`
 512:  *
 513:  * Add the script file to a custom block:
 514:  *
 515:  * `$this->Html->script('styles.js', array('block' => 'bodyScript'));`
 516:  *
 517:  * ### Options
 518:  *
 519:  * - `inline` Whether script should be output inline or into `$scripts_for_layout`. When set to false,
 520:  *   the script tag will be appended to the 'script' view block as well as `$scripts_for_layout`.
 521:  * - `block` The name of the block you want the script appended to. Leave undefined to output inline.
 522:  *   Using this option will override the inline option.
 523:  * - `once` Whether or not the script should be checked for uniqueness. If true scripts will only be
 524:  *   included once, use false to allow the same script to be included more than once per request.
 525:  * - `plugin` False value will prevent parsing path as a plugin
 526:  * - `fullBase` If true the url will get a full address for the script file.
 527:  *
 528:  * @param string|array $url String or array of javascript files to include
 529:  * @param array|bool $options Array of options, and html attributes see above. If boolean sets $options['inline'] = value
 530:  * @return mixed String of `<script />` tags or null if $inline is false or if $once is true and the file has been
 531:  *   included before.
 532:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::script
 533:  */
 534:     public function script($url, $options = array()) {
 535:         if (is_bool($options)) {
 536:             list($inline, $options) = array($options, array());
 537:             $options['inline'] = $inline;
 538:         }
 539:         $options += array('block' => null, 'inline' => true, 'once' => true);
 540:         if (!$options['inline'] && empty($options['block'])) {
 541:             $options['block'] = __FUNCTION__;
 542:         }
 543:         unset($options['inline']);
 544: 
 545:         if (is_array($url)) {
 546:             $out = '';
 547:             foreach ($url as $i) {
 548:                 $out .= "\n\t" . $this->script($i, $options);
 549:             }
 550:             if (empty($options['block'])) {
 551:                 return $out . "\n";
 552:             }
 553:             return null;
 554:         }
 555:         if ($options['once'] && isset($this->_includedAssets[__METHOD__][$url])) {
 556:             return null;
 557:         }
 558:         $this->_includedAssets[__METHOD__][$url] = true;
 559: 
 560:         if (strpos($url, '//') === false) {
 561:             $url = $this->assetUrl($url, $options + array('pathPrefix' => Configure::read('App.jsBaseUrl'), 'ext' => '.js'));
 562:             $options = array_diff_key($options, array('fullBase' => null, 'pathPrefix' => null));
 563: 
 564:             if (Configure::read('Asset.filter.js')) {
 565:                 $url = str_replace(Configure::read('App.jsBaseUrl'), 'cjs/', $url);
 566:             }
 567:         }
 568:         $attributes = $this->_parseAttributes($options, array('block', 'once'));
 569:         $out = sprintf($this->_tags['javascriptlink'], $url, $attributes);
 570: 
 571:         if (empty($options['block'])) {
 572:             return $out;
 573:         }
 574:         $this->_View->append($options['block'], $out);
 575:     }
 576: 
 577: /**
 578:  * Wrap $script in a script tag.
 579:  *
 580:  * ### Options
 581:  *
 582:  * - `safe` (boolean) Whether or not the $script should be wrapped in <![CDATA[ ]]>
 583:  * - `inline` (boolean) Whether or not the $script should be added to
 584:  *   `$scripts_for_layout` / `script` block, or output inline. (Deprecated, use `block` instead)
 585:  * - `block` Which block you want this script block appended to.
 586:  *   Defaults to `script`.
 587:  *
 588:  * @param string $script The script to wrap
 589:  * @param array $options The options to use. Options not listed above will be
 590:  *    treated as HTML attributes.
 591:  * @return mixed string or null depending on the value of `$options['block']`
 592:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::scriptBlock
 593:  */
 594:     public function scriptBlock($script, $options = array()) {
 595:         $options += array('type' => 'text/javascript', 'safe' => true, 'inline' => true);
 596:         if ($options['safe']) {
 597:             $script = "\n" . '//<![CDATA[' . "\n" . $script . "\n" . '//]]>' . "\n";
 598:         }
 599:         if (!$options['inline'] && empty($options['block'])) {
 600:             $options['block'] = 'script';
 601:         }
 602:         unset($options['inline'], $options['safe']);
 603: 
 604:         $attributes = $this->_parseAttributes($options, array('block'));
 605:         $out = sprintf($this->_tags['javascriptblock'], $attributes, $script);
 606: 
 607:         if (empty($options['block'])) {
 608:             return $out;
 609:         }
 610:         $this->_View->append($options['block'], $out);
 611:     }
 612: 
 613: /**
 614:  * Begin a script block that captures output until HtmlHelper::scriptEnd()
 615:  * is called. This capturing block will capture all output between the methods
 616:  * and create a scriptBlock from it.
 617:  *
 618:  * ### Options
 619:  *
 620:  * - `safe` Whether the code block should contain a CDATA
 621:  * - `inline` Should the generated script tag be output inline or in `$scripts_for_layout`
 622:  *
 623:  * @param array $options Options for the code block.
 624:  * @return void
 625:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::scriptStart
 626:  */
 627:     public function scriptStart($options = array()) {
 628:         $options += array('safe' => true, 'inline' => true);
 629:         $this->_scriptBlockOptions = $options;
 630:         ob_start();
 631:     }
 632: 
 633: /**
 634:  * End a Buffered section of JavaScript capturing.
 635:  * Generates a script tag inline or in `$scripts_for_layout` depending on the settings
 636:  * used when the scriptBlock was started
 637:  *
 638:  * @return mixed depending on the settings of scriptStart() either a script tag or null
 639:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::scriptEnd
 640:  */
 641:     public function scriptEnd() {
 642:         $buffer = ob_get_clean();
 643:         $options = $this->_scriptBlockOptions;
 644:         $this->_scriptBlockOptions = array();
 645:         return $this->scriptBlock($buffer, $options);
 646:     }
 647: 
 648: /**
 649:  * Builds CSS style data from an array of CSS properties
 650:  *
 651:  * ### Usage:
 652:  *
 653:  * ```
 654:  * echo $this->Html->style(array('margin' => '10px', 'padding' => '10px'), true);
 655:  *
 656:  * // creates
 657:  * 'margin:10px;padding:10px;'
 658:  * ```
 659:  *
 660:  * @param array $data Style data array, keys will be used as property names, values as property values.
 661:  * @param bool $oneline Whether or not the style block should be displayed on one line.
 662:  * @return string CSS styling data
 663:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::style
 664:  */
 665:     public function style($data, $oneline = true) {
 666:         if (!is_array($data)) {
 667:             return $data;
 668:         }
 669:         $out = array();
 670:         foreach ($data as $key => $value) {
 671:             $out[] = $key . ':' . $value . ';';
 672:         }
 673:         if ($oneline) {
 674:             return implode(' ', $out);
 675:         }
 676:         return implode("\n", $out);
 677:     }
 678: 
 679: /**
 680:  * Returns the breadcrumb trail as a sequence of &raquo;-separated links.
 681:  *
 682:  * If `$startText` is an array, the accepted keys are:
 683:  *
 684:  * - `text` Define the text/content for the link.
 685:  * - `url` Define the target of the created link.
 686:  *
 687:  * All other keys will be passed to HtmlHelper::link() as the `$options` parameter.
 688:  *
 689:  * @param string $separator Text to separate crumbs.
 690:  * @param string|array|bool $startText This will be the first crumb, if false it defaults to first crumb in array. Can
 691:  *   also be an array, see above for details.
 692:  * @return string|null Composed bread crumbs
 693:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#creating-breadcrumb-trails-with-htmlhelper
 694:  */
 695:     public function getCrumbs($separator = '&raquo;', $startText = false) {
 696:         $crumbs = $this->_prepareCrumbs($startText);
 697:         if (!empty($crumbs)) {
 698:             $out = array();
 699:             foreach ($crumbs as $crumb) {
 700:                 if (!empty($crumb[1])) {
 701:                     $out[] = $this->link($crumb[0], $crumb[1], $crumb[2]);
 702:                 } else {
 703:                     $out[] = $crumb[0];
 704:                 }
 705:             }
 706:             return implode($separator, $out);
 707:         }
 708:         return null;
 709:     }
 710: 
 711: /**
 712:  * Returns breadcrumbs as a (x)html list
 713:  *
 714:  * This method uses HtmlHelper::tag() to generate list and its elements. Works
 715:  * similar to HtmlHelper::getCrumbs(), so it uses options which every
 716:  * crumb was added with.
 717:  *
 718:  * ### Options
 719:  * - `separator` Separator content to insert in between breadcrumbs, defaults to ''
 720:  * - `firstClass` Class for wrapper tag on the first breadcrumb, defaults to 'first'
 721:  * - `lastClass` Class for wrapper tag on current active page, defaults to 'last'
 722:  *
 723:  * @param array $options Array of html attributes to apply to the generated list elements.
 724:  * @param string|array|bool $startText This will be the first crumb, if false it defaults to first crumb in array. Can
 725:  *   also be an array, see `HtmlHelper::getCrumbs` for details.
 726:  * @return string|null breadcrumbs html list
 727:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#creating-breadcrumb-trails-with-htmlhelper
 728:  */
 729:     public function getCrumbList($options = array(), $startText = false) {
 730:         $defaults = array('firstClass' => 'first', 'lastClass' => 'last', 'separator' => '', 'escape' => true);
 731:         $options = (array)$options + $defaults;
 732:         $firstClass = $options['firstClass'];
 733:         $lastClass = $options['lastClass'];
 734:         $separator = $options['separator'];
 735:         $escape = $options['escape'];
 736:         unset($options['firstClass'], $options['lastClass'], $options['separator'], $options['escape']);
 737: 
 738:         $crumbs = $this->_prepareCrumbs($startText, $escape);
 739:         if (empty($crumbs)) {
 740:             return null;
 741:         }
 742: 
 743:         $result = '';
 744:         $crumbCount = count($crumbs);
 745:         $ulOptions = $options;
 746:         foreach ($crumbs as $which => $crumb) {
 747:             $options = array();
 748:             if (empty($crumb[1])) {
 749:                 $elementContent = $crumb[0];
 750:             } else {
 751:                 $elementContent = $this->link($crumb[0], $crumb[1], $crumb[2]);
 752:             }
 753:             if (!$which && $firstClass !== false) {
 754:                 $options['class'] = $firstClass;
 755:             } elseif ($which == $crumbCount - 1 && $lastClass !== false) {
 756:                 $options['class'] = $lastClass;
 757:             }
 758:             if (!empty($separator) && ($crumbCount - $which >= 2)) {
 759:                 $elementContent .= $separator;
 760:             }
 761:             $result .= $this->tag('li', $elementContent, $options);
 762:         }
 763:         return $this->tag('ul', $result, $ulOptions);
 764:     }
 765: 
 766: /**
 767:  * Prepends startText to crumbs array if set
 768:  *
 769:  * @param string $startText Text to prepend
 770:  * @param bool $escape If the output should be escaped or not
 771:  * @return array Crumb list including startText (if provided)
 772:  */
 773:     protected function _prepareCrumbs($startText, $escape = true) {
 774:         $crumbs = $this->_crumbs;
 775:         if ($startText) {
 776:             if (!is_array($startText)) {
 777:                 $startText = array(
 778:                     'url' => '/',
 779:                     'text' => $startText
 780:                 );
 781:             }
 782:             $startText += array('url' => '/', 'text' => __d('cake', 'Home'));
 783:             list($url, $text) = array($startText['url'], $startText['text']);
 784:             unset($startText['url'], $startText['text']);
 785:             array_unshift($crumbs, array($text, $url, $startText + array('escape' => $escape)));
 786:         }
 787:         return $crumbs;
 788:     }
 789: 
 790: /**
 791:  * Creates a formatted IMG element.
 792:  *
 793:  * This method will set an empty alt attribute if one is not supplied.
 794:  *
 795:  * ### Usage:
 796:  *
 797:  * Create a regular image:
 798:  *
 799:  * `echo $this->Html->image('cake_icon.png', array('alt' => 'CakePHP'));`
 800:  *
 801:  * Create an image link:
 802:  *
 803:  * `echo $this->Html->image('cake_icon.png', array('alt' => 'CakePHP', 'url' => 'http://cakephp.org'));`
 804:  *
 805:  * ### Options:
 806:  *
 807:  * - `url` If provided an image link will be generated and the link will point at
 808:  *   `$options['url']`.
 809:  * - `fullBase` If true the src attribute will get a full address for the image file.
 810:  * - `plugin` False value will prevent parsing path as a plugin
 811:  *
 812:  * @param string $path Path to the image file, relative to the app/webroot/img/ directory.
 813:  * @param array $options Array of HTML attributes. See above for special options.
 814:  * @return string completed img tag
 815:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::image
 816:  */
 817:     public function image($path, $options = array()) {
 818:         $path = $this->assetUrl($path, $options + array('pathPrefix' => Configure::read('App.imageBaseUrl')));
 819:         $options = array_diff_key($options, array('fullBase' => null, 'pathPrefix' => null));
 820: 
 821:         if (!isset($options['alt'])) {
 822:             $options['alt'] = '';
 823:         }
 824: 
 825:         $url = false;
 826:         if (!empty($options['url'])) {
 827:             $url = $options['url'];
 828:             unset($options['url']);
 829:         }
 830: 
 831:         $image = sprintf($this->_tags['image'], $path, $this->_parseAttributes($options));
 832: 
 833:         if ($url) {
 834:             return sprintf($this->_tags['link'], $this->url($url), null, $image);
 835:         }
 836:         return $image;
 837:     }
 838: 
 839: /**
 840:  * Returns a row of formatted and named TABLE headers.
 841:  *
 842:  * @param array $names Array of tablenames. Each tablename also can be a key that points to an array with a set
 843:  *     of attributes to its specific tag
 844:  * @param array $trOptions HTML options for TR elements.
 845:  * @param array $thOptions HTML options for TH elements.
 846:  * @return string Completed table headers
 847:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::tableHeaders
 848:  */
 849:     public function tableHeaders($names, $trOptions = null, $thOptions = null) {
 850:         $out = array();
 851:         foreach ($names as $arg) {
 852:             if (!is_array($arg)) {
 853:                 $out[] = sprintf($this->_tags['tableheader'], $this->_parseAttributes($thOptions), $arg);
 854:             } else {
 855:                 $out[] = sprintf($this->_tags['tableheader'], $this->_parseAttributes(current($arg)), key($arg));
 856:             }
 857:         }
 858:         return sprintf($this->_tags['tablerow'], $this->_parseAttributes($trOptions), implode(' ', $out));
 859:     }
 860: 
 861: /**
 862:  * Returns a formatted string of table rows (TR's with TD's in them).
 863:  *
 864:  * @param array $data Array of table data
 865:  * @param array $oddTrOptions HTML options for odd TR elements if true useCount is used
 866:  * @param array $evenTrOptions HTML options for even TR elements
 867:  * @param bool $useCount adds class "column-$i"
 868:  * @param bool $continueOddEven If false, will use a non-static $count variable,
 869:  *    so that the odd/even count is reset to zero just for that call.
 870:  * @return string Formatted HTML
 871:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::tableCells
 872:  */
 873:     public function tableCells($data, $oddTrOptions = null, $evenTrOptions = null, $useCount = false, $continueOddEven = true) {
 874:         if (empty($data[0]) || !is_array($data[0])) {
 875:             $data = array($data);
 876:         }
 877: 
 878:         if ($oddTrOptions === true) {
 879:             $useCount = true;
 880:             $oddTrOptions = null;
 881:         }
 882: 
 883:         if ($evenTrOptions === false) {
 884:             $continueOddEven = false;
 885:             $evenTrOptions = null;
 886:         }
 887: 
 888:         if ($continueOddEven) {
 889:             static $count = 0;
 890:         } else {
 891:             $count = 0;
 892:         }
 893: 
 894:         foreach ($data as $line) {
 895:             $count++;
 896:             $cellsOut = array();
 897:             $i = 0;
 898:             foreach ($line as $cell) {
 899:                 $cellOptions = array();
 900: 
 901:                 if (is_array($cell)) {
 902:                     $cellOptions = $cell[1];
 903:                     $cell = $cell[0];
 904:                 } elseif ($useCount) {
 905:                     $cellOptions['class'] = 'column-' . ++$i;
 906:                 }
 907:                 $cellsOut[] = sprintf($this->_tags['tablecell'], $this->_parseAttributes($cellOptions), $cell);
 908:             }
 909:             $options = $this->_parseAttributes($count % 2 ? $oddTrOptions : $evenTrOptions);
 910:             $out[] = sprintf($this->_tags['tablerow'], $options, implode(' ', $cellsOut));
 911:         }
 912:         return implode("\n", $out);
 913:     }
 914: 
 915: /**
 916:  * Returns a formatted block tag, i.e DIV, SPAN, P.
 917:  *
 918:  * ### Options
 919:  *
 920:  * - `escape` Whether or not the contents should be html_entity escaped.
 921:  *
 922:  * @param string $name Tag name.
 923:  * @param string $text String content that will appear inside the div element.
 924:  *   If null, only a start tag will be printed
 925:  * @param array $options Additional HTML attributes of the DIV tag, see above.
 926:  * @return string The formatted tag element
 927:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::tag
 928:  */
 929:     public function tag($name, $text = null, $options = array()) {
 930:         if (empty($name)) {
 931:             return $text;
 932:         }
 933:         if (isset($options['escape']) && $options['escape']) {
 934:             $text = h($text);
 935:             unset($options['escape']);
 936:         }
 937:         if ($text === null) {
 938:             $tag = 'tagstart';
 939:         } else {
 940:             $tag = 'tag';
 941:         }
 942:         return sprintf($this->_tags[$tag], $name, $this->_parseAttributes($options), $text, $name);
 943:     }
 944: 
 945: /**
 946:  * Returns a formatted existent block of $tags
 947:  *
 948:  * @param string $tag Tag name
 949:  * @return string Formatted block
 950:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::useTag
 951:  */
 952:     public function useTag($tag) {
 953:         if (!isset($this->_tags[$tag])) {
 954:             return '';
 955:         }
 956:         $args = func_get_args();
 957:         array_shift($args);
 958:         foreach ($args as &$arg) {
 959:             if (is_array($arg)) {
 960:                 $arg = $this->_parseAttributes($arg);
 961:             }
 962:         }
 963:         return vsprintf($this->_tags[$tag], $args);
 964:     }
 965: 
 966: /**
 967:  * Returns a formatted DIV tag for HTML FORMs.
 968:  *
 969:  * ### Options
 970:  *
 971:  * - `escape` Whether or not the contents should be html_entity escaped.
 972:  *
 973:  * @param string $class CSS class name of the div element.
 974:  * @param string $text String content that will appear inside the div element.
 975:  *   If null, only a start tag will be printed
 976:  * @param array $options Additional HTML attributes of the DIV tag
 977:  * @return string The formatted DIV element
 978:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::div
 979:  */
 980:     public function div($class = null, $text = null, $options = array()) {
 981:         if (!empty($class)) {
 982:             $options['class'] = $class;
 983:         }
 984:         return $this->tag('div', $text, $options);
 985:     }
 986: 
 987: /**
 988:  * Returns a formatted P tag.
 989:  *
 990:  * ### Options
 991:  *
 992:  * - `escape` Whether or not the contents should be html_entity escaped.
 993:  *
 994:  * @param string $class CSS class name of the p element.
 995:  * @param string $text String content that will appear inside the p element.
 996:  * @param array $options Additional HTML attributes of the P tag
 997:  * @return string The formatted P element
 998:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::para
 999:  */
1000:     public function para($class, $text, $options = array()) {
1001:         if (isset($options['escape'])) {
1002:             $text = h($text);
1003:         }
1004:         if ($class && !empty($class)) {
1005:             $options['class'] = $class;
1006:         }
1007:         $tag = 'para';
1008:         if ($text === null) {
1009:             $tag = 'parastart';
1010:         }
1011:         return sprintf($this->_tags[$tag], $this->_parseAttributes($options), $text);
1012:     }
1013: 
1014: /**
1015:  * Returns an audio/video element
1016:  *
1017:  * ### Usage
1018:  *
1019:  * Using an audio file:
1020:  *
1021:  * `echo $this->Html->media('audio.mp3', array('fullBase' => true));`
1022:  *
1023:  * Outputs:
1024:  *
1025:  * `<video src="http://www.somehost.com/files/audio.mp3">Fallback text</video>`
1026:  *
1027:  * Using a video file:
1028:  *
1029:  * `echo $this->Html->media('video.mp4', array('text' => 'Fallback text'));`
1030:  *
1031:  * Outputs:
1032:  *
1033:  * `<video src="/files/video.mp4">Fallback text</video>`
1034:  *
1035:  * Using multiple video files:
1036:  *
1037:  * ```
1038:  * echo $this->Html->media(
1039:  *      array('video.mp4', array('src' => 'video.ogv', 'type' => "video/ogg; codecs='theora, vorbis'")),
1040:  *      array('tag' => 'video', 'autoplay')
1041:  * );
1042:  * ```
1043:  *
1044:  * Outputs:
1045:  *
1046:  * ```
1047:  * <video autoplay="autoplay">
1048:  *      <source src="/files/video.mp4" type="video/mp4"/>
1049:  *      <source src="/files/video.ogv" type="video/ogv; codecs='theora, vorbis'"/>
1050:  * </video>
1051:  * ```
1052:  *
1053:  * ### Options
1054:  *
1055:  * - `tag` Type of media element to generate, either "audio" or "video".
1056:  *  If tag is not provided it's guessed based on file's mime type.
1057:  * - `text` Text to include inside the audio/video tag
1058:  * - `pathPrefix` Path prefix to use for relative URLs, defaults to 'files/'
1059:  * - `fullBase` If provided the src attribute will get a full address including domain name
1060:  *
1061:  * @param string|array $path Path to the video file, relative to the webroot/{$options['pathPrefix']} directory.
1062:  *  Or an array where each item itself can be a path string or an associate array containing keys `src` and `type`
1063:  * @param array $options Array of HTML attributes, and special options above.
1064:  * @return string Generated media element
1065:  */
1066:     public function media($path, $options = array()) {
1067:         $options += array(
1068:             'tag' => null,
1069:             'pathPrefix' => 'files/',
1070:             'text' => ''
1071:         );
1072: 
1073:         if (!empty($options['tag'])) {
1074:             $tag = $options['tag'];
1075:         } else {
1076:             $tag = null;
1077:         }
1078: 
1079:         if (is_array($path)) {
1080:             $sourceTags = '';
1081:             foreach ($path as &$source) {
1082:                 if (is_string($source)) {
1083:                     $source = array(
1084:                         'src' => $source,
1085:                     );
1086:                 }
1087:                 if (!isset($source['type'])) {
1088:                     $ext = pathinfo($source['src'], PATHINFO_EXTENSION);
1089:                     $source['type'] = $this->response->getMimeType($ext);
1090:                 }
1091:                 $source['src'] = $this->assetUrl($source['src'], $options);
1092:                 $sourceTags .= $this->useTag('tagselfclosing', 'source', $source);
1093:             }
1094:             unset($source);
1095:             $options['text'] = $sourceTags . $options['text'];
1096:             unset($options['fullBase']);
1097:         } else {
1098:             if (empty($path) && !empty($options['src'])) {
1099:                 $path = $options['src'];
1100:             }
1101:             $options['src'] = $this->assetUrl($path, $options);
1102:         }
1103: 
1104:         if ($tag === null) {
1105:             if (is_array($path)) {
1106:                 $mimeType = $path[0]['type'];
1107:             } else {
1108:                 $mimeType = $this->response->getMimeType(pathinfo($path, PATHINFO_EXTENSION));
1109:             }
1110:             if (preg_match('#^video/#', $mimeType)) {
1111:                 $tag = 'video';
1112:             } else {
1113:                 $tag = 'audio';
1114:             }
1115:         }
1116: 
1117:         if (isset($options['poster'])) {
1118:             $options['poster'] = $this->assetUrl($options['poster'], array('pathPrefix' => Configure::read('App.imageBaseUrl')) + $options);
1119:         }
1120:         $text = $options['text'];
1121: 
1122:         $options = array_diff_key($options, array(
1123:             'tag' => null,
1124:             'fullBase' => null,
1125:             'pathPrefix' => null,
1126:             'text' => null
1127:         ));
1128:         return $this->tag($tag, $text, $options);
1129:     }
1130: 
1131: /**
1132:  * Build a nested list (UL/OL) out of an associative array.
1133:  *
1134:  * @param array $list Set of elements to list
1135:  * @param array $options Additional HTML attributes of the list (ol/ul) tag or if ul/ol use that as tag
1136:  * @param array $itemOptions Additional HTML attributes of the list item (LI) tag
1137:  * @param string $tag Type of list tag to use (ol/ul)
1138:  * @return string The nested list
1139:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::nestedList
1140:  */
1141:     public function nestedList($list, $options = array(), $itemOptions = array(), $tag = 'ul') {
1142:         if (is_string($options)) {
1143:             $tag = $options;
1144:             $options = array();
1145:         }
1146:         $items = $this->_nestedListItem($list, $options, $itemOptions, $tag);
1147:         return sprintf($this->_tags[$tag], $this->_parseAttributes($options), $items);
1148:     }
1149: 
1150: /**
1151:  * Internal function to build a nested list (UL/OL) out of an associative array.
1152:  *
1153:  * @param array $items Set of elements to list
1154:  * @param array $options Additional HTML attributes of the list (ol/ul) tag
1155:  * @param array $itemOptions Additional HTML attributes of the list item (LI) tag
1156:  * @param string $tag Type of list tag to use (ol/ul)
1157:  * @return string The nested list element
1158:  * @see HtmlHelper::nestedList()
1159:  */
1160:     protected function _nestedListItem($items, $options, $itemOptions, $tag) {
1161:         $out = '';
1162: 
1163:         $index = 1;
1164:         foreach ($items as $key => $item) {
1165:             if (is_array($item)) {
1166:                 $item = $key . $this->nestedList($item, $options, $itemOptions, $tag);
1167:             }
1168:             if (isset($itemOptions['even']) && $index % 2 === 0) {
1169:                 $itemOptions['class'] = $itemOptions['even'];
1170:             } elseif (isset($itemOptions['odd']) && $index % 2 !== 0) {
1171:                 $itemOptions['class'] = $itemOptions['odd'];
1172:             }
1173:             $out .= sprintf($this->_tags['li'], $this->_parseAttributes($itemOptions, array('even', 'odd')), $item);
1174:             $index++;
1175:         }
1176:         return $out;
1177:     }
1178: 
1179: /**
1180:  * Load Html tag configuration.
1181:  *
1182:  * Loads a file from APP/Config that contains tag data. By default the file is expected
1183:  * to be compatible with PhpReader:
1184:  *
1185:  * `$this->Html->loadConfig('tags.php');`
1186:  *
1187:  * tags.php could look like:
1188:  *
1189:  * ```
1190:  * $tags = array(
1191:  *      'meta' => '<meta%s>'
1192:  * );
1193:  * ```
1194:  *
1195:  * If you wish to store tag definitions in another format you can give an array
1196:  * containing the file name, and reader class name:
1197:  *
1198:  * `$this->Html->loadConfig(array('tags.ini', 'ini'));`
1199:  *
1200:  * Its expected that the `tags` index will exist from any configuration file that is read.
1201:  * You can also specify the path to read the configuration file from, if APP/Config is not
1202:  * where the file is.
1203:  *
1204:  * `$this->Html->loadConfig('tags.php', APP . 'Lib' . DS);`
1205:  *
1206:  * Configuration files can define the following sections:
1207:  *
1208:  * - `tags` The tags to replace.
1209:  * - `minimizedAttributes` The attributes that are represented like `disabled="disabled"`
1210:  * - `docTypes` Additional doctypes to use.
1211:  * - `attributeFormat` Format for long attributes e.g. `'%s="%s"'`
1212:  * - `minimizedAttributeFormat` Format for minimized attributes e.g. `'%s="%s"'`
1213:  *
1214:  * @param string|array $configFile String with the config file (load using PhpReader) or an array with file and reader name
1215:  * @param string $path Path with config file
1216:  * @return mixed False to error or loaded configs
1217:  * @throws ConfigureException
1218:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#changing-the-tags-output-by-htmlhelper
1219:  */
1220:     public function loadConfig($configFile, $path = null) {
1221:         if (!$path) {
1222:             $path = APP . 'Config' . DS;
1223:         }
1224:         $file = null;
1225:         $reader = 'php';
1226: 
1227:         if (!is_array($configFile)) {
1228:             $file = $configFile;
1229:         } elseif (isset($configFile[0])) {
1230:             $file = $configFile[0];
1231:             if (isset($configFile[1])) {
1232:                 $reader = $configFile[1];
1233:             }
1234:         } else {
1235:             throw new ConfigureException(__d('cake_dev', 'Cannot load the configuration file. Wrong "configFile" configuration.'));
1236:         }
1237: 
1238:         $readerClass = Inflector::camelize($reader) . 'Reader';
1239:         App::uses($readerClass, 'Configure');
1240:         if (!class_exists($readerClass)) {
1241:             throw new ConfigureException(__d('cake_dev', 'Cannot load the configuration file. Unknown reader.'));
1242:         }
1243: 
1244:         $readerObj = new $readerClass($path);
1245:         $configs = $readerObj->read($file);
1246:         if (isset($configs['tags']) && is_array($configs['tags'])) {
1247:             $this->_tags = $configs['tags'] + $this->_tags;
1248:         }
1249:         if (isset($configs['minimizedAttributes']) && is_array($configs['minimizedAttributes'])) {
1250:             $this->_minimizedAttributes = $configs['minimizedAttributes'] + $this->_minimizedAttributes;
1251:         }
1252:         if (isset($configs['docTypes']) && is_array($configs['docTypes'])) {
1253:             $this->_docTypes = $configs['docTypes'] + $this->_docTypes;
1254:         }
1255:         if (isset($configs['attributeFormat'])) {
1256:             $this->_attributeFormat = $configs['attributeFormat'];
1257:         }
1258:         if (isset($configs['minimizedAttributeFormat'])) {
1259:             $this->_minimizedAttributeFormat = $configs['minimizedAttributeFormat'];
1260:         }
1261:         return $configs;
1262:     }
1263: 
1264: }
1265: 
OpenHub
Rackspace
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Reporting Security Issues
  • Privacy Policy
  • Logos & Trademarks
  • Community
  • Get Involved
  • Issues (GitHub)
  • Bakery
  • Featured Resources
  • Training
  • Meetups
  • My CakePHP
  • CakeFest
  • Newsletter
  • Linkedin
  • YouTube
  • Facebook
  • Twitter
  • Mastodon
  • Help & Support
  • Forum
  • Stack Overflow
  • Slack
  • Paid Support

Generated using CakePHP API Docs