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

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