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