diff --git a/cake/libs/view/helper.php b/cake/libs/view/helper.php index 16ea94798..0337b5088 100644 --- a/cake/libs/view/helper.php +++ b/cake/libs/view/helper.php @@ -105,30 +105,6 @@ class Helper extends Object { */ protected $_View; -/** - * Minimized attributes - * - * @var array - */ - protected $_minimizedAttributes = array( - 'compact', 'checked', 'declare', 'readonly', 'disabled', 'selected', - 'defer', 'ismap', 'nohref', 'noshade', 'nowrap', 'multiple', 'noresize' - ); - -/** - * Format to attribute - * - * @var string - */ - protected $_attributeFormat = '%s="%s"'; - -/** - * Format to attribute - * - * @var string - */ - protected $_minimizedAttributeFormat = '%s="%s"'; - /** * Default Constructor * @@ -198,22 +174,6 @@ class Helper extends Object { return $this->{$name} = $value; } -/** - * Parses tag templates into $this->tags. - * - * @param $name file name inside app/config to load. - * @return array merged tags from config/$name.php - */ - public function loadConfig($name = 'tags') { - if (file_exists(CONFIGS . $name .'.php')) { - require(CONFIGS . $name .'.php'); - if (isset($tags)) { - $this->tags = array_merge($this->tags, $tags); - } - } - return $this->tags; - } - /** * Finds URL for specified action. * @@ -330,94 +290,6 @@ class Helper extends Object { return $this->__cleaned; } -/** - * Returns a space-delimited string with items of the $options array. If a - * key of $options array happens to be one of: - * - * - 'compact' - * - 'checked' - * - 'declare' - * - 'readonly' - * - 'disabled' - * - 'selected' - * - 'defer' - * - 'ismap' - * - 'nohref' - * - 'noshade' - * - 'nowrap' - * - 'multiple' - * - 'noresize' - * - * And its value is one of: - * - * - '1' (string) - * - 1 (integer) - * - true (boolean) - * - 'true' (string) - * - * Then the value will be reset to be identical with key's name. - * If the value is not one of these 3, the parameter is not output. - * - * 'escape' is a special option in that it controls the conversion of - * attributes to their html-entity encoded equivalents. Set to false to disable html-encoding. - * - * If value for any option key is set to `null` or `false`, that option will be excluded from output. - * - * @param array $options Array of options. - * @param array $exclude Array of options to be excluded, the options here will not be part of the return. - * @param string $insertBefore String to be inserted before options. - * @param string $insertAfter String to be inserted after options. - * @return string Composed attributes. - */ - public function _parseAttributes($options, $exclude = null, $insertBefore = ' ', $insertAfter = null) { - if (is_array($options)) { - $options = array_merge(array('escape' => true), $options); - - if (!is_array($exclude)) { - $exclude = array(); - } - $filtered = array_diff_key($options, array_merge(array_flip($exclude), array('escape' => true))); - $escape = $options['escape']; - $attributes = array(); - - foreach ($filtered as $key => $value) { - if ($value !== false && $value !== null) { - $attributes[] = $this->_formatAttribute($key, $value, $escape); - } - } - $out = implode(' ', $attributes); - } else { - $out = $options; - } - return $out ? $insertBefore . $out . $insertAfter : ''; - } - -/** - * Formats an individual attribute, and returns the string value of the composed attribute. - * Works with minimized attributes that have the same value as their name such as 'disabled' and 'checked' - * - * @param string $key The name of the attribute to create - * @param string $value The value of the attribute to create. - * @return string The composed attribute. - */ - protected function _formatAttribute($key, $value, $escape = true) { - $attribute = ''; - if (is_array($value)) { - $value = ''; - } - - if (is_numeric($key)) { - $attribute = sprintf($this->_minimizedAttributeFormat, $value, $value); - } elseif (in_array($key, $this->_minimizedAttributes)) { - if ($value === 1 || $value === true || $value === 'true' || $value === '1' || $value == $key) { - $attribute = sprintf($this->_minimizedAttributeFormat, $key, $key); - } - } else { - $attribute = sprintf($this->_attributeFormat, $key, ($escape ? h($value) : $value)); - } - return $attribute; - } - /** * Sets this helper's model and field properties to the dot-separated value-pair in $entity. * diff --git a/cake/libs/view/helpers/form.php b/cake/libs/view/helpers/form.php index f397c670d..1eb2b315f 100644 --- a/cake/libs/view/helpers/form.php +++ b/cake/libs/view/helpers/form.php @@ -314,12 +314,11 @@ class FormHelper extends AppHelper { } if (!empty($append)) { - $append = sprintf($this->Html->tags['block'], ' style="display:none;"', $append); + $append = $this->Html->useTag('block', ' style="display:none;"', $append); } $this->setEntity($model . '.', true); - $attributes = $this->_parseAttributes($htmlAttributes, null, ''); - return sprintf($this->Html->tags['form'], $attributes) . $append; + return $this->Html->useTag('form', $htmlAttributes) . $append; } /** @@ -372,7 +371,7 @@ class FormHelper extends AppHelper { $this->fields = array(); } $this->setEntity(null); - $out .= $this->Html->tags['formend']; + $out .= $this->Html->useTag('formend'); $this->_View->modelScope = false; return $out; @@ -407,8 +406,7 @@ class FormHelper extends AppHelper { 'value' => urlencode($fields . ':' . $locked), 'id' => 'TokenFields' . mt_rand() )); - $out = sprintf($this->Html->tags['block'], ' style="display:none;"', $out); - return $out; + return $this->Html->useTag('block', ' style="display:none;"', $out); } /** @@ -562,11 +560,7 @@ class FormHelper extends AppHelper { $labelFor = $this->domId($fieldName); } - return sprintf( - $this->Html->tags['label'], - $labelFor, - $this->_parseAttributes($options), $text - ); + return $this->Html->useTag('label', $labelFor, $options, $text); } /** @@ -657,13 +651,9 @@ class FormHelper extends AppHelper { } if ($fieldset && $legend) { - return sprintf( - $this->Html->tags['fieldset'], - $fieldsetClass, - sprintf($this->Html->tags['legend'], $legend) . $out - ); + return $this->Html->useTag('fieldset', $fieldsetClass, $this->Html->useTag('legend', $legend) . $out); } elseif ($fieldset) { - return sprintf($this->Html->tags['fieldset'], $fieldsetClass, $out); + return $this->Html->useTag('fieldset', $fieldsetClass, $out); } else { return $out; } @@ -1019,11 +1009,7 @@ class FormHelper extends AppHelper { } unset($options['hiddenField']); - return $output . sprintf( - $this->Html->tags['checkbox'], - $options['name'], - $this->_parseAttributes($options, array('name'), null, ' ') - ); + return $output . $this->Html->useTag('checkbox', $options['name'], array_diff_key($options, array('name' => ''))); } /** @@ -1085,20 +1071,17 @@ class FormHelper extends AppHelper { if (isset($value) && $optValue == $value) { $optionsHere['checked'] = 'checked'; } - $parsedOptions = $this->_parseAttributes( - array_merge($attributes, $optionsHere), - array('name', 'type', 'id'), '', ' ' - ); $tagName = Inflector::camelize( $attributes['id'] . '_' . Inflector::slug($optValue) ); if ($label) { - $optTitle = sprintf($this->Html->tags['label'], $tagName, null, $optTitle); + $optTitle = $this->Html->useTag('label', $tagName, '', $optTitle); } - $out[] = sprintf( - $this->Html->tags['radio'], $attributes['name'], - $tagName, $parsedOptions, $optTitle + $allOptions = array_merge($attributes, $optionsHere); + $out[] = $this->Html->useTag('radio', $attributes['name'], $tagName, + array_diff_key($allOptions, array('name' => '', 'type' => '', 'id' => '')), + $optTitle ); } $hidden = null; @@ -1113,10 +1096,7 @@ class FormHelper extends AppHelper { $out = $hidden . implode($inbetween, $out); if ($legend) { - $out = sprintf( - $this->Html->tags['fieldset'], '', - sprintf($this->Html->tags['legend'], $legend) . $out - ); + $out = $this->Html->useTag('fieldset', '', $this->Html->useTag('legend', $legend) . $out); } return $out; } @@ -1154,11 +1134,7 @@ class FormHelper extends AppHelper { $options['type'] = $method; } $options = $this->_initInputField($params[0], $options); - return sprintf( - $this->Html->tags['input'], - $options['name'], - $this->_parseAttributes($options, array('name'), null, ' ') - ); + return $this->Html->useTag('input', $options['name'], array_diff_key($options, array('name' => ''))); } /** @@ -1185,12 +1161,7 @@ class FormHelper extends AppHelper { } unset($options['value']); } - return sprintf( - $this->Html->tags['textarea'], - $options['name'], - $this->_parseAttributes($options, array('type', 'name'), null, ' '), - $value - ); + return $this->Html->useTag('textarea', $options['name'], array_diff_key($options, array('type' => '', 'name' => '')), $value); } /** @@ -1218,11 +1189,7 @@ class FormHelper extends AppHelper { $this->__secure(null, '' . $options['value']); } - return sprintf( - $this->Html->tags['hidden'], - $options['name'], - $this->_parseAttributes($options, array('name', 'class'), '', ' ') - ); + return $this->Html->useTag('hidden', $options['name'], array_diff_key($options, array('name' => '', 'class' => ''))); } /** @@ -1243,8 +1210,7 @@ class FormHelper extends AppHelper { $this->__secure(array_merge($field, array($suffix))); } - $attributes = $this->_parseAttributes($options, array('name'), '', ' '); - return sprintf($this->Html->tags['file'], $options['name'], $attributes); + return $this->Html->useTag('file', $options['name'], array_diff_key($options, array('name' => ''))); } /** @@ -1266,12 +1232,7 @@ class FormHelper extends AppHelper { if ($options['escape']) { $title = h($title); } - return sprintf( - $this->Html->tags['button'], - $options['type'], - $this->_parseAttributes($options, array('type'), ' ', ''), - $title - ); + return $this->Html->useTag('button', $options['type'], array_diff_key($options, array('type' => '')), $title); } /** @@ -1408,11 +1369,7 @@ class FormHelper extends AppHelper { if (strpos($caption, '://') !== false) { unset($options['type']); - $out .= $before . sprintf( - $this->Html->tags['submitimage'], - $caption, - $this->_parseAttributes($options, null, '', ' ') - ) . $after; + $out .= $before . $this->Html->useTag('submitimage', $caption, $options) . $after; } elseif (preg_match('/\.(jpg|jpe|jpeg|gif|png|ico)$/', $caption)) { unset($options['type']); if ($caption{0} !== '/') { @@ -1421,17 +1378,10 @@ class FormHelper extends AppHelper { $caption = trim($caption, '/'); $url = $this->webroot($caption); } - $out .= $before . sprintf( - $this->Html->tags['submitimage'], - $url, - $this->_parseAttributes($options, null, '', ' ') - ) . $after; + $out .= $before . $this->Html->useTag('submitimage', $url, $options) . $after; } else { $options['value'] = $caption; - $out .= $before . sprintf( - $this->Html->tags['submit'], - $this->_parseAttributes($options, null, '', ' ') - ). $after; + $out .= $before . $this->Html->useTag('submit', $options) . $after; } if (isset($divOptions)) { @@ -1524,7 +1474,7 @@ class FormHelper extends AppHelper { if (isset($attributes) && array_key_exists('multiple', $attributes)) { $style = ($attributes['multiple'] === 'checkbox') ? 'checkbox' : null; $template = ($style) ? 'checkboxmultiplestart' : 'selectmultiplestart'; - $tag = $this->Html->tags[$template]; + $tag = $template; $hiddenAttributes = array( 'value' => '', 'id' => $attributes['id'] . ($style ? '' : '_'), @@ -1533,16 +1483,14 @@ class FormHelper extends AppHelper { ); $select[] = $this->hidden(null, $hiddenAttributes); } else { - $tag = $this->Html->tags['selectstart']; + $tag = 'selectstart'; } if (!empty($tag) || isset($template)) { if (!isset($secure) || $secure == true) { $this->__secure(); } - $select[] = sprintf($tag, $attributes['name'], $this->_parseAttributes( - $attributes, array('name', 'value')) - ); + $select[] = $this->Html->useTag($tag, $attributes['name'], array_diff_key($attributes, array('name' => '', 'value' => ''))); } $emptyMulti = ( $showEmpty !== null && $showEmpty !== false && !( @@ -1566,7 +1514,7 @@ class FormHelper extends AppHelper { )); $template = ($style == 'checkbox') ? 'checkboxmultipleend' : 'selectend'; - $select[] = $this->Html->tags[$template]; + $select[] = $this->Html->useTag($template); return implode("\n", $select); } @@ -2057,9 +2005,9 @@ class FormHelper extends AppHelper { if (is_array($title) && (!isset($title['name']) || !isset($title['value']))) { if (!empty($name)) { if ($attributes['style'] === 'checkbox') { - $select[] = $this->Html->tags['fieldsetend']; + $select[] = $this->Html->useTag('fieldsetend'); } else { - $select[] = $this->Html->tags['optiongroupend']; + $select[] = $this->Html->useTag('optiongroupend'); } $parents[] = $name; } @@ -2070,9 +2018,9 @@ class FormHelper extends AppHelper { if (!empty($name)) { $name = $attributes['escape'] ? h($name) : $name; if ($attributes['style'] === 'checkbox') { - $select[] = sprintf($this->Html->tags['fieldsetstart'], $name); + $select[] = $this->Html->useTag('fieldsetstart', $name); } else { - $select[] = sprintf($this->Html->tags['optiongroup'], $name, ''); + $select[] = $this->Html->useTag('optiongroup', $name, ''); } } $name = null; @@ -2117,16 +2065,10 @@ class FormHelper extends AppHelper { $attributes['class'] = 'checkbox'; } $label = $this->label(null, $title, $label); - $item = sprintf( - $this->Html->tags['checkboxmultiple'], $name, - $this->_parseAttributes($htmlOptions) - ); + $item = $this->Html->useTag('checkboxmultiple', $name, $htmlOptions); $select[] = $this->Html->div($attributes['class'], $item . $label); } else { - $select[] = sprintf( - $this->Html->tags['selectoption'], - $name, $this->_parseAttributes($htmlOptions), $title - ); + $select[] = $this->Html->useTag('selectoption', $name, $htmlOptions, $title); } } } diff --git a/cake/libs/view/helpers/html.php b/cake/libs/view/helpers/html.php index c5165515f..436941a81 100644 --- a/cake/libs/view/helpers/html.php +++ b/cake/libs/view/helpers/html.php @@ -29,9 +29,8 @@ class HtmlHelper extends AppHelper { * html tags used by this helper. * * @var array - * @access public */ - public $tags = array( + protected $_tags = array( 'meta' => '', 'metalink' => '', 'link' => '%s', @@ -90,6 +89,30 @@ class HtmlHelper extends AppHelper { 'javascriptend' => '' ); +/** + * Minimized attributes + * + * @var array + */ + protected $_minimizedAttributes = array( + 'compact', 'checked', 'declare', 'readonly', 'disabled', 'selected', + 'defer', 'ismap', 'nohref', 'noshade', 'nowrap', 'multiple', 'noresize' + ); + +/** + * Format to attribute + * + * @var string + */ + protected $_attributeFormat = '%s="%s"'; + +/** + * Format to attribute + * + * @var string + */ + protected $_minimizedAttributeFormat = '%s="%s"'; + /** * Breadcrumbs. * @@ -122,12 +145,26 @@ class HtmlHelper extends AppHelper { 'html4-strict' => '', 'html4-trans' => '', 'html4-frame' => '', + 'html5' => '', 'xhtml-strict' => '', 'xhtml-trans' => '', 'xhtml-frame' => '', 'xhtml11' => '' ); +/** + * Default Constructor + * + * @param View $View The View this helper is being attached to. + * @param array $settings Configuration settings for the helper. + */ + public function __construct(View $View, $settings = array()) { + parent::__construct($View, $settings); + if (!empty($settings['configFile'])) { + $this->loadConfig($settings['configFile']); + } + } + /** * Adds a link to the breadcrumbs array. * @@ -149,6 +186,7 @@ class HtmlHelper extends AppHelper { * - html4-strict: HTML4 Strict. * - html4-trans: HTML4 Transitional. * - html4-frame: HTML4 Frameset. + * - html5: HTML5. * - xhtml-strict: XHTML1 Strict. * - xhtml-trans: XHTML1 Transitional. * - xhtml-frame: XHTML1 Frameset. @@ -220,14 +258,14 @@ class HtmlHelper extends AppHelper { if (isset($options['link'])) { if (isset($options['rel']) && $options['rel'] === 'icon') { - $out = sprintf($this->tags['metalink'], $options['link'], $this->_parseAttributes($options, array('link'), ' ', ' ')); + $out = sprintf($this->_tags['metalink'], $options['link'], $this->_parseAttributes($options, array('link'), ' ', ' ')); $options['rel'] = 'shortcut icon'; } else { $options['link'] = $this->url($options['link'], true); } - $out .= sprintf($this->tags['metalink'], $options['link'], $this->_parseAttributes($options, array('link'), ' ', ' ')); + $out .= sprintf($this->_tags['metalink'], $options['link'], $this->_parseAttributes($options, array('link'), ' ', ' ')); } else { - $out = sprintf($this->tags['meta'], $this->_parseAttributes($options, array('type'), ' ', ' ')); + $out = sprintf($this->_tags['meta'], $this->_parseAttributes($options, array('type'), ' ', ' ')); } if ($inline) { @@ -250,7 +288,7 @@ class HtmlHelper extends AppHelper { if (empty($charset)) { $charset = strtolower(Configure::read('App.encoding')); } - return sprintf($this->tags['charset'], (!empty($charset) ? $charset : 'utf-8')); + return sprintf($this->_tags['charset'], (!empty($charset) ? $charset : 'utf-8')); } /** @@ -310,7 +348,7 @@ class HtmlHelper extends AppHelper { } unset($options['default']); } - return sprintf($this->tags['link'], $url, $this->_parseAttributes($options), $title); + return sprintf($this->_tags['link'], $url, $this->_parseAttributes($options), $title); } /** @@ -365,12 +403,12 @@ class HtmlHelper extends AppHelper { } if ($rel == 'import') { - $out = sprintf($this->tags['style'], $this->_parseAttributes($options, array('inline'), '', ' '), '@import url(' . $url . ');'); + $out = sprintf($this->_tags['style'], $this->_parseAttributes($options, array('inline'), '', ' '), '@import url(' . $url . ');'); } else { if ($rel == null) { $rel = 'stylesheet'; } - $out = sprintf($this->tags['css'], $rel, $url, $this->_parseAttributes($options, array('inline'), '', ' ')); + $out = sprintf($this->_tags['css'], $rel, $url, $this->_parseAttributes($options, array('inline'), '', ' ')); } if ($options['inline']) { @@ -436,7 +474,7 @@ class HtmlHelper extends AppHelper { } } $attributes = $this->_parseAttributes($options, array('inline', 'once'), ' '); - $out = sprintf($this->tags['javascriptlink'], $url, $attributes); + $out = sprintf($this->_tags['javascriptlink'], $url, $attributes); if ($options['inline']) { return $out; @@ -468,9 +506,9 @@ class HtmlHelper extends AppHelper { unset($options['inline'], $options['safe']); $attributes = $this->_parseAttributes($options, ' ', ' '); if ($inline) { - return sprintf($this->tags['javascriptblock'], $attributes, $script); + return sprintf($this->_tags['javascriptblock'], $attributes, $script); } else { - $this->_View->addScript(sprintf($this->tags['javascriptblock'], $attributes, $script)); + $this->_View->addScript(sprintf($this->_tags['javascriptblock'], $attributes, $script)); return null; } } @@ -649,10 +687,10 @@ class HtmlHelper extends AppHelper { unset($options['url']); } - $image = sprintf($this->tags['image'], $path, $this->_parseAttributes($options, null, '', ' ')); + $image = sprintf($this->_tags['image'], $path, $this->_parseAttributes($options, null, '', ' ')); if ($url) { - return sprintf($this->tags['link'], $this->url($url), null, $image); + return sprintf($this->_tags['link'], $this->url($url), null, $image); } return $image; } @@ -670,9 +708,9 @@ class HtmlHelper extends AppHelper { public function tableHeaders($names, $trOptions = null, $thOptions = null) { $out = array(); foreach ($names as $arg) { - $out[] = sprintf($this->tags['tableheader'], $this->_parseAttributes($thOptions), $arg); + $out[] = sprintf($this->_tags['tableheader'], $this->_parseAttributes($thOptions), $arg); } - return sprintf($this->tags['tablerow'], $this->_parseAttributes($trOptions), join(' ', $out)); + return sprintf($this->_tags['tablerow'], $this->_parseAttributes($trOptions), join(' ', $out)); } /** @@ -722,10 +760,10 @@ class HtmlHelper extends AppHelper { } elseif ($useCount) { $cellOptions['class'] = 'column-' . ++$i; } - $cellsOut[] = sprintf($this->tags['tablecell'], $this->_parseAttributes($cellOptions), $cell); + $cellsOut[] = sprintf($this->_tags['tablecell'], $this->_parseAttributes($cellOptions), $cell); } $options = $this->_parseAttributes($count % 2 ? $oddTrOptions : $evenTrOptions); - $out[] = sprintf($this->tags['tablerow'], $options, implode(' ', $cellsOut)); + $out[] = sprintf($this->_tags['tablerow'], $options, implode(' ', $cellsOut)); } return implode("\n", $out); } @@ -758,7 +796,27 @@ class HtmlHelper extends AppHelper { } else { $tag = 'tag'; } - return sprintf($this->tags[$tag], $name, $this->_parseAttributes($options, null, ' ', ''), $text, $name); + return sprintf($this->_tags[$tag], $name, $this->_parseAttributes($options, null, ' ', ''), $text, $name); + } + +/** + * Returns a formatted existent block of $tags + * + * @param string $tag Tag name + * @return string Formatted block + */ + public function useTag($tag) { + if (!isset($this->_tags[$tag])) { + return ''; + } + $args = func_get_args(); + array_shift($args); + foreach ($args as &$arg) { + if (is_array($arg)) { + $arg = $this->_parseAttributes($arg, null, ' ', ''); + } + } + return vsprintf($this->_tags[$tag], $args); } /** @@ -809,7 +867,7 @@ class HtmlHelper extends AppHelper { } else { $tag = 'para'; } - return sprintf($this->tags[$tag], $this->_parseAttributes($options, null, ' ', ''), $text); + return sprintf($this->_tags[$tag], $this->_parseAttributes($options, null, ' ', ''), $text); } /** @@ -827,7 +885,7 @@ class HtmlHelper extends AppHelper { $options = array(); } $items = $this->__nestedListItem($list, $options, $itemOptions, $tag); - return sprintf($this->tags[$tag], $this->_parseAttributes($options, null, ' ', ''), $items); + return sprintf($this->_tags[$tag], $this->_parseAttributes($options, null, ' ', ''), $items); } /** @@ -854,9 +912,145 @@ class HtmlHelper extends AppHelper { } else if (isset($itemOptions['odd']) && $index % 2 != 0) { $itemOptions['class'] = $itemOptions['odd']; } - $out .= sprintf($this->tags['li'], $this->_parseAttributes($itemOptions, array('even', 'odd'), ' ', ''), $item); + $out .= sprintf($this->_tags['li'], $this->_parseAttributes($itemOptions, array('even', 'odd'), ' ', ''), $item); $index++; } return $out; } + +/** + * Load Html configs + * + * @param mixed $configFile String with the config file (load using PhpReader) or an array with file and reader name + * @param string $path Path with config file + * @return mixed False to error or loaded configs + */ + public function loadConfig($configFile, $path = CONFIGS) { + $file = null; + $reader = 'php'; + + if (!is_array($configFile)) { + $file = $configFile; + } elseif (isset($configFile[0])) { + $file = $configFile[0]; + if (isset($configFile[1])) { + $reader = $configFile[1]; + } + } else { + throw new ConfigureException(__('Cannot load the configuration file. Wrong "configFile" configuration.')); + } + + $readerClass = Inflector::camelize($reader) . 'Reader'; + if (!App::import('Lib', 'config/' . $readerClass)) { + throw new ConfigureException(__('Cannot load the configuration file. Unknown reader.')); + } + + $readerObj = new $readerClass($path); + $configs = $readerObj->read($file); + if (isset($configs['tags']) && is_array($configs['tags'])) { + $this->_tags = array_merge($this->_tags, $configs['tags']); + } + if (isset($configs['minimizedAttributes']) && is_array($configs['minimizedAttributes'])) { + $this->_minimizedAttributes = array_merge($this->_minimizedAttributes, $configs['minimizedAttributes']); + } + if (isset($configs['docTypes']) && is_array($configs['docTypes'])) { + $this->__docTypes = array_merge($this->__docTypes, $configs['docTypes']); + } + if (isset($configs['attributeFormat'])) { + $this->_attributeFormat = $configs['attributeFormat']; + } + if (isset($configs['minimizedAttributeFormat'])) { + $this->_minimizedAttributeFormat = $configs['minimizedAttributeFormat']; + } + return $configs; + } + +/** + * Returns a space-delimited string with items of the $options array. If a + * key of $options array happens to be one of: + * + * - 'compact' + * - 'checked' + * - 'declare' + * - 'readonly' + * - 'disabled' + * - 'selected' + * - 'defer' + * - 'ismap' + * - 'nohref' + * - 'noshade' + * - 'nowrap' + * - 'multiple' + * - 'noresize' + * + * And its value is one of: + * + * - '1' (string) + * - 1 (integer) + * - true (boolean) + * - 'true' (string) + * + * Then the value will be reset to be identical with key's name. + * If the value is not one of these 3, the parameter is not output. + * + * 'escape' is a special option in that it controls the conversion of + * attributes to their html-entity encoded equivalents. Set to false to disable html-encoding. + * + * If value for any option key is set to `null` or `false`, that option will be excluded from output. + * + * @param array $options Array of options. + * @param array $exclude Array of options to be excluded, the options here will not be part of the return. + * @param string $insertBefore String to be inserted before options. + * @param string $insertAfter String to be inserted after options. + * @return string Composed attributes. + */ + public function _parseAttributes($options, $exclude = null, $insertBefore = ' ', $insertAfter = null) { + if (is_array($options)) { + $options = array_merge(array('escape' => true), $options); + + if (!is_array($exclude)) { + $exclude = array(); + } + $filtered = array_diff_key($options, array_merge(array_flip($exclude), array('escape' => true))); + $escape = $options['escape']; + $attributes = array(); + + foreach ($filtered as $key => $value) { + if ($value !== false && $value !== null) { + $attributes[] = $this->_formatAttribute($key, $value, $escape); + } + } + $out = implode(' ', $attributes); + } else { + $out = $options; + } + return $out ? $insertBefore . $out . $insertAfter : ''; + } + +/** + * Formats an individual attribute, and returns the string value of the composed attribute. + * Works with minimized attributes that have the same value as their name such as 'disabled' and 'checked' + * + * @param string $key The name of the attribute to create + * @param string $value The value of the attribute to create. + * @return string The composed attribute. + */ + protected function _formatAttribute($key, $value, $escape = true) { + $attribute = ''; + if (is_array($value)) { + $value = ''; + } + + if (is_numeric($key)) { + $attribute = sprintf($this->_minimizedAttributeFormat, $value, $value); + } elseif (in_array($key, $this->_minimizedAttributes)) { + if ($value === 1 || $value === true || $value === 'true' || $value === '1' || $value == $key) { + $attribute = sprintf($this->_minimizedAttributeFormat, $key, $key); + } + } else { + $attribute = sprintf($this->_attributeFormat, $key, ($escape ? h($value) : $value)); + } + return $attribute; + } + } diff --git a/cake/tests/cases/libs/view/helper.test.php b/cake/tests/cases/libs/view/helper.test.php index 44b38f903..125e00ac1 100644 --- a/cake/tests/cases/libs/view/helper.test.php +++ b/cake/tests/cases/libs/view/helper.test.php @@ -179,35 +179,6 @@ class TestHelper extends Helper { } } -/** - * Html5TestHelper class - * - * @package cake.tests.cases.libs.view - */ -class Html5TestHelper extends TestHelper { - -/** - * Minimized - * - * @var array - */ - protected $_minimizedAttributes = array('require', 'checked'); - -/** - * Allow compact use in HTML - * - * @var string - */ - protected $_minimizedAttributeFormat = '%s'; - -/** - * Test to attribute format - * - * @var string - */ - protected $_attributeFormat = 'data-%s="%s"'; -} - /** * HelperTest class * @@ -815,32 +786,6 @@ class HelperTest extends CakeTestCase { Configure::write('App.www_root', $webRoot); } -/** - * test parsing attributes. - * - * @return void - */ - function testParseAttributeCompact() { - $helper = new TestHelper($this->View); - $compact = array('compact', 'checked', 'declare', 'readonly', 'disabled', - 'selected', 'defer', 'ismap', 'nohref', 'noshade', 'nowrap', 'multiple', 'noresize'); - - foreach ($compact as $attribute) { - foreach (array('true', true, 1, '1', $attribute) as $value) { - $attrs = array($attribute => $value); - $expected = ' ' . $attribute . '="' . $attribute . '"'; - $this->assertEqual($helper->parseAttributes($attrs), $expected, '%s Failed on ' . $value); - } - } - $this->assertEqual($helper->parseAttributes(array('compact')), ' compact="compact"'); - - $helper = new Html5TestHelper($this->View); - $expected = ' require'; - $this->assertEqual($helper->parseAttributes(array('require')), $expected); - $this->assertEqual($helper->parseAttributes(array('require' => true)), $expected); - $this->assertEqual($helper->parseAttributes(array('require' => false)), ''); - } - /** * test lazy loading helpers is seamless * diff --git a/cake/tests/cases/libs/view/helpers/form.test.php b/cake/tests/cases/libs/view/helpers/form.test.php index c4f1e9dd7..bb389396a 100644 --- a/cake/tests/cases/libs/view/helpers/form.test.php +++ b/cake/tests/cases/libs/view/helpers/form.test.php @@ -5253,7 +5253,7 @@ class FormHelperTest extends CakeTestCase { )); $result = $this->Form->postButton('Send', '/', array('data' => array('extra' => 'value'))); - $this->assertTrue(strpos($result, '') !== false); + $this->assertTrue(strpos($result, '') !== false); } /** @@ -5293,7 +5293,7 @@ class FormHelperTest extends CakeTestCase { )); $result = $this->Form->postLink('Delete', '/posts/delete', array('data' => array('id' => 1))); - $this->assertTrue(strpos($result, '') !== false); + $this->assertTrue(strpos($result, '') !== false); } /** diff --git a/cake/tests/cases/libs/view/helpers/html.test.php b/cake/tests/cases/libs/view/helpers/html.test.php index 142fe91b5..c2226acac 100644 --- a/cake/tests/cases/libs/view/helpers/html.test.php +++ b/cake/tests/cases/libs/view/helpers/html.test.php @@ -47,6 +47,64 @@ class TheHtmlTestController extends Controller { public $uses = null; } +class TestHtmlHelper extends HtmlHelper { +/** + * expose a method as public + * + * @param string $options + * @param string $exclude + * @param string $insertBefore + * @param string $insertAfter + * @return void + */ + function parseAttributes($options, $exclude = null, $insertBefore = ' ', $insertAfter = null) { + return $this->_parseAttributes($options, $exclude, $insertBefore, $insertAfter); + } + +/** + * Get a protected attribute value + * + * @param string $attribute + * @return mixed + */ + public function getAttribute($attribute) { + if (!isset($this->{$attribute})) { + return null; + } + return $this->{$attribute}; + } + +} + +/** + * Html5TestHelper class + * + * @package cake.tests.cases.libs.view.helpers + */ +class Html5TestHelper extends TestHtmlHelper { + +/** + * Minimized + * + * @var array + */ + protected $_minimizedAttributes = array('require', 'checked'); + +/** + * Allow compact use in HTML + * + * @var string + */ + protected $_minimizedAttributeFormat = '%s'; + +/** + * Test to attribute format + * + * @var string + */ + protected $_attributeFormat = 'data-%s="%s"'; +} + /** * HtmlHelperTest class * @@ -84,7 +142,7 @@ class HtmlHelperTest extends CakeTestCase { function setUp() { parent::setUp(); $this->View = $this->getMock('View', array('addScript'), array(new TheHtmlTestController())); - $this->Html = new HtmlHelper($this->View); + $this->Html = new TestHtmlHelper($this->View); $this->Html->request = new CakeRequest(null, false); $this->Html->request->webroot = ''; @@ -1231,6 +1289,22 @@ class HtmlHelperTest extends CakeTestCase { $this->assertTags($result, array('div' => array('class' => 'class-name'), '<text>', '/div')); } +/** + * testUseTag method + * + * @return void + */ + public function testUseTag() { + $result = $this->Html->useTag('formend'); + $this->assertTags($result, '/form'); + + $result = $this->Html->useTag('form', 'test'); + $this->assertEqual($result, '