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

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