diff --git a/.gitignore b/.gitignore index 34b5594bd..9edf61016 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -app/config -app/tmp -plugins -vendors \ No newline at end of file +/app/config +/app/tmp +/plugins +/vendors \ No newline at end of file diff --git a/cake/libs/model/connection_manager.php b/cake/libs/model/connection_manager.php index e9dbd8990..bd1459ad1 100644 --- a/cake/libs/model/connection_manager.php +++ b/cake/libs/model/connection_manager.php @@ -25,8 +25,8 @@ * @lastmodified $Date$ * @license http://www.opensource.org/licenses/mit-license.php The MIT License */ -uses ('model' . DS . 'datasources' . DS . 'datasource'); -config('database'); +require LIBS . 'model' . DS . 'datasources' . DS . 'datasource.php'; +include_once CONFIGS . 'database.php'; /** * Manages loaded instances of DataSource objects @@ -104,18 +104,23 @@ class ConnectionManager extends Object { $return =& $_this->_dataSources[$name]; return $return; } - $connections = $_this->enumConnectionObjects(); - if (!empty($connections[$name])) { - $conn = $connections[$name]; - $class = $conn['classname']; - $_this->loadDataSource($name); - $_this->_dataSources[$name] =& new $class($_this->config->{$name}); - $_this->_dataSources[$name]->configKeyName = $name; - } else { + + if (empty($connections[$name])) { trigger_error(sprintf(__("ConnectionManager::getDataSource - Non-existent data source %s", true), $name), E_USER_ERROR); - return null; + $null = null; + return $null; } + $conn = $connections[$name]; + $class = $conn['classname']; + + if ($_this->loadDataSource($name) === null) { + trigger_error(sprintf(__("ConnectionManager::getDataSource - Could not load class %s", true), $class), E_USER_ERROR); + $null = null; + return $null; + } + $_this->_dataSources[$name] =& new $class($_this->config->{$name}); + $_this->_dataSources[$name]->configKeyName = $name; $return =& $_this->_dataSources[$name]; return $return; @@ -137,19 +142,14 @@ class ConnectionManager extends Object { * Gets a DataSource name from an object reference * * @param object $source DataSource object - * @return string Datasource name + * @return string Datasource name, or null if source is not present + * in the ConnectionManager. * @access public * @static */ function getSourceName(&$source) { $_this =& ConnectionManager::getInstance(); - $names = array_keys($_this->_dataSources); - for ($i = 0; $i < count($names); $i++) { - if ($_this->_dataSources[$names[$i]] === $source) { - return $names[$i]; - } - } - return null; + return array_search($source, $_this->_dataSources); } /** @@ -172,23 +172,23 @@ class ConnectionManager extends Object { $conn = $connections[$connName]; } - if (!empty($conn['parent'])) { - $_this->loadDataSource($conn['parent']); - } - if (class_exists($conn['classname'])) { return false; } - if (file_exists(MODELS . 'datasources' . DS . $conn['filename'] . '.php')) { - require (MODELS . 'datasources' . DS . $conn['filename'] . '.php'); - } elseif (fileExistsInPath(LIBS . 'model' . DS . 'datasources' . DS . $conn['filename'] . '.php')) { - require (LIBS . 'model' . DS . 'datasources' . DS . $conn['filename'] . '.php'); - } else { - $error = __('Unable to load DataSource file %s.php', true); - trigger_error(sprintf($error, $conn['filename']), E_USER_ERROR); + if (!empty($conn['parent'])) { + $_this->loadDataSource($conn['parent']); + } + + $conn = array_merge(array('plugin' => null, 'classname' => null, 'parent' => null), $conn); + $class = "{$conn['plugin']}.{$conn['classname']}"; + + if (!App::import('Datasource', $class, false)) { + $error = __('ConnectionManager::loadDataSource - Unable to import DataSource class %s', true); + trigger_error(sprintf($error, $class), E_USER_ERROR); return null; } + return true; } /** @@ -209,7 +209,7 @@ class ConnectionManager extends Object { if ($connections != null) { foreach ($connections as $name => $config) { - $_this->_connectionsEnum[$name] = $_this->__getDriver($config); + $_this->_connectionsEnum[$name] = $_this->__connectionData($config); } return $_this->_connectionsEnum; } else { @@ -233,9 +233,8 @@ class ConnectionManager extends Object { $null = null; return $null; } - $_this->config->{$name} = $config; - $_this->_connectionsEnum[$name] = $_this->__getDriver($config); + $_this->_connectionsEnum[$name] = $_this->__connectionData($config); $return =& $_this->getDataSource($name); return $return; } @@ -243,24 +242,31 @@ class ConnectionManager extends Object { /** * Returns the file, class name, and parent for the given driver. * - * @return array An indexed array with: filename, classname, and parent + * @return array An indexed array with: filename, classname, plugin and parent * @access private */ - function __getDriver($config) { + function __connectionData($config) { if (!isset($config['datasource'])) { $config['datasource'] = 'dbo'; } + $filename = $classname = $parent = $plugin = null; - if (isset($config['driver']) && $config['driver'] != null && !empty($config['driver'])) { - $filename = $config['datasource'] . DS . $config['datasource'] . '_' . $config['driver']; - $classname = Inflector::camelize(strtolower($config['datasource'] . '_' . $config['driver'])); - $parent = $this->__getDriver(array('datasource' => $config['datasource'])); + if (!empty($config['driver'])) { + $source = $config['datasource'] . '_' . $config['driver']; + + $filename = $config['datasource'] . DS . $source; + $classname = Inflector::camelize(strtolower($source)); + $parent = $this->__connectionData(array('datasource' => $config['datasource'])); } else { - $filename = $config['datasource'] . '_source'; - $classname = Inflector::camelize(strtolower($config['datasource'] . '_source')); - $parent = null; + if (strpos($config['datasource'], '.') !== false) { + list($plugin, $classname) = explode('.', $config['datasource']); + $filename = Inflector::underscore($classname); + } else { + $filename = $config['datasource'] . '_source'; + $classname = Inflector::camelize(strtolower($filename)); + } } - return array('filename' => $filename, 'classname' => $classname, 'parent' => $parent); + return compact('filename', 'classname', 'parent', 'plugin'); } /** diff --git a/cake/libs/set.php b/cake/libs/set.php index e50895da1..611d45a31 100644 --- a/cake/libs/set.php +++ b/cake/libs/set.php @@ -373,8 +373,8 @@ class Set extends Object { * Bugs as you find them. Suggestions for additional features to imlement are also very welcome! * * @param string $path An absolute XPath 2.0 path - * @param string $data An array of data to extract from - * @param string $options Currently only supports 'flatten' which can be disabled for higher XPath-ness + * @param array $data An array of data to extract from + * @param array $options Currently only supports 'flatten' which can be disabled for higher XPath-ness * @return array An array of matched items * @access public * @static @@ -820,14 +820,17 @@ class Set extends Object { /** * Determines if two Sets or arrays are equal + * This method is deprecated, and will be removed in a future release. * * @param array $val1 First value * @param array $val2 Second value * @return boolean true if they are equal, false otherwise * @access public * @static + * @deprecated */ function isEqual($val1, $val2 = null) { + trigger_error('Set::isEqual() is deprecated. Please use standard comparison operators instead.', E_USER_WARNING); return ($val1 == $val2); } @@ -1002,11 +1005,10 @@ class Set extends Object { } /** - * Converts an object into an array. If $object is no object, reverse - * will return the same value. - * + * Converts an object into an array. * @param object $object Object to reverse - * @return array + * @return array Array representation of given object + * @public * @static */ function reverse($object) { @@ -1110,10 +1112,10 @@ class Set extends Object { /** * Sorts an array by any value, determined by a Set-compatible path * - * @param array $data + * @param array $data An array of data to sort * @param string $path A Set-compatible path to the array value - * @param string $dir asc/desc - * @return array + * @param string $dir Direction of sorting - either ascending (ASC), or descending (DESC) + * @return array Sorted array of data * @static */ function sort($data, $path, $dir) { @@ -1138,11 +1140,41 @@ class Set extends Object { } /** - * Deprecated, Set class should be called statically + * Allows the application of a callback method to elements of an + * array extracted by a Set::extract() compatible path. * + * @param mixed $path Set-compatible path to the array value + * @param array $data An array of data to extract from & then process with the $callback. + * @param mixed $callback Callback method to be applied to extracted data. + * See http://ca2.php.net/manual/en/language.pseudo-types.php#language.types.callback for examples + * of callback formats. + * @param array $options Options are: + * - type : can be pass, map, or reduce. Map will handoff the given callback + * to array_map, reduce will handoff to array_reduce, and pass will + * use call_user_func_array(). + * @return mixed Result of the callback when applied to extracted data + * @access public + * @static */ - function &get() { - trigger_error('get() is deprecated. Set class should be called statically', E_USER_WARNING); + function apply($path, $data, $callback, $options = array()) { + $defaults = array('type' => 'pass'); + $options = array_merge($defaults, $options); + + $extracted = Set::extract($path, $data); + + if ($options['type'] === 'map') { + $result = array_map($callback, &$extracted); + + } elseif ($options['type'] === 'reduce') { + $result = array_reduce(&$extracted, $callback); + + } elseif ($options['type'] === 'pass') { + $result = call_user_func_array($callback, array($extracted)); + } else { + return null; + } + + return $result; } } ?> \ No newline at end of file diff --git a/cake/libs/validation.php b/cake/libs/validation.php index ee8db26d4..41673b50d 100644 --- a/cake/libs/validation.php +++ b/cake/libs/validation.php @@ -843,7 +843,7 @@ class Validation extends Object { function url($check, $strict = false) { $_this =& Validation::getInstance(); $_this->check = $check; - $validChars = '([' . preg_quote('!"$&\'()*+,-.@_:;=') . '\/0-9a-z]|(%[0-9a-f]{2}))'; + $validChars = '([' . preg_quote('!"$&\'()*+,-.@_:;=~') . '\/0-9a-z]|(%[0-9a-f]{2}))'; $_this->regex = '/^(?:(?:https?|ftps?|file|news|gopher):\/\/)' . (!empty($strict) ? '' : '?') . '(?:' . $_this->__pattern['ip'] . '|' . $_this->__pattern['hostname'] . ')(?::[1-9][0-9]{0,3})?' . '(?:\/?|\/' . $validChars . '*)?' . diff --git a/cake/libs/view/helper.php b/cake/libs/view/helper.php index fedb9586f..fd4a610f3 100644 --- a/cake/libs/view/helper.php +++ b/cake/libs/view/helper.php @@ -224,6 +224,25 @@ class Helper extends Overloadable { return $webPath; } +/** + * Adds a timestamp to a file based resource based on the value of `Asset.timestamp` in + * Configure. If Asset.timestamp is true and debug > 0, or Asset.timestamp == 'force' + * a timestamp will be added. + * + * @param string $path The file path to timestamp, the path must be inside WWW_ROOT + * @return string Path with a timestamp added, or not. + **/ + function assetTimestamp($path) { + $timestampEnabled = ( + (Configure::read('Asset.timestamp') === true && Configure::read() > 0) || + Configure::read('Asset.timestamp') === 'force' + ); + if (strpos($path, '?') === false && $timestampEnabled) { + $path .= '?' . @filemtime(WWW_ROOT . str_replace('/', DS, $path)); + } + return $path; + } + /** * Used to remove harmful tags from content * diff --git a/cake/libs/view/helpers/html.php b/cake/libs/view/helpers/html.php index 6be580f89..ec06ee016 100644 --- a/cake/libs/view/helpers/html.php +++ b/cake/libs/view/helpers/html.php @@ -373,17 +373,7 @@ class HtmlHelper extends AppHelper { $path .= '.css'; } } - - $path = $this->webroot($path); - - $url = $path; - $timestampEnabled = ( - (Configure::read('Asset.timestamp') === true && Configure::read() > 0) || - Configure::read('Asset.timestamp') === 'force' - ); - if (strpos($path, '?') === false && $timestampEnabled) { - $url .= '?' . @filemtime(WWW_ROOT . str_replace('/', DS, $path)); - } + $url = $this->webroot($this->assetTimestamp($path)); if (Configure::read('Asset.filter.css')) { $url = str_replace(CSS_URL, 'ccss/', $url); @@ -452,21 +442,10 @@ class HtmlHelper extends AppHelper { if ($url[0] !== '/') { $url = JS_URL . $url; } - $url = $this->webroot($url); - if (strpos($url, '?') === false) { - if (strpos($url, '.js') === false) { - $url .= '.js'; - } - } - - $timestampEnabled = ( - (Configure::read('Asset.timestamp') === true && Configure::read('debug') > 0) || - Configure::read('Asset.timestamp') === 'force' - ); - - if (strpos($url, '?') === false && $timestampEnabled) { - $url .= '?' . @filemtime(WWW_ROOT . str_replace('/', DS, $url)); + if (strpos($url, '?') === false && strpos($url, '.js') === false) { + $url .= '.js'; } + $url = $this->webroot($this->assetTimestamp($url)); if (Configure::read('Asset.filter.js')) { $url = str_replace(JS_URL, 'cjs/', $url); @@ -607,13 +586,11 @@ class HtmlHelper extends AppHelper { function image($path, $options = array()) { if (is_array($path)) { $path = $this->url($path); - } elseif ($path[0] === '/') { - $path = $this->webroot($path); } elseif (strpos($path, '://') === false) { - $path = $this->webroot(IMAGES_URL . $path); - if ((Configure::read('Asset.timestamp') == true && Configure::read() > 0) || Configure::read('Asset.timestamp') === 'force') { - $path .= '?' . @filemtime(str_replace('/', DS, WWW_ROOT . $path)); + if ($path[0] !== '/') { + $path = IMAGES_URL . $path; } + $path = $this->webroot($this->assetTimestamp($path)); } if (!isset($options['alt'])) { diff --git a/cake/libs/view/helpers/javascript.php b/cake/libs/view/helpers/javascript.php index 3460f1c07..b378bbf0a 100644 --- a/cake/libs/view/helpers/javascript.php +++ b/cake/libs/view/helpers/javascript.php @@ -270,16 +270,7 @@ class JavascriptHelper extends AppHelper { $url .= '.js'; } } - - $url = $this->webroot($url); - $timestampEnabled = ( - (Configure::read('Asset.timestamp') === true && Configure::read() > 0) || - Configure::read('Asset.timestamp') === 'force' - ); - - if (strpos($url, '?') === false && $timestampEnabled) { - $url .= '?' . @filemtime(WWW_ROOT . str_replace('/', DS, $url)); - } + $url = $this->webroot($this->assetTimestamp($url)); if (Configure::read('Asset.filter.js')) { $url = str_replace(JS_URL, 'cjs/', $url); diff --git a/cake/libs/xml.php b/cake/libs/xml.php index 830701e26..d9d804e40 100644 --- a/cake/libs/xml.php +++ b/cake/libs/xml.php @@ -704,7 +704,6 @@ class XmlNode extends Object { continue; } elseif (isset($child->children[0]) && is_a($child->children[0], 'XmlTextNode')) { $value = $child->children[0]->value; - if ($child->attributes) { $value = array_merge(array('value' => $value), $child->attributes); } @@ -720,10 +719,10 @@ class XmlNode extends Object { continue; } elseif (count($child->children) === 0 && $child->value == '') { $value = $child->attributes; - if (isset($out[$child->name]) || isset($multi[$key])) { + if (isset($out[$key]) || isset($multi[$key])) { if (!isset($multi[$key])) { - $multi[$key] = array($out[$child->name]); - unset($out[$child->name]); + $multi[$key] = array($out[$key]); + unset($out[$key]); } $multi[$key][] = $value; } elseif (!empty($value)) { diff --git a/cake/tests/cases/libs/configure.test.php b/cake/tests/cases/libs/configure.test.php index c2ece8a6a..0348a42f5 100644 --- a/cake/tests/cases/libs/configure.test.php +++ b/cake/tests/cases/libs/configure.test.php @@ -409,21 +409,26 @@ class AppImportTest extends UnitTestCase { $file = App::import('Model', 'Model', false); $this->assertTrue($file); + $this->assertTrue(class_exists('Model')); $file = App::import('Controller', 'Controller', false); $this->assertTrue($file); + $this->assertTrue(class_exists('Controller')); $file = App::import('Component', 'Component', false); $this->assertTrue($file); + $this->assertTrue(class_exists('Component')); $file = App::import('Shell', 'Shell', false); $this->assertTrue($file); + $this->assertTrue(class_exists('Shell')); $file = App::import('Model', 'SomeRandomModelThatDoesNotExist', false); $this->assertFalse($file); $file = App::import('Model', 'AppModel', false); $this->assertTrue($file); + $this->assertTrue(class_exists('AppModel')); $file = App::import('WrongType', null, true, array(), ''); $this->assertTrue($file); @@ -456,6 +461,7 @@ class AppImportTest extends UnitTestCase { $file = App::import('Controller', 'Pages'); $this->assertTrue($file); + $this->assertTrue(class_exists('PagesController')); $classes = array_flip(get_declared_classes()); @@ -469,15 +475,22 @@ class AppImportTest extends UnitTestCase { $file = App::import('Behavior', 'Containable'); $this->assertTrue($file); + $this->assertTrue(class_exists('ContainableBehavior')); $file = App::import('Component', 'RequestHandler'); $this->assertTrue($file); + $this->assertTrue(class_exists('RequestHandlerComponent')); $file = App::import('Helper', 'Form'); $this->assertTrue($file); + $this->assertTrue(class_exists('FormHelper')); $file = App::import('Model', 'NonExistingModel'); $this->assertFalse($file); + + $file = App::import('Datasource', 'DboSource'); + $this->assertTrue($file); + $this->assertTrue(class_exists('DboSource')); } App::build(array( @@ -493,6 +506,10 @@ class AppImportTest extends UnitTestCase { $this->assertTrue($result); $this->assertTrue(class_exists('OtherHelperHelper')); + $result = App::import('Datasource', 'TestPlugin.TestSource'); + $this->assertTrue($result); + $this->assertTrue(class_exists('TestSource')); + App::build(); } diff --git a/cake/tests/cases/libs/model/connection_manager.test.php b/cake/tests/cases/libs/model/connection_manager.test.php new file mode 100644 index 000000000..58e0f0bda --- /dev/null +++ b/cake/tests/cases/libs/model/connection_manager.test.php @@ -0,0 +1,211 @@ +ConnectionManager = ConnectionManager::getInstance(); + } + +/** + * tearDown method + * + * @access public + * @return void + */ + function tearDown() { + unset($this->ConnectionManager); + } + +/** + * testInstantiation method + * + * @access public + * @return void + */ + function testInstantiation() { + $this->assertTrue(is_a($this->ConnectionManager, 'ConnectionManager')); + } + +/** + * testEnumConnectionObjects method + * + * @access public + * @return void + */ + function testEnumConnectionObjects() { + $sources = ConnectionManager::enumConnectionObjects(); + $this->assertTrue(count($sources) >= 1); + + $connections = array('default', 'test', 'test_suite'); + $this->assertTrue(count(array_intersect(array_keys($sources), $connections)) >= 1); + } + +/** + * testGetDataSource method + * + * @access public + * @return void + */ + function testGetDataSource() { + $connections = ConnectionManager::enumConnectionObjects(); + $this->assertTrue(count(array_keys($connections) >= 1)); + + $source = ConnectionManager::getDataSource(key($connections)); + $this->assertTrue(is_object($source)); + + $this->expectError(new PatternExpectation('/Non-existent data source/i')); + + $source = ConnectionManager::getDataSource('non_existent_source'); + $this->assertEqual($source, null); + + } + +/** + * testGetPluginDataSource method + * + * @access public + * @return void + */ + function testGetPluginDataSource() { + App::build(array( + 'plugins' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'plugins' . DS) + )); + + $name = 'test_source'; + $config = array('datasource' => 'TestPlugin.TestSource'); + $connection = ConnectionManager::create($name, $config); + + $this->assertTrue(class_exists('TestSource')); + $this->assertEqual($connection->configKeyName, $name); + $this->assertEqual($connection->config, $config); + + App::build(); + } + +/** + * testSourceList method + * + * @access public + * @return void + */ + function testSourceList() { + $sources = ConnectionManager::sourceList(); + $this->assertTrue(count($sources) >= 1); + + $connections = array('default', 'test', 'test_suite'); + $this->assertTrue(count(array_intersect($sources, $connections)) >= 1); + } + +/** + * testGetSourceName method + * + * @access public + * @return void + */ + function testGetSourceName() { + $connections = ConnectionManager::enumConnectionObjects(); + $name = key($connections); + $source = ConnectionManager::getDataSource($name); + $result = ConnectionManager::getSourceName($source); + + $this->assertEqual($result, $name); + + $source =& new StdClass(); + $result = ConnectionManager::getSourceName($source); + $this->assertEqual($result, null); + } + +/** + * testLoadDataSource method + * + * @access public + * @return void + */ + function testLoadDataSource() { + $connections = array( + array('classname' => 'DboMysql', 'filename' => 'dbo' . DS . 'dbo_mysql'), + array('classname' => 'DboMysqli', 'filename' => 'dbo' . DS . 'dbo_mysqli'), + array('classname' => 'DboMssql', 'filename' => 'dbo' . DS . 'dbo_mssql'), + array('classname' => 'DboOracle', 'filename' => 'dbo' . DS . 'dbo_oracle'), + ); + + foreach ($connections as $connection) { + $exists = class_exists($connection['classname']); + $loaded = ConnectionManager::loadDataSource($connection); + $this->assertEqual($loaded, !$exists, "%s Failed loading the {$connection['classname']} datasource"); + } + + $connection = array('classname' => 'NonExistentDataSource', 'filename' => 'non_existent'); + $this->expectError(new PatternExpectation('/Unable to import DataSource class/i')); + + $loaded = ConnectionManager::loadDataSource($connection); + $this->assertEqual($loaded, null); + } + +/** + * testCreateDataSource method + * + * @access public + * @return void + */ + function testCreateDataSourceWithIntegrationTests() { + $name = 'test_created_connection'; + + $connections = ConnectionManager::enumConnectionObjects(); + $this->assertTrue(count(array_keys($connections) >= 1)); + + $source = ConnectionManager::getDataSource(key($connections)); + $this->assertTrue(is_object($source)); + + $config = $source->config; + $connection = ConnectionManager::create($name, $config); + + $this->assertTrue(is_object($connection)); + $this->assertEqual($name, $connection->configKeyName); + $this->assertEqual($name, ConnectionManager::getSourceName($connection)); + + $source = ConnectionManager::create(null, array()); + $this->assertEqual($source, null); + + $source = ConnectionManager::create('another_test', array()); + $this->assertEqual($source, null); + + $config = array('classname' => 'DboMysql', 'filename' => 'dbo' . DS . 'dbo_mysql'); + $source = ConnectionManager::create(null, $config); + $this->assertEqual($source, null); + } +} +?> \ No newline at end of file diff --git a/cake/tests/cases/libs/set.test.php b/cake/tests/cases/libs/set.test.php index 1b7da9a22..18dc92ec9 100644 --- a/cake/tests/cases/libs/set.test.php +++ b/cake/tests/cases/libs/set.test.php @@ -1450,29 +1450,6 @@ class SetTest extends CakeTestCase { $this->assertIdentical($result, $expected); } -/** - * testIsEqual method - * - * @access public - * @return void - */ - function testIsEqual() { - $a = array( - 0 => array('name' => 'main'), - 1 => array('name' => 'about') - ); - $b = array( - 0 => array('name' => 'main'), - 1 => array('name' => 'about'), - 2 => array('name' => 'contact') - ); - - $this->assertTrue(Set::isEqual($a, $a)); - $this->assertTrue(Set::isEqual($b, $b)); - $this->assertFalse(Set::isEqual($a, $b)); - $this->assertFalse(Set::isEqual($b, $a)); - } - /** * testContains method * @@ -2402,6 +2379,56 @@ class SetTest extends CakeTestCase { $this->assertIdentical($result, $array1+$array2); } +/** + * testSetApply method + * @access public + * @return void + * + */ + function testApply() { + $data = array( + array('Movie' => array('id' => 1, 'title' => 'movie 3', 'rating' => 5)), + array('Movie' => array('id' => 1, 'title' => 'movie 1', 'rating' => 1)), + array('Movie' => array('id' => 1, 'title' => 'movie 2', 'rating' => 3)) + ); + + $result = Set::apply('/Movie/rating', $data, 'array_sum'); + $expected = 9; + $this->assertEqual($result, $expected); + + $result = Set::apply('/Movie/rating', $data, 'array_product'); + $expected = 15; + $this->assertEqual($result, $expected); + + $result = Set::apply('/Movie/title', $data, 'ucfirst', array('type' => 'map')); + $expected = array('Movie 3', 'Movie 1', 'Movie 2'); + $this->assertEqual($result, $expected); + + $result = Set::apply('/Movie/title', $data, 'strtoupper', array('type' => 'map')); + $expected = array('MOVIE 3', 'MOVIE 1', 'MOVIE 2'); + $this->assertEqual($result, $expected); + + $result = Set::apply('/Movie/rating', $data, array('self', '_method'), array('type' => 'reduce')); + $expected = 9; + $this->assertEqual($result, $expected); + + $result = Set::apply('/Movie/rating', $data, 'strtoupper', array('type' => 'non existing type')); + $expected = null; + $this->assertEqual($result, $expected); + + } + +/** + * Helper method to test Set::apply() + * + * @access protected + * @return void + */ + function _method($val1, $val2) { + $val1 += $val2; + return $val1; + } + /** * testXmlSetReverse method * diff --git a/cake/tests/cases/libs/validation.test.php b/cake/tests/cases/libs/validation.test.php index bde7d34dc..08e988359 100644 --- a/cake/tests/cases/libs/validation.test.php +++ b/cake/tests/cases/libs/validation.test.php @@ -1755,6 +1755,7 @@ class ValidationTest extends CakeTestCase { $this->assertFalse(Validation::url('http://en.(wikipedia).org/')); $this->assertFalse(Validation::url('www.cakephp.org', true)); $this->assertTrue(Validation::url('http://www.cakephp.org', true)); + $this->assertTrue(Validation::url('http://example.com/~userdir/')); } /** diff --git a/cake/tests/cases/libs/view/helper.test.php b/cake/tests/cases/libs/view/helper.test.php index 6b314dece..9bf9d37c9 100644 --- a/cake/tests/cases/libs/view/helper.test.php +++ b/cake/tests/cases/libs/view/helper.test.php @@ -411,6 +411,41 @@ class HelperTest extends CakeTestCase { $this->assertEqual($result, "/posts/index/page:1?one=value&two=value&three=purple"); } +/** + * test assetTimestamp application + * + * @return void + **/ + function testAssetTimestamp() { + $_timestamp = Configure::read('Asset.timestamp'); + $_debug = Configure::read('debug'); + + Configure::write('Asset.timestamp', false); + $result = $this->Helper->assetTimestamp(CSS_URL . 'cake.generic.css'); + $this->assertEqual($result, CSS_URL . 'cake.generic.css'); + + Configure::write('Asset.timestamp', true); + Configure::write('debug', 0); + $result = $this->Helper->assetTimestamp(CSS_URL . 'cake.generic.css'); + $this->assertEqual($result, CSS_URL . 'cake.generic.css'); + + Configure::write('Asset.timestamp', true); + Configure::write('debug', 2); + $result = $this->Helper->assetTimestamp(CSS_URL . 'cake.generic.css'); + $this->assertPattern('/' . preg_quote(CSS_URL . 'cake.generic.css?', '/') . '[0-9]+/', $result); + + Configure::write('Asset.timestamp', 'force'); + Configure::write('debug', 0); + $result = $this->Helper->assetTimestamp(CSS_URL . 'cake.generic.css'); + $this->assertPattern('/' . preg_quote(CSS_URL . 'cake.generic.css?', '/') . '[0-9]+/', $result); + + $result = $this->Helper->assetTimestamp(CSS_URL . 'cake.generic.css?someparam'); + $this->assertEqual($result, CSS_URL . 'cake.generic.css?someparam'); + + Configure::write('debug', $_debug); + Configure::write('Asset.timestamp', $_timestamp); + } + /** * testFieldsWithSameName method * diff --git a/cake/tests/cases/libs/view/helpers/html.test.php b/cake/tests/cases/libs/view/helpers/html.test.php index 18c998b30..cee2b7916 100644 --- a/cake/tests/cases/libs/view/helpers/html.test.php +++ b/cake/tests/cases/libs/view/helpers/html.test.php @@ -297,7 +297,14 @@ class HtmlHelperTest extends CakeTestCase { $result = $this->Html->image('/test/view/1.gif'); $this->assertTags($result, array('img' => array('src' => '/test/view/1.gif', 'alt' => ''))); + } +/** + * test image() with Asset.timestamp + * + * @return void + **/ + function testImageTagWithTimestampping() { Configure::write('Asset.timestamp', 'force'); $result = $this->Html->image('cake.icon.gif'); @@ -308,6 +315,15 @@ class HtmlHelperTest extends CakeTestCase { $result = $this->Html->image('cake.icon.gif'); $this->assertTags($result, array('img' => array('src' => 'preg:/img\/cake\.icon\.gif\?\d+/', 'alt' => ''))); + + $webroot = $this->Html->webroot; + $this->Html->webroot = '/testing/longer/'; + $result = $this->Html->image('cake.icon.gif'); + $expected = array( + 'img' => array('src' => 'preg:/\/testing\/longer\/img\/cake\.icon\.gif\?[0-9]+/', 'alt' => '') + ); + $this->assertTags($result, $expected); + $this->Html->webroot = $webroot; } /** @@ -332,6 +348,16 @@ class HtmlHelperTest extends CakeTestCase { 'src' => 'preg:/themed\/default\/img\/cake\.power\.gif\?\d+/', 'alt' => '' ))); + + $webroot = $this->Html->webroot; + $this->Html->webroot = '/testing/'; + $result = $this->Html->image('cake.power.gif'); + $this->assertTags($result, array( + 'img' => array( + 'src' => 'preg:/\/testing\/themed\/default\/img\/cake\.power\.gif\?\d+/', + 'alt' => '' + ))); + $this->Html->webroot = $webroot; } /** @@ -391,15 +417,20 @@ class HtmlHelperTest extends CakeTestCase { $expected['link']['href'] = 'preg:/.*css\/vendor\.generic\.css/'; $this->assertTags($result[1], $expected); $this->assertEqual(count($result), 2); + } +/** + * test use of css() and timestamping + * + * @return void + **/ + function testCssTimestamping() { Configure::write('debug', 2); Configure::write('Asset.timestamp', true); - Configure::write('Asset.filter.css', 'css.php'); - $result = $this->Html->css('cake.generic'); - $expected['link']['href'] = 'preg:/.*ccss\/cake\.generic\.css\?[0-9]+/'; - $this->assertTags($result, $expected); - Configure::write('Asset.filter.css', false); + $expected = array( + 'link' => array('rel' => 'stylesheet', 'type' => 'text/css', 'href' => '') + ); $result = $this->Html->css('cake.generic'); $expected['link']['href'] = 'preg:/.*css\/cake\.generic\.css\?[0-9]+/'; @@ -420,14 +451,14 @@ class HtmlHelperTest extends CakeTestCase { $webroot = $this->Html->webroot; $this->Html->webroot = '/testing/'; $result = $this->Html->css('cake.generic'); - $expected['link']['href'] = 'preg:/\/testing\/css\/cake\.generic\.css\?/'; + $expected['link']['href'] = 'preg:/\/testing\/css\/cake\.generic\.css\?[0-9]+/'; $this->assertTags($result, $expected); $this->Html->webroot = $webroot; $webroot = $this->Html->webroot; $this->Html->webroot = '/testing/longer/'; $result = $this->Html->css('cake.generic'); - $expected['link']['href'] = 'preg:/\/testing\/longer\/css\/cake\.generic\.css\?/'; + $expected['link']['href'] = 'preg:/\/testing\/longer\/css\/cake\.generic\.css\?[0-9]+/'; $this->assertTags($result, $expected); $this->Html->webroot = $webroot; } @@ -508,6 +539,7 @@ class HtmlHelperTest extends CakeTestCase { ); $this->assertTags($result, $expected); } + /** * test Script block generation * @@ -557,6 +589,7 @@ class HtmlHelperTest extends CakeTestCase { ); $this->assertTags($result, $expected); } + /** * test script tag output buffering when using scriptStart() and scriptEnd(); * @@ -603,6 +636,7 @@ class HtmlHelperTest extends CakeTestCase { $result = $this->Html->scriptEnd(); $this->assertNull($result); } + /** * testCharsetTag method * diff --git a/cake/tests/cases/libs/view/helpers/javascript.test.php b/cake/tests/cases/libs/view/helpers/javascript.test.php index eb64fec96..0ceea78f0 100644 --- a/cake/tests/cases/libs/view/helpers/javascript.test.php +++ b/cake/tests/cases/libs/view/helpers/javascript.test.php @@ -278,11 +278,11 @@ class JavascriptTest extends CakeTestCase { $this->Javascript->webroot = '/testing/'; $result = $this->Javascript->link('__cake_js_test'); - $this->assertPattern('/^]+src="\/testing\/js\/__cake_js_test\.js\?"[^<>]*>/', $result); + $this->assertPattern('/^]+src="\/testing\/js\/__cake_js_test\.js\?\d+"[^<>]*>/', $result); $this->Javascript->webroot = '/testing/longer/'; $result = $this->Javascript->link('__cake_js_test'); - $this->assertPattern('/^]+src="\/testing\/longer\/js\/__cake_js_test\.js\?"[^<>]*>/', $result); + $this->assertPattern('/^]+src="\/testing\/longer\/js\/__cake_js_test\.js\?\d+"[^<>]*>/', $result); $this->Javascript->webroot = $webroot; Configure::write('debug', $debug); diff --git a/cake/tests/cases/libs/xml.test.php b/cake/tests/cases/libs/xml.test.php index 5d5a01358..9082b8638 100644 --- a/cake/tests/cases/libs/xml.test.php +++ b/cake/tests/cases/libs/xml.test.php @@ -784,7 +784,7 @@ class XmlTest extends CakeTestCase { /** * test that empty values do not casefold collapse - * + * * @see http://code.cakephp.org/tickets/view/8 * @return void **/ @@ -820,7 +820,7 @@ class XmlTest extends CakeTestCase { varchar(45) '; - + $xml =& new XML($emptyValue); $expected = array( 'Method' => array( @@ -1204,7 +1204,29 @@ class XmlTest extends CakeTestCase { ) ) )); + $this->assertEqual($result, $expected); + $text = ' + + + + + + + '; + $xml = new Xml($text); + $result = $xml->toArray(); + $expected = array( + 'Root' => array( + 'Child' => array( + array('id' => 1, 'other' => 1), + array('id' => 2, 'other' => 1), + array('id' => 3, 'other' => 1), + array('id' => 4, 'other' => 1), + array('id' => 5, 'other' => 1) + ) + ) + ); $this->assertEqual($result, $expected); } diff --git a/cake/tests/groups/database.group.php b/cake/tests/groups/database.group.php index 8d31040fe..973227a66 100644 --- a/cake/tests/groups/database.group.php +++ b/cake/tests/groups/database.group.php @@ -54,6 +54,7 @@ class DatabaseGroupTest extends TestSuite { function DatabaseGroupTest() { TestManager::addTestFile($this, CORE_TEST_CASES . DS . 'libs' . DS . 'model' . DS . 'db_acl'); TestManager::addTestFile($this, CORE_TEST_CASES . DS . 'libs' . DS . 'model' . DS . 'cake_schema'); + TestManager::addTestFile($this, CORE_TEST_CASES . DS . 'libs' . DS . 'model' . DS . 'connection_manager'); TestManager::addTestFile($this, CORE_TEST_CASES . DS . 'libs' . DS . 'model' . DS . 'datasources' . DS . 'dbo_source'); } } diff --git a/cake/tests/test_app/plugins/test_plugin/models/datasources/test_source.php b/cake/tests/test_app/plugins/test_plugin/models/datasources/test_source.php new file mode 100644 index 000000000..c2087f7a4 --- /dev/null +++ b/cake/tests/test_app/plugins/test_plugin/models/datasources/test_source.php @@ -0,0 +1,30 @@ + \ No newline at end of file