Merge remote branch 'upstream/2.0' into 2.0

This commit is contained in:
Jeremy Harris 2011-01-27 18:33:07 -08:00
commit 3575053463
15 changed files with 474 additions and 309 deletions

View file

@ -29,7 +29,6 @@
*
* driver => The name of a supported driver; valid options are as follows:
* mysql - MySQL 4 & 5,
* mysqli - MySQL 4 & 5 Improved Interface (PHP5 only),
* sqlite - SQLite (PHP5 only),
* postgres - PostgreSQL 7 and higher,
* mssql - Microsoft SQL Server 2000 and higher,
@ -43,19 +42,18 @@
* Determines whether or not the database should use a persistent connection
*
* host =>
* the host you connect to the database. To add a socket or port number, use 'port' => #
* the host you connect to the database. To add a socket or port number, use 'port' => #
*
* prefix =>
* Uses the given prefix for all the tables in this database. This setting can be overridden
* on a per-table basis with the Model::$tablePrefix property.
*
* schema =>
* For Postgresspecifies which schema you would like to use the tables in. Postgres defaults to
* 'public', DB2 defaults to empty.
* For Postgres specifies which schema you would like to use the tables in. Postgres defaults to 'public'.
*
* encoding =>
* For MySQL, MySQLi, Postgres specifies the character encoding to use when connecting to the
* database. Uses database default.
* For MySQL, Postgres specifies the character encoding to use when connecting to the
* database. Uses database default not specified.
*
*/
class DATABASE_CONFIG {

View file

@ -71,13 +71,24 @@ class IniReader implements ConfigReaderInterface {
*/
public function read($file) {
$filename = $this->_path . $file;
if (!file_exists($filename)) {
$filename .= '.ini';
if (!file_exists($filename)) {
throw new ConfigureException(__('Could not load configuration files: %s or %s', substr($filename, 0, -4), $filename));
}
}
$contents = parse_ini_file($filename, true);
if (!empty($this->_section) && isset($contents[$this->_section])) {
$values = $this->_parseNestedValues($contents[$this->_section]);
} else {
$values = array();
foreach ($contents as $section => $attribs) {
$values[$section] = $this->_parseNestedValues($attribs);
if (is_array($attribs)) {
$values[$section] = $this->_parseNestedValues($attribs);
} else {
$parse = $this->_parseNestedValues(array($attribs));
$values[$section] = array_shift($parse);
}
}
}
return $values;

View file

@ -57,15 +57,21 @@ class PhpReader implements ConfigReaderInterface {
if (strpos($key, '..') !== false) {
throw new ConfigureException(__('Cannot load configuration files with ../ in them.'));
}
if (substr($key, -4) === '.php') {
$key = substr($key, 0, -4);
}
list($plugin, $key) = pluginSplit($key);
if ($plugin) {
$file = App::pluginPath($plugin) . 'config' . DS . $key . '.php';
$file = App::pluginPath($plugin) . 'config' . DS . $key;
} else {
$file = $this->_path . $key . '.php';
$file = $this->_path . $key;
}
if (!file_exists($file)) {
throw new ConfigureException(__('Could not load configuration file: ') . $file);
$file .= '.php';
if (!file_exists($file)) {
throw new ConfigureException(__('Could not load configuration files: %s or %s', substr($file, 0, -4), $file));
}
}
include $file;
if (!isset($config)) {

View file

@ -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.
*

View file

@ -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);
}
}
}

View file

@ -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' => '<meta%s/>',
'metalink' => '<link href="%s"%s/>',
'link' => '<a href="%s"%s>%s</a>',
@ -90,6 +89,30 @@ class HtmlHelper extends AppHelper {
'javascriptend' => '</script>'
);
/**
* 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' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">',
'html4-trans' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
'html4-frame' => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">',
'html5' => '<!DOCTYPE html>',
'xhtml-strict' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
'xhtml-trans' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
'xhtml-frame' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
'xhtml11' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'
);
/**
* 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;
}
}

View file

@ -624,7 +624,8 @@ class View extends Object {
public function loadHelpers() {
$helpers = HelperCollection::normalizeObjectArray($this->helpers);
foreach ($helpers as $name => $properties) {
$this->Helpers->load($properties['class'], $properties['settings']);
list($plugin, $class) = pluginSplit($properties['class']);
$this->{$class} = $this->Helpers->load($properties['class'], $properties['settings']);
}
$this->_helpersLoaded = true;
}

View file

@ -64,6 +64,22 @@ class IniReaderTest extends CakeTestCase {
$this->assertEquals('administrators', $config['groups']);
}
/**
* test without section
*
* @return void
*/
public function testReadingWithoutSection() {
$reader = new IniReader($this->path);
$config = $reader->read('no_section.ini');
$expected = array(
'some_key' => 'some_value',
'bool_key' => true
);
$this->assertEquals($config, $expected);
}
/**
* test that names with .'s get exploded into arrays.
*
@ -98,4 +114,15 @@ class IniReaderTest extends CakeTestCase {
$this->assertFalse($config['bools']['test_null']);
}
/**
* test read file without extension
*
* @return void
*/
public function testReadingWithoutExtension() {
$reader = new IniReader($this->path);
$config = $reader->read('nested');
$this->assertTrue($config['bools']['test_on']);
}
}

View file

@ -38,6 +38,9 @@ class PhpReaderTest extends CakeTestCase {
$values = $reader->read('var_test');
$this->assertEquals('value', $values['Read']);
$this->assertEquals('buried', $values['Deep']['Deeper']['Deepest']);
$values = $reader->read('var_test.php');
$this->assertEquals('value', $values['Read']);
}
/**
@ -84,7 +87,9 @@ class PhpReaderTest extends CakeTestCase {
), true);
$reader = new PhpReader($this->path);
$result = $reader->read('TestPlugin.load');
$this->assertTrue(isset($result['plugin_load']));
$result = $reader->read('TestPlugin.load.php');
$this->assertTrue(isset($result['plugin_load']));
}
}

View file

@ -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
*

View file

@ -5253,7 +5253,7 @@ class FormHelperTest extends CakeTestCase {
));
$result = $this->Form->postButton('Send', '/', array('data' => array('extra' => 'value')));
$this->assertTrue(strpos($result, '<input type="hidden" name="data[extra]" value="value" />') !== false);
$this->assertTrue(strpos($result, '<input type="hidden" name="data[extra]" value="value"/>') !== 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, '<input type="hidden" name="data[id]" value="1" />') !== false);
$this->assertTrue(strpos($result, '<input type="hidden" name="data[id]" value="1"/>') !== false);
}
/**

View file

@ -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'), '&lt;text&gt;', '/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, '<form test>');
$result = $this->Html->useTag('form', array('test' => 'ok'));
$this->assertTags($result, array('form' => array('test' => 'ok')));
}
/**
* testDiv method
*
@ -1296,4 +1370,82 @@ class HtmlHelperTest extends CakeTestCase {
)
);
}
/**
* testLoadConfig method
*
* @return void
*/
public function testLoadConfig() {
$path = TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'config'. DS;
$result = $this->Html->loadConfig('htmlhelper_tags', $path);
$expected = array(
'tags' => array(
'form' => 'start form',
'formend' => 'finish form'
)
);
$this->assertEqual($result, $expected);
$tags = $this->Html->getAttribute('_tags');
$this->assertEqual($tags['form'], 'start form');
$this->assertEqual($tags['formend'], 'finish form');
$this->assertEqual($tags['selectend'], '</select>');
$result = $this->Html->loadConfig(array('htmlhelper_minimized.ini', 'ini'), $path);
$expected = array(
'minimizedAttributeFormat' => 'format'
);
$this->assertEqual($result, $expected);
$this->assertEqual($this->Html->getAttribute('_minimizedAttributeFormat'), 'format');
}
/**
* testLoadConfigWrongFile method
*
* @return void
* @expectedException ConfigureException
*/
public function testLoadConfigWrongFile() {
$result = $this->Html->loadConfig('wrong_file');
}
/**
* testLoadConfigWrongReader method
*
* @return void
* @expectedException ConfigureException
*/
public function testLoadConfigWrongReader() {
$path = TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'config'. DS;
$result = $this->Html->loadConfig(array('htmlhelper_tags', 'wrong_reader'), $path);
}
/**
* test parsing attributes.
*
* @return void
*/
function testParseAttributeCompact() {
$helper = new TestHtmlHelper($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)), '');
}
}

View file

@ -0,0 +1,2 @@
minimizedAttributeFormat = "format"

View file

@ -0,0 +1,8 @@
<?php
$config = array(
'tags' => array(
'form' => 'start form',
'formend' => 'finish form'
)
);

View file

@ -0,0 +1,2 @@
some_key = some_value
bool_key = 1