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.10 API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 2.10
      • 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
  • None

Classes

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