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

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 2.3
      • 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 files that have been included once
 116:  *
 117:  * @var array
 118:  */
 119:     protected $_includedScripts = 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 void
 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:     }
 184: 
 185: /**
 186:  * Returns a doctype string.
 187:  *
 188:  * Possible doctypes:
 189:  *
 190:  *  - html4-strict:  HTML4 Strict.
 191:  *  - html4-trans:  HTML4 Transitional.
 192:  *  - html4-frame:  HTML4 Frameset.
 193:  *  - html5: HTML5. Default value.
 194:  *  - xhtml-strict: XHTML1 Strict.
 195:  *  - xhtml-trans: XHTML1 Transitional.
 196:  *  - xhtml-frame: XHTML1 Frameset.
 197:  *  - xhtml11: XHTML1.1.
 198:  *
 199:  * @param string $type Doctype to use.
 200:  * @return string Doctype string
 201:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::docType
 202:  */
 203:     public function docType($type = 'html5') {
 204:         if (isset($this->_docTypes[$type])) {
 205:             return $this->_docTypes[$type];
 206:         }
 207:         return null;
 208:     }
 209: 
 210: /**
 211:  * Creates a link to an external resource and handles basic meta tags
 212:  *
 213:  * Create a meta tag that is output inline:
 214:  *
 215:  * `$this->Html->meta('icon', 'favicon.ico');
 216:  *
 217:  * Append the meta tag to `$scripts_for_layout`:
 218:  *
 219:  * `$this->Html->meta('description', 'A great page', array('inline' => false));`
 220:  *
 221:  * Append the meta tag to custom view block:
 222:  *
 223:  * `$this->Html->meta('description', 'A great page', array('block' => 'metaTags'));`
 224:  *
 225:  * ### Options
 226:  *
 227:  * - `inline` Whether or not the link element should be output inline. Set to false to
 228:  *   have the meta tag included in `$scripts_for_layout`, and appended to the 'meta' view block.
 229:  * - `block` Choose a custom block to append the meta tag to. Using this option
 230:  *   will override the inline option.
 231:  *
 232:  * @param string $type The title of the external resource
 233:  * @param string|array $url The address of the external resource or string for content attribute
 234:  * @param array $options Other attributes for the generated tag. If the type attribute is html,
 235:  *    rss, atom, or icon, the mime-type is returned.
 236:  * @return string A completed `<link />` element.
 237:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::meta
 238:  */
 239:     public function meta($type, $url = null, $options = array()) {
 240:         $options += array('inline' => true, 'block' => null);
 241:         if (!$options['inline'] && empty($options['block'])) {
 242:             $options['block'] = __FUNCTION__;
 243:         }
 244:         unset($options['inline']);
 245: 
 246:         if (!is_array($type)) {
 247:             $types = array(
 248:                 'rss' => array('type' => 'application/rss+xml', 'rel' => 'alternate', 'title' => $type, 'link' => $url),
 249:                 'atom' => array('type' => 'application/atom+xml', 'title' => $type, 'link' => $url),
 250:                 'icon' => array('type' => 'image/x-icon', 'rel' => 'icon', 'link' => $url),
 251:                 'keywords' => array('name' => 'keywords', 'content' => $url),
 252:                 'description' => array('name' => 'description', 'content' => $url),
 253:             );
 254: 
 255:             if ($type === 'icon' && $url === null) {
 256:                 $types['icon']['link'] = $this->webroot('favicon.ico');
 257:             }
 258: 
 259:             if (isset($types[$type])) {
 260:                 $type = $types[$type];
 261:             } elseif (!isset($options['type']) && $url !== null) {
 262:                 if (is_array($url) && isset($url['ext'])) {
 263:                     $type = $types[$url['ext']];
 264:                 } else {
 265:                     $type = $types['rss'];
 266:                 }
 267:             } elseif (isset($options['type']) && isset($types[$options['type']])) {
 268:                 $type = $types[$options['type']];
 269:                 unset($options['type']);
 270:             } else {
 271:                 $type = array();
 272:             }
 273:         }
 274: 
 275:         $options = array_merge($type, $options);
 276:         $out = null;
 277: 
 278:         if (isset($options['link'])) {
 279:             if (isset($options['rel']) && $options['rel'] === 'icon') {
 280:                 $out = sprintf($this->_tags['metalink'], $options['link'], $this->_parseAttributes($options, array('block', 'link'), ' ', ' '));
 281:                 $options['rel'] = 'shortcut icon';
 282:             } else {
 283:                 $options['link'] = $this->url($options['link'], true);
 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:  * - `confirm` JavaScript confirmation message.
 324:  *
 325:  * @param string $title The content to be wrapped by <a> tags.
 326:  * @param string|array $url Cake-relative URL or array of URL parameters, or external URL (starts with http://)
 327:  * @param array $options Array of HTML attributes.
 328:  * @param string $confirmMessage JavaScript confirmation message.
 329:  * @return string An `<a />` element.
 330:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::link
 331:  */
 332:     public function link($title, $url = null, $options = array(), $confirmMessage = false) {
 333:         $escapeTitle = true;
 334:         if ($url !== null) {
 335:             $url = $this->url($url);
 336:         } else {
 337:             $url = $this->url($title);
 338:             $title = htmlspecialchars_decode($url, ENT_QUOTES);
 339:             $title = h(urldecode($title));
 340:             $escapeTitle = false;
 341:         }
 342: 
 343:         if (isset($options['escape'])) {
 344:             $escapeTitle = $options['escape'];
 345:         }
 346: 
 347:         if ($escapeTitle === true) {
 348:             $title = h($title);
 349:         } elseif (is_string($escapeTitle)) {
 350:             $title = htmlentities($title, ENT_QUOTES, $escapeTitle);
 351:         }
 352: 
 353:         if (!empty($options['confirm'])) {
 354:             $confirmMessage = $options['confirm'];
 355:             unset($options['confirm']);
 356:         }
 357:         if ($confirmMessage) {
 358:             $confirmMessage = str_replace("'", "\'", $confirmMessage);
 359:             $confirmMessage = str_replace('"', '\"', $confirmMessage);
 360:             $options['onclick'] = "return confirm('{$confirmMessage}');";
 361:         } elseif (isset($options['default']) && !$options['default']) {
 362:             if (isset($options['onclick'])) {
 363:                 $options['onclick'] .= ' event.returnValue = false; return false;';
 364:             } else {
 365:                 $options['onclick'] = 'event.returnValue = false; return false;';
 366:             }
 367:             unset($options['default']);
 368:         }
 369:         return sprintf($this->_tags['link'], $url, $this->_parseAttributes($options), $title);
 370:     }
 371: 
 372: /**
 373:  * Creates a link element for CSS stylesheets.
 374:  *
 375:  * ### Usage
 376:  *
 377:  * Include one CSS file:
 378:  *
 379:  * `echo $this->Html->css('styles.css');`
 380:  *
 381:  * Include multiple CSS files:
 382:  *
 383:  * `echo $this->Html->css(array('one.css', 'two.css'));`
 384:  *
 385:  * Add the stylesheet to the `$scripts_for_layout` layout var:
 386:  *
 387:  * `$this->Html->css('styles.css', null, array('inline' => false));`
 388:  *
 389:  * Add the stylesheet to a custom block:
 390:  *
 391:  * `$this->Html->css('styles.css', null, array('block' => 'layoutCss'));`
 392:  *
 393:  * ### Options
 394:  *
 395:  * - `inline` If set to false, the generated tag will be appended to the 'css' block,
 396:  *   and included in the `$scripts_for_layout` layout variable. Defaults to true.
 397:  * - `block` Set the name of the block link/style tag will be appended to. This overrides the `inline`
 398:  *   option.
 399:  * - `plugin` False value will prevent parsing path as a plugin
 400:  * - `fullBase` If true the url will get a full address for the css file.
 401:  *
 402:  * @param string|array $path The name of a CSS style sheet or an array containing names of
 403:  *   CSS stylesheets. If `$path` is prefixed with '/', the path will be relative to the webroot
 404:  *   of your application. Otherwise, the path will be relative to your CSS path, usually webroot/css.
 405:  * @param string $rel Rel attribute. Defaults to "stylesheet". If equal to 'import' the stylesheet will be imported.
 406:  * @param array $options Array of HTML attributes.
 407:  * @return string CSS <link /> or <style /> tag, depending on the type of link.
 408:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::css
 409:  */
 410:     public function css($path, $rel = null, $options = array()) {
 411:         $options += array('block' => null, 'inline' => true);
 412:         if (!$options['inline'] && empty($options['block'])) {
 413:             $options['block'] = __FUNCTION__;
 414:         }
 415:         unset($options['inline']);
 416: 
 417:         if (is_array($path)) {
 418:             $out = '';
 419:             foreach ($path as $i) {
 420:                 $out .= "\n\t" . $this->css($i, $rel, $options);
 421:             }
 422:             if (empty($options['block'])) {
 423:                 return $out . "\n";
 424:             }
 425:             return;
 426:         }
 427: 
 428:         if (strpos($path, '//') !== false) {
 429:             $url = $path;
 430:         } else {
 431:             $url = $this->assetUrl($path, $options + array('pathPrefix' => CSS_URL, 'ext' => '.css'));
 432:             $options = array_diff_key($options, array('fullBase' => null));
 433: 
 434:             if (Configure::read('Asset.filter.css')) {
 435:                 $pos = strpos($url, CSS_URL);
 436:                 if ($pos !== false) {
 437:                     $url = substr($url, 0, $pos) . 'ccss/' . substr($url, $pos + strlen(CSS_URL));
 438:                 }
 439:             }
 440:         }
 441: 
 442:         if ($rel === 'import') {
 443:             $out = sprintf($this->_tags['style'], $this->_parseAttributes($options, array('inline', 'block'), '', ' '), '@import url(' . $url . ');');
 444:         } else {
 445:             if (!$rel) {
 446:                 $rel = 'stylesheet';
 447:             }
 448:             $out = sprintf($this->_tags['css'], $rel, $url, $this->_parseAttributes($options, array('inline', 'block'), '', ' '));
 449:         }
 450: 
 451:         if (empty($options['block'])) {
 452:             return $out;
 453:         }
 454:         $this->_View->append($options['block'], $out);
 455:     }
 456: 
 457: /**
 458:  * Returns one or many `<script>` tags depending on the number of scripts given.
 459:  *
 460:  * If the filename is prefixed with "/", the path will be relative to the base path of your
 461:  * application. Otherwise, the path will be relative to your JavaScript path, usually webroot/js.
 462:  *
 463:  *
 464:  * ### Usage
 465:  *
 466:  * Include one script file:
 467:  *
 468:  * `echo $this->Html->script('styles.js');`
 469:  *
 470:  * Include multiple script files:
 471:  *
 472:  * `echo $this->Html->script(array('one.js', 'two.js'));`
 473:  *
 474:  * Add the script file to the `$scripts_for_layout` layout var:
 475:  *
 476:  * `$this->Html->script('styles.js', array('inline' => false));`
 477:  *
 478:  * Add the script file to a custom block:
 479:  *
 480:  * `$this->Html->script('styles.js', null, array('block' => 'bodyScript'));`
 481:  *
 482:  * ### Options
 483:  *
 484:  * - `inline` Whether script should be output inline or into `$scripts_for_layout`. When set to false,
 485:  *   the script tag will be appended to the 'script' view block as well as `$scripts_for_layout`.
 486:  * - `block` The name of the block you want the script appended to. Leave undefined to output inline.
 487:  *   Using this option will override the inline option.
 488:  * - `once` Whether or not the script should be checked for uniqueness. If true scripts will only be
 489:  *   included once, use false to allow the same script to be included more than once per request.
 490:  * - `plugin` False value will prevent parsing path as a plugin
 491:  * - `fullBase` If true the url will get a full address for the script file.
 492:  *
 493:  * @param string|array $url String or array of javascript files to include
 494:  * @param array|boolean $options Array of options, and html attributes see above. If boolean sets $options['inline'] = value
 495:  * @return mixed String of `<script />` tags or null if $inline is false or if $once is true and the file has been
 496:  *   included before.
 497:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::script
 498:  */
 499:     public function script($url, $options = array()) {
 500:         if (is_bool($options)) {
 501:             list($inline, $options) = array($options, array());
 502:             $options['inline'] = $inline;
 503:         }
 504:         $options = array_merge(array('block' => null, 'inline' => true, 'once' => true), $options);
 505:         if (!$options['inline'] && empty($options['block'])) {
 506:             $options['block'] = __FUNCTION__;
 507:         }
 508:         unset($options['inline']);
 509: 
 510:         if (is_array($url)) {
 511:             $out = '';
 512:             foreach ($url as $i) {
 513:                 $out .= "\n\t" . $this->script($i, $options);
 514:             }
 515:             if (empty($options['block'])) {
 516:                 return $out . "\n";
 517:             }
 518:             return null;
 519:         }
 520:         if ($options['once'] && isset($this->_includedScripts[$url])) {
 521:             return null;
 522:         }
 523:         $this->_includedScripts[$url] = true;
 524: 
 525:         if (strpos($url, '//') === false) {
 526:             $url = $this->assetUrl($url, $options + array('pathPrefix' => JS_URL, 'ext' => '.js'));
 527:             $options = array_diff_key($options, array('fullBase' => null));
 528: 
 529:             if (Configure::read('Asset.filter.js')) {
 530:                 $url = str_replace(JS_URL, 'cjs/', $url);
 531:             }
 532:         }
 533:         $attributes = $this->_parseAttributes($options, array('block', 'once'), ' ');
 534:         $out = sprintf($this->_tags['javascriptlink'], $url, $attributes);
 535: 
 536:         if (empty($options['block'])) {
 537:             return $out;
 538:         } else {
 539:             $this->_View->append($options['block'], $out);
 540:         }
 541:     }
 542: 
 543: /**
 544:  * Wrap $script in a script tag.
 545:  *
 546:  * ### Options
 547:  *
 548:  * - `safe` (boolean) Whether or not the $script should be wrapped in <![CDATA[ ]]>
 549:  * - `inline` (boolean) Whether or not the $script should be added to
 550:  *   `$scripts_for_layout` / `script` block, or output inline. (Deprecated, use `block` instead)
 551:  * - `block` Which block you want this script block appended to.
 552:  *   Defaults to `script`.
 553:  *
 554:  * @param string $script The script to wrap
 555:  * @param array $options The options to use. Options not listed above will be
 556:  *    treated as HTML attributes.
 557:  * @return mixed string or null depending on the value of `$options['block']`
 558:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::scriptBlock
 559:  */
 560:     public function scriptBlock($script, $options = array()) {
 561:         $options += array('type' => 'text/javascript', 'safe' => true, 'inline' => true);
 562:         if ($options['safe']) {
 563:             $script = "\n" . '//<![CDATA[' . "\n" . $script . "\n" . '//]]>' . "\n";
 564:         }
 565:         if (!$options['inline'] && empty($options['block'])) {
 566:             $options['block'] = 'script';
 567:         }
 568:         unset($options['inline'], $options['safe']);
 569: 
 570:         $attributes = $this->_parseAttributes($options, array('block'), ' ');
 571:         $out = sprintf($this->_tags['javascriptblock'], $attributes, $script);
 572: 
 573:         if (empty($options['block'])) {
 574:             return $out;
 575:         } else {
 576:             $this->_View->append($options['block'], $out);
 577:         }
 578:     }
 579: 
 580: /**
 581:  * Begin a script block that captures output until HtmlHelper::scriptEnd()
 582:  * is called. This capturing block will capture all output between the methods
 583:  * and create a scriptBlock from it.
 584:  *
 585:  * ### Options
 586:  *
 587:  * - `safe` Whether the code block should contain a CDATA
 588:  * - `inline` Should the generated script tag be output inline or in `$scripts_for_layout`
 589:  *
 590:  * @param array $options Options for the code block.
 591:  * @return void
 592:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::scriptStart
 593:  */
 594:     public function scriptStart($options = array()) {
 595:         $options += array('safe' => true, 'inline' => true);
 596:         $this->_scriptBlockOptions = $options;
 597:         ob_start();
 598:         return null;
 599:     }
 600: 
 601: /**
 602:  * End a Buffered section of Javascript capturing.
 603:  * Generates a script tag inline or in `$scripts_for_layout` depending on the settings
 604:  * used when the scriptBlock was started
 605:  *
 606:  * @return mixed depending on the settings of scriptStart() either a script tag or null
 607:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::scriptEnd
 608:  */
 609:     public function scriptEnd() {
 610:         $buffer = ob_get_clean();
 611:         $options = $this->_scriptBlockOptions;
 612:         $this->_scriptBlockOptions = array();
 613:         return $this->scriptBlock($buffer, $options);
 614:     }
 615: 
 616: /**
 617:  * Builds CSS style data from an array of CSS properties
 618:  *
 619:  * ### Usage:
 620:  *
 621:  * {{{
 622:  * echo $this->Html->style(array('margin' => '10px', 'padding' => '10px'), true);
 623:  *
 624:  * // creates
 625:  * 'margin:10px;padding:10px;'
 626:  * }}}
 627:  *
 628:  * @param array $data Style data array, keys will be used as property names, values as property values.
 629:  * @param boolean $oneline Whether or not the style block should be displayed on one line.
 630:  * @return string CSS styling data
 631:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::style
 632:  */
 633:     public function style($data, $oneline = true) {
 634:         if (!is_array($data)) {
 635:             return $data;
 636:         }
 637:         $out = array();
 638:         foreach ($data as $key => $value) {
 639:             $out[] = $key . ':' . $value . ';';
 640:         }
 641:         if ($oneline) {
 642:             return implode(' ', $out);
 643:         }
 644:         return implode("\n", $out);
 645:     }
 646: 
 647: /**
 648:  * Returns the breadcrumb trail as a sequence of &raquo;-separated links.
 649:  *
 650:  * If `$startText` is an array, the accepted keys are:
 651:  *
 652:  * - `text` Define the text/content for the link.
 653:  * - `url` Define the target of the created link.
 654:  *
 655:  * All other keys will be passed to HtmlHelper::link() as the `$options` parameter.
 656:  *
 657:  * @param string $separator Text to separate crumbs.
 658:  * @param string|array|boolean $startText This will be the first crumb, if false it defaults to first crumb in array. Can
 659:  *   also be an array, see above for details.
 660:  * @return string Composed bread crumbs
 661:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#creating-breadcrumb-trails-with-htmlhelper
 662:  */
 663:     public function getCrumbs($separator = '&raquo;', $startText = false) {
 664:         $crumbs = $this->_prepareCrumbs($startText);
 665:         if (!empty($crumbs)) {
 666:             $out = array();
 667:             foreach ($crumbs as $crumb) {
 668:                 if (!empty($crumb[1])) {
 669:                     $out[] = $this->link($crumb[0], $crumb[1], $crumb[2]);
 670:                 } else {
 671:                     $out[] = $crumb[0];
 672:                 }
 673:             }
 674:             return implode($separator, $out);
 675:         }
 676:         return null;
 677:     }
 678: 
 679: /**
 680:  * Returns breadcrumbs as a (x)html list
 681:  *
 682:  * This method uses HtmlHelper::tag() to generate list and its elements. Works
 683:  * similar to HtmlHelper::getCrumbs(), so it uses options which every
 684:  * crumb was added with.
 685:  *
 686:  * ### Options
 687:  * - `separator` Separator content to insert in between breadcrumbs, defaults to ''
 688:  * - `firstClass` Class for wrapper tag on the first breadcrumb, defaults to 'first'
 689:  * - `lastClass` Class for wrapper tag on current active page, defaults to 'last'
 690:  *
 691:  * @param array $options Array of html attributes to apply to the generated list elements.
 692:  * @param string|array|boolean $startText This will be the first crumb, if false it defaults to first crumb in array. Can
 693:  *   also be an array, see `HtmlHelper::getCrumbs` for details.
 694:  * @return string breadcrumbs html list
 695:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#creating-breadcrumb-trails-with-htmlhelper
 696:  */
 697:     public function getCrumbList($options = array(), $startText = false) {
 698:         $defaults = array('firstClass' => 'first', 'lastClass' => 'last', 'separator' => '');
 699:         $options = array_merge($defaults, (array)$options);
 700:         $firstClass = $options['firstClass'];
 701:         $lastClass = $options['lastClass'];
 702:         $separator = $options['separator'];
 703:         unset($options['firstClass'], $options['lastClass'], $options['separator']);
 704: 
 705:         $crumbs = $this->_prepareCrumbs($startText);
 706:         if (empty($crumbs)) {
 707:             return null;
 708:         }
 709: 
 710:         $result = '';
 711:         $crumbCount = count($crumbs);
 712:         $ulOptions = $options;
 713:         foreach ($crumbs as $which => $crumb) {
 714:             $options = array();
 715:             if (empty($crumb[1])) {
 716:                 $elementContent = $crumb[0];
 717:             } else {
 718:                 $elementContent = $this->link($crumb[0], $crumb[1], $crumb[2]);
 719:             }
 720:             if (!$which && $firstClass !== false) {
 721:                 $options['class'] = $firstClass;
 722:             } elseif ($which == $crumbCount - 1 && $lastClass !== false) {
 723:                 $options['class'] = $lastClass;
 724:             }
 725:             if (!empty($separator) && ($crumbCount - $which >= 2)) {
 726:                 $elementContent .= $separator;
 727:             }
 728:             $result .= $this->tag('li', $elementContent, $options);
 729:         }
 730:         return $this->tag('ul', $result, $ulOptions);
 731:     }
 732: 
 733: /**
 734:  * Prepends startText to crumbs array if set
 735:  *
 736:  * @param string $startText Text to prepend
 737:  * @return array Crumb list including startText (if provided)
 738:  */
 739:     protected function _prepareCrumbs($startText) {
 740:         $crumbs = $this->_crumbs;
 741:         if ($startText) {
 742:             if (!is_array($startText)) {
 743:                 $startText = array(
 744:                     'url' => '/',
 745:                     'text' => $startText
 746:                 );
 747:             }
 748:             $startText += array('url' => '/', 'text' => __d('cake', 'Home'));
 749:             list($url, $text) = array($startText['url'], $startText['text']);
 750:             unset($startText['url'], $startText['text']);
 751:             array_unshift($crumbs, array($text, $url, $startText));
 752:         }
 753:         return $crumbs;
 754:     }
 755: 
 756: /**
 757:  * Creates a formatted IMG element.
 758:  *
 759:  * This method will set an empty alt attribute if one is not supplied.
 760:  *
 761:  * ### Usage:
 762:  *
 763:  * Create a regular image:
 764:  *
 765:  * `echo $this->Html->image('cake_icon.png', array('alt' => 'CakePHP'));`
 766:  *
 767:  * Create an image link:
 768:  *
 769:  * `echo $this->Html->image('cake_icon.png', array('alt' => 'CakePHP', 'url' => 'http://cakephp.org'));`
 770:  *
 771:  * ### Options:
 772:  *
 773:  * - `url` If provided an image link will be generated and the link will point at
 774:  *   `$options['url']`.
 775:  * - `fullBase` If true the src attribute will get a full address for the image file.
 776:  * - `plugin` False value will prevent parsing path as a plugin
 777:  *
 778:  * @param string $path Path to the image file, relative to the app/webroot/img/ directory.
 779:  * @param array $options Array of HTML attributes. See above for special options.
 780:  * @return string completed img tag
 781:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::image
 782:  */
 783:     public function image($path, $options = array()) {
 784:         $path = $this->assetUrl($path, $options + array('pathPrefix' => IMAGES_URL));
 785:         $options = array_diff_key($options, array('fullBase' => null, 'pathPrefix' => null));
 786: 
 787:         if (!isset($options['alt'])) {
 788:             $options['alt'] = '';
 789:         }
 790: 
 791:         $url = false;
 792:         if (!empty($options['url'])) {
 793:             $url = $options['url'];
 794:             unset($options['url']);
 795:         }
 796: 
 797:         $image = sprintf($this->_tags['image'], $path, $this->_parseAttributes($options, null, '', ' '));
 798: 
 799:         if ($url) {
 800:             return sprintf($this->_tags['link'], $this->url($url), null, $image);
 801:         }
 802:         return $image;
 803:     }
 804: 
 805: /**
 806:  * Returns a row of formatted and named TABLE headers.
 807:  *
 808:  * @param array $names Array of tablenames. Each tablename also can be a key that points to an array with a set
 809:  *     of attributes to its specific tag
 810:  * @param array $trOptions HTML options for TR elements.
 811:  * @param array $thOptions HTML options for TH elements.
 812:  * @return string Completed table headers
 813:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::tableHeaders
 814:  */
 815:     public function tableHeaders($names, $trOptions = null, $thOptions = null) {
 816:         $out = array();
 817:         foreach ($names as $arg) {
 818:             if (!is_array($arg)) {
 819:                 $out[] = sprintf($this->_tags['tableheader'], $this->_parseAttributes($thOptions), $arg);
 820:             } else {
 821:                 $out[] = sprintf($this->_tags['tableheader'], $this->_parseAttributes(current($arg)), key($arg));
 822:             }
 823:         }
 824:         return sprintf($this->_tags['tablerow'], $this->_parseAttributes($trOptions), implode(' ', $out));
 825:     }
 826: 
 827: /**
 828:  * Returns a formatted string of table rows (TR's with TD's in them).
 829:  *
 830:  * @param array $data Array of table data
 831:  * @param array $oddTrOptions HTML options for odd TR elements if true useCount is used
 832:  * @param array $evenTrOptions HTML options for even TR elements
 833:  * @param boolean $useCount adds class "column-$i"
 834:  * @param boolean $continueOddEven If false, will use a non-static $count variable,
 835:  *    so that the odd/even count is reset to zero just for that call.
 836:  * @return string Formatted HTML
 837:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::tableCells
 838:  */
 839:     public function tableCells($data, $oddTrOptions = null, $evenTrOptions = null, $useCount = false, $continueOddEven = true) {
 840:         if (empty($data[0]) || !is_array($data[0])) {
 841:             $data = array($data);
 842:         }
 843: 
 844:         if ($oddTrOptions === true) {
 845:             $useCount = true;
 846:             $oddTrOptions = null;
 847:         }
 848: 
 849:         if ($evenTrOptions === false) {
 850:             $continueOddEven = false;
 851:             $evenTrOptions = null;
 852:         }
 853: 
 854:         if ($continueOddEven) {
 855:             static $count = 0;
 856:         } else {
 857:             $count = 0;
 858:         }
 859: 
 860:         foreach ($data as $line) {
 861:             $count++;
 862:             $cellsOut = array();
 863:             $i = 0;
 864:             foreach ($line as $cell) {
 865:                 $cellOptions = array();
 866: 
 867:                 if (is_array($cell)) {
 868:                     $cellOptions = $cell[1];
 869:                     $cell = $cell[0];
 870:                 } elseif ($useCount) {
 871:                     $cellOptions['class'] = 'column-' . ++$i;
 872:                 }
 873:                 $cellsOut[] = sprintf($this->_tags['tablecell'], $this->_parseAttributes($cellOptions), $cell);
 874:             }
 875:             $options = $this->_parseAttributes($count % 2 ? $oddTrOptions : $evenTrOptions);
 876:             $out[] = sprintf($this->_tags['tablerow'], $options, implode(' ', $cellsOut));
 877:         }
 878:         return implode("\n", $out);
 879:     }
 880: 
 881: /**
 882:  * Returns a formatted block tag, i.e DIV, SPAN, P.
 883:  *
 884:  * ### Options
 885:  *
 886:  * - `escape` Whether or not the contents should be html_entity escaped.
 887:  *
 888:  * @param string $name Tag name.
 889:  * @param string $text String content that will appear inside the div element.
 890:  *   If null, only a start tag will be printed
 891:  * @param array $options Additional HTML attributes of the DIV tag, see above.
 892:  * @return string The formatted tag element
 893:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::tag
 894:  */
 895:     public function tag($name, $text = null, $options = array()) {
 896:         if (empty($name)) {
 897:             return $text;
 898:         }
 899:         if (is_array($options) && isset($options['escape']) && $options['escape']) {
 900:             $text = h($text);
 901:             unset($options['escape']);
 902:         }
 903:         if (!is_array($options)) {
 904:             $options = array('class' => $options);
 905:         }
 906:         if ($text === null) {
 907:             $tag = 'tagstart';
 908:         } else {
 909:             $tag = 'tag';
 910:         }
 911:         return sprintf($this->_tags[$tag], $name, $this->_parseAttributes($options, null, ' ', ''), $text, $name);
 912:     }
 913: 
 914: /**
 915:  * Returns a formatted existent block of $tags
 916:  *
 917:  * @param string $tag Tag name
 918:  * @return string Formatted block
 919:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::useTag
 920:  */
 921:     public function useTag($tag) {
 922:         if (!isset($this->_tags[$tag])) {
 923:             return '';
 924:         }
 925:         $args = func_get_args();
 926:         array_shift($args);
 927:         foreach ($args as &$arg) {
 928:             if (is_array($arg)) {
 929:                 $arg = $this->_parseAttributes($arg, null, ' ', '');
 930:             }
 931:         }
 932:         return vsprintf($this->_tags[$tag], $args);
 933:     }
 934: 
 935: /**
 936:  * Returns a formatted DIV tag for HTML FORMs.
 937:  *
 938:  * ### Options
 939:  *
 940:  * - `escape` Whether or not the contents should be html_entity escaped.
 941:  *
 942:  * @param string $class CSS class name of the div element.
 943:  * @param string $text String content that will appear inside the div element.
 944:  *   If null, only a start tag will be printed
 945:  * @param array $options Additional HTML attributes of the DIV tag
 946:  * @return string The formatted DIV element
 947:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::div
 948:  */
 949:     public function div($class = null, $text = null, $options = array()) {
 950:         if (!empty($class)) {
 951:             $options['class'] = $class;
 952:         }
 953:         return $this->tag('div', $text, $options);
 954:     }
 955: 
 956: /**
 957:  * Returns a formatted P tag.
 958:  *
 959:  * ### Options
 960:  *
 961:  * - `escape` Whether or not the contents should be html_entity escaped.
 962:  *
 963:  * @param string $class CSS class name of the p element.
 964:  * @param string $text String content that will appear inside the p element.
 965:  * @param array $options Additional HTML attributes of the P tag
 966:  * @return string The formatted P element
 967:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::para
 968:  */
 969:     public function para($class, $text, $options = array()) {
 970:         if (isset($options['escape'])) {
 971:             $text = h($text);
 972:         }
 973:         if ($class && !empty($class)) {
 974:             $options['class'] = $class;
 975:         }
 976:         $tag = 'para';
 977:         if ($text === null) {
 978:             $tag = 'parastart';
 979:         }
 980:         return sprintf($this->_tags[$tag], $this->_parseAttributes($options, null, ' ', ''), $text);
 981:     }
 982: 
 983: /**
 984:  * Returns an audio/video element
 985:  *
 986:  * ### Usage
 987:  *
 988:  * Using an audio file:
 989:  *
 990:  * `echo $this->Html->media('audio.mp3', array('fullBase' => true));`
 991:  *
 992:  * Outputs:
 993:  *
 994:  * `<video src="http://www.somehost.com/files/audio.mp3">Fallback text</video>`
 995:  *
 996:  * Using a video file:
 997:  *
 998:  * `echo $this->Html->media('video.mp4', array('text' => 'Fallback text'));`
 999:  *
1000:  * Outputs:
1001:  *
1002:  * `<video src="/files/video.mp4">Fallback text</video>`
1003:  *
1004:  * Using multiple video files:
1005:  *
1006:  * {{{
1007:  * echo $this->Html->media(
1008:  *      array('video.mp4', array('src' => 'video.ogv', 'type' => "video/ogg; codecs='theora, vorbis'")),
1009:  *      array('tag' => 'video', 'autoplay')
1010:  * );
1011:  * }}}
1012:  *
1013:  * Outputs:
1014:  *
1015:  * {{{
1016:  * <video autoplay="autoplay">
1017:  *      <source src="/files/video.mp4" type="video/mp4"/>
1018:  *      <source src="/files/video.ogv" type="video/ogv; codecs='theora, vorbis'"/>
1019:  * </video>
1020:  * }}}
1021:  *
1022:  * ### Options
1023:  *
1024:  * - `tag` Type of media element to generate, either "audio" or "video".
1025:  *  If tag is not provided it's guessed based on file's mime type.
1026:  * - `text` Text to include inside the audio/video tag
1027:  * - `pathPrefix` Path prefix to use for relative URLs, defaults to 'files/'
1028:  * - `fullBase` If provided the src attribute will get a full address including domain name
1029:  *
1030:  * @param string|array $path Path to the video file, relative to the webroot/{$options['pathPrefix']} directory.
1031:  *  Or an array where each item itself can be a path string or an associate array containing keys `src` and `type`
1032:  * @param array $options Array of HTML attributes, and special options above.
1033:  * @return string Generated media element
1034:  */
1035:     public function media($path, $options = array()) {
1036:         $options += array(
1037:             'tag' => null,
1038:             'pathPrefix' => 'files/',
1039:             'text' => ''
1040:         );
1041: 
1042:         if (!empty($options['tag'])) {
1043:             $tag = $options['tag'];
1044:         } else {
1045:             $tag = null;
1046:         }
1047: 
1048:         if (is_array($path)) {
1049:             $sourceTags = '';
1050:             foreach ($path as &$source) {
1051:                 if (is_string($source)) {
1052:                     $source = array(
1053:                         'src' => $source,
1054:                     );
1055:                 }
1056:                 if (!isset($source['type'])) {
1057:                     $ext = pathinfo($source['src'], PATHINFO_EXTENSION);
1058:                     $source['type'] = $this->response->getMimeType($ext);
1059:                 }
1060:                 $source['src'] = $this->assetUrl($source['src'], $options);
1061:                 $sourceTags .= $this->useTag('tagselfclosing', 'source', $source);
1062:             }
1063:             unset($source);
1064:             $options['text'] = $sourceTags . $options['text'];
1065:             unset($options['fullBase']);
1066:         } else {
1067:             if (empty($path) && !empty($options['src'])) {
1068:                 $path = $options['src'];
1069:             }
1070:             $options['src'] = $this->assetUrl($path, $options);
1071:         }
1072: 
1073:         if ($tag === null) {
1074:             if (is_array($path)) {
1075:                 $mimeType = $path[0]['type'];
1076:             } else {
1077:                 $mimeType = $this->response->getMimeType(pathinfo($path, PATHINFO_EXTENSION));
1078:             }
1079:             if (preg_match('#^video/#', $mimeType)) {
1080:                 $tag = 'video';
1081:             } else {
1082:                 $tag = 'audio';
1083:             }
1084:         }
1085: 
1086:         if (isset($options['poster'])) {
1087:             $options['poster'] = $this->assetUrl($options['poster'], array('pathPrefix' => IMAGES_URL) + $options);
1088:         }
1089:         $text = $options['text'];
1090: 
1091:         $options = array_diff_key($options, array(
1092:             'tag' => null,
1093:             'fullBase' => null,
1094:             'pathPrefix' => null,
1095:             'text' => null
1096:         ));
1097:         return $this->tag($tag, $text, $options);
1098:     }
1099: 
1100: /**
1101:  * Build a nested list (UL/OL) out of an associative array.
1102:  *
1103:  * @param array $list Set of elements to list
1104:  * @param array $options Additional HTML attributes of the list (ol/ul) tag or if ul/ol use that as tag
1105:  * @param array $itemOptions Additional HTML attributes of the list item (LI) tag
1106:  * @param string $tag Type of list tag to use (ol/ul)
1107:  * @return string The nested list
1108:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::nestedList
1109:  */
1110:     public function nestedList($list, $options = array(), $itemOptions = array(), $tag = 'ul') {
1111:         if (is_string($options)) {
1112:             $tag = $options;
1113:             $options = array();
1114:         }
1115:         $items = $this->_nestedListItem($list, $options, $itemOptions, $tag);
1116:         return sprintf($this->_tags[$tag], $this->_parseAttributes($options, null, ' ', ''), $items);
1117:     }
1118: 
1119: /**
1120:  * Internal function to build a nested list (UL/OL) out of an associative array.
1121:  *
1122:  * @param array $items Set of elements to list
1123:  * @param array $options Additional HTML attributes of the list (ol/ul) tag
1124:  * @param array $itemOptions Additional HTML attributes of the list item (LI) tag
1125:  * @param string $tag Type of list tag to use (ol/ul)
1126:  * @return string The nested list element
1127:  * @see HtmlHelper::nestedList()
1128:  */
1129:     protected function _nestedListItem($items, $options, $itemOptions, $tag) {
1130:         $out = '';
1131: 
1132:         $index = 1;
1133:         foreach ($items as $key => $item) {
1134:             if (is_array($item)) {
1135:                 $item = $key . $this->nestedList($item, $options, $itemOptions, $tag);
1136:             }
1137:             if (isset($itemOptions['even']) && $index % 2 === 0) {
1138:                 $itemOptions['class'] = $itemOptions['even'];
1139:             } elseif (isset($itemOptions['odd']) && $index % 2 !== 0) {
1140:                 $itemOptions['class'] = $itemOptions['odd'];
1141:             }
1142:             $out .= sprintf($this->_tags['li'], $this->_parseAttributes($itemOptions, array('even', 'odd'), ' ', ''), $item);
1143:             $index++;
1144:         }
1145:         return $out;
1146:     }
1147: 
1148: /**
1149:  * Load Html tag configuration.
1150:  *
1151:  * Loads a file from APP/Config that contains tag data. By default the file is expected
1152:  * to be compatible with PhpReader:
1153:  *
1154:  * `$this->Html->loadConfig('tags.php');`
1155:  *
1156:  * tags.php could look like:
1157:  *
1158:  * {{{
1159:  * $tags = array(
1160:  *      'meta' => '<meta %s>'
1161:  * );
1162:  * }}}
1163:  *
1164:  * If you wish to store tag definitions in another format you can give an array
1165:  * containing the file name, and reader class name:
1166:  *
1167:  * `$this->Html->loadConfig(array('tags.ini', 'ini'));`
1168:  *
1169:  * Its expected that the `tags` index will exist from any configuration file that is read.
1170:  * You can also specify the path to read the configuration file from, if APP/Config is not
1171:  * where the file is.
1172:  *
1173:  * `$this->Html->loadConfig('tags.php', APP . 'Lib' . DS);`
1174:  *
1175:  * Configuration files can define the following sections:
1176:  *
1177:  * - `tags` The tags to replace.
1178:  * - `minimizedAttributes` The attributes that are represented like `disabled="disabled"`
1179:  * - `docTypes` Additional doctypes to use.
1180:  * - `attributeFormat` Format for long attributes e.g. `'%s="%s"'`
1181:  * - `minimizedAttributeFormat` Format for minimized attributes e.g. `'%s="%s"'`
1182:  *
1183:  * @param string|array $configFile String with the config file (load using PhpReader) or an array with file and reader name
1184:  * @param string $path Path with config file
1185:  * @return mixed False to error or loaded configs
1186:  * @throws ConfigureException
1187:  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#changing-the-tags-output-by-htmlhelper
1188:  */
1189:     public function loadConfig($configFile, $path = null) {
1190:         if (!$path) {
1191:             $path = APP . 'Config' . DS;
1192:         }
1193:         $file = null;
1194:         $reader = 'php';
1195: 
1196:         if (!is_array($configFile)) {
1197:             $file = $configFile;
1198:         } elseif (isset($configFile[0])) {
1199:             $file = $configFile[0];
1200:             if (isset($configFile[1])) {
1201:                 $reader = $configFile[1];
1202:             }
1203:         } else {
1204:             throw new ConfigureException(__d('cake_dev', 'Cannot load the configuration file. Wrong "configFile" configuration.'));
1205:         }
1206: 
1207:         $readerClass = Inflector::camelize($reader) . 'Reader';
1208:         App::uses($readerClass, 'Configure');
1209:         if (!class_exists($readerClass)) {
1210:             throw new ConfigureException(__d('cake_dev', 'Cannot load the configuration file. Unknown reader.'));
1211:         }
1212: 
1213:         $readerObj = new $readerClass($path);
1214:         $configs = $readerObj->read($file);
1215:         if (isset($configs['tags']) && is_array($configs['tags'])) {
1216:             $this->_tags = array_merge($this->_tags, $configs['tags']);
1217:         }
1218:         if (isset($configs['minimizedAttributes']) && is_array($configs['minimizedAttributes'])) {
1219:             $this->_minimizedAttributes = array_merge($this->_minimizedAttributes, $configs['minimizedAttributes']);
1220:         }
1221:         if (isset($configs['docTypes']) && is_array($configs['docTypes'])) {
1222:             $this->_docTypes = array_merge($this->_docTypes, $configs['docTypes']);
1223:         }
1224:         if (isset($configs['attributeFormat'])) {
1225:             $this->_attributeFormat = $configs['attributeFormat'];
1226:         }
1227:         if (isset($configs['minimizedAttributeFormat'])) {
1228:             $this->_minimizedAttributeFormat = $configs['minimizedAttributeFormat'];
1229:         }
1230:         return $configs;
1231:     }
1232: 
1233: }
1234: 
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