From ca632461f1bf1e922b4687692ced473bec1989b5 Mon Sep 17 00:00:00 2001 From: jperras Date: Sat, 19 Sep 2009 12:14:47 -0400 Subject: [PATCH 01/22] Adding tilde (~) to accepted characters for URL validation. Fixes #52, and legacy trac enhancement 6213. --- cake/libs/validation.php | 2 +- cake/tests/cases/libs/validation.test.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) 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/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/')); } /** From 42fac9ec71eaa48b4f8fc2f1fff93227fac4e580 Mon Sep 17 00:00:00 2001 From: "renan.saddam" Date: Tue, 22 Sep 2009 17:47:11 -0300 Subject: [PATCH 02/22] Fixing Xml::toArray() when blank nodes are provided. Fixes #87. --- cake/libs/xml.php | 7 +++---- cake/tests/cases/libs/xml.test.php | 26 ++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 6 deletions(-) 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/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); } From b2eb1882a4f5cfc2a0f7d74ce487c4528bbfb88d Mon Sep 17 00:00:00 2001 From: jperras Date: Wed, 23 Sep 2009 21:03:09 -0400 Subject: [PATCH 03/22] Adding convenience method Set::apply(). --- cake/libs/set.php | 34 ++++++++++++++++++++ cake/tests/cases/libs/set.test.php | 50 ++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/cake/libs/set.php b/cake/libs/set.php index e50895da1..fbf4cd614 100644 --- a/cake/libs/set.php +++ b/cake/libs/set.php @@ -1137,6 +1137,40 @@ class Set extends Object { return $sorted; } +/** + * Allows the application of a callback method to elements of an + * array extracted by a Set::extract() compatible path. + * + * @param string $path A Set-compatible path to the array value + * @param array $data + * @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 + * @return mixed Result of the callback when applied to extracted data + * + */ + 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; + } + /** * Deprecated, Set class should be called statically * diff --git a/cake/tests/cases/libs/set.test.php b/cake/tests/cases/libs/set.test.php index 1b7da9a22..993692bbb 100644 --- a/cake/tests/cases/libs/set.test.php +++ b/cake/tests/cases/libs/set.test.php @@ -2402,6 +2402,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 * From 33117ee13df1e1ccaff3c979f80ee52879611ab2 Mon Sep 17 00:00:00 2001 From: jperras Date: Wed, 23 Sep 2009 23:09:15 -0400 Subject: [PATCH 04/22] Adding additional class_exists tests to configure.test.php for App::import usage. --- cake/tests/cases/libs/configure.test.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cake/tests/cases/libs/configure.test.php b/cake/tests/cases/libs/configure.test.php index c2ece8a6a..9ecd07b82 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,12 +475,15 @@ 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); From 98bdaaf87e51dfa408127f7d2948cb0ce9410c7e Mon Sep 17 00:00:00 2001 From: jperras Date: Wed, 23 Sep 2009 23:12:22 -0400 Subject: [PATCH 05/22] Adding App::import() tests for plugin datasources. --- cake/tests/cases/libs/configure.test.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cake/tests/cases/libs/configure.test.php b/cake/tests/cases/libs/configure.test.php index 9ecd07b82..0348a42f5 100644 --- a/cake/tests/cases/libs/configure.test.php +++ b/cake/tests/cases/libs/configure.test.php @@ -487,6 +487,10 @@ class AppImportTest extends UnitTestCase { $file = App::import('Model', 'NonExistingModel'); $this->assertFalse($file); + + $file = App::import('Datasource', 'DboSource'); + $this->assertTrue($file); + $this->assertTrue(class_exists('DboSource')); } App::build(array( @@ -502,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(); } From de4737323f9650be3d07af0191cb9f61ea8bf1c2 Mon Sep 17 00:00:00 2001 From: ADmad Date: Tue, 22 Sep 2009 02:30:52 +0530 Subject: [PATCH 06/22] Updated Html and Javascript helpers to suffix asset urls with timestamp even when the app is run off a subfolder on the domain Signed-off-by: Mark Story --- cake/libs/view/helpers/html.php | 21 ++++++++----------- cake/libs/view/helpers/javascript.php | 12 ++++------- .../cases/libs/view/helpers/html.test.php | 14 +++++++++++-- .../libs/view/helpers/javascript.test.php | 4 ++-- 4 files changed, 27 insertions(+), 24 deletions(-) diff --git a/cake/libs/view/helpers/html.php b/cake/libs/view/helpers/html.php index 6be580f89..331b1ad8d 100644 --- a/cake/libs/view/helpers/html.php +++ b/cake/libs/view/helpers/html.php @@ -374,14 +374,8 @@ class HtmlHelper extends AppHelper { } } - $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 = $this->webroot($path); + if (strpos($path, '?') === false && ((Configure::read('Asset.timestamp') === true && Configure::read() > 0) || Configure::read('Asset.timestamp') === 'force')) { $url .= '?' . @filemtime(WWW_ROOT . str_replace('/', DS, $path)); } @@ -607,12 +601,15 @@ 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 ($path[0] !== '/') { + $path = 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)); + $path = $this->webroot($path) . '?' . @filemtime(WWW_ROOT . str_replace('/', DS, $path)); + } else { + $path = $this->webroot($path); } } diff --git a/cake/libs/view/helpers/javascript.php b/cake/libs/view/helpers/javascript.php index 3460f1c07..b46fc14a4 100644 --- a/cake/libs/view/helpers/javascript.php +++ b/cake/libs/view/helpers/javascript.php @@ -271,14 +271,10 @@ class JavascriptHelper extends AppHelper { } } - $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)); + if (strpos($url, '?') === false && ((Configure::read('Asset.timestamp') === true && Configure::read() > 0) || Configure::read('Asset.timestamp') === 'force')) { + $url = $this->webroot($url) . '?' . @filemtime(WWW_ROOT . str_replace('/', DS, $url)); + } else { + $url = $this->webroot($url); } if (Configure::read('Asset.filter.js')) { diff --git a/cake/tests/cases/libs/view/helpers/html.test.php b/cake/tests/cases/libs/view/helpers/html.test.php index 18c998b30..0a5b2f1f2 100644 --- a/cake/tests/cases/libs/view/helpers/html.test.php +++ b/cake/tests/cases/libs/view/helpers/html.test.php @@ -332,6 +332,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; } /** @@ -420,14 +430,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; } 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); From 26d2237df02db6a7b51a12d112cfe82272fd5357 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 22 Sep 2009 19:04:40 -0400 Subject: [PATCH 07/22] Making conditions easier to read. Adding additional test for image timestamping. Refs #108 --- cake/libs/view/helpers/html.php | 7 +++++-- cake/libs/view/helpers/javascript.php | 6 +++++- cake/tests/cases/libs/view/helpers/html.test.php | 9 +++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/cake/libs/view/helpers/html.php b/cake/libs/view/helpers/html.php index 331b1ad8d..353a78b8b 100644 --- a/cake/libs/view/helpers/html.php +++ b/cake/libs/view/helpers/html.php @@ -373,9 +373,12 @@ class HtmlHelper extends AppHelper { $path .= '.css'; } } - + $timestampEnabled = ( + (Configure::read('Asset.timestamp') === true && Configure::read() > 0) || + Configure::read('Asset.timestamp') === 'force' + ); $url = $this->webroot($path); - if (strpos($path, '?') === false && ((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)); } diff --git a/cake/libs/view/helpers/javascript.php b/cake/libs/view/helpers/javascript.php index b46fc14a4..ef4b0ab79 100644 --- a/cake/libs/view/helpers/javascript.php +++ b/cake/libs/view/helpers/javascript.php @@ -270,8 +270,12 @@ class JavascriptHelper extends AppHelper { $url .= '.js'; } } + $timestampEnabled = ( + (Configure::read('Asset.timestamp') === true && Configure::read() > 0) || + Configure::read('Asset.timestamp') === 'force' + ); - if (strpos($url, '?') === false && ((Configure::read('Asset.timestamp') === true && Configure::read() > 0) || Configure::read('Asset.timestamp') === 'force')) { + if (strpos($url, '?') === false && $timestampEnabled) { $url = $this->webroot($url) . '?' . @filemtime(WWW_ROOT . str_replace('/', DS, $url)); } else { $url = $this->webroot($url); diff --git a/cake/tests/cases/libs/view/helpers/html.test.php b/cake/tests/cases/libs/view/helpers/html.test.php index 0a5b2f1f2..831cb048b 100644 --- a/cake/tests/cases/libs/view/helpers/html.test.php +++ b/cake/tests/cases/libs/view/helpers/html.test.php @@ -308,6 +308,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; } /** From ee514f3fc6fce7bf4a4fef76af6104b85283a208 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 23 Sep 2009 23:45:11 -0400 Subject: [PATCH 08/22] Adding Helper::assetTimestamp() Refactor's repeated code from Html and Javascript Helpers. Test cases added. --- cake/libs/view/helper.php | 19 ++++++++++++ cake/tests/cases/libs/view/helper.test.php | 35 ++++++++++++++++++++++ 2 files changed, 54 insertions(+) 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/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 * From 7f49f7f455f1f818f92b11ff40bba8f817185177 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 24 Sep 2009 00:16:19 -0400 Subject: [PATCH 09/22] Updating HtmlHelper and JavascriptHelper to use Helper::assetTimestamp --- cake/libs/view/helpers/html.php | 33 ++++----------------------- cake/libs/view/helpers/javascript.php | 11 +-------- 2 files changed, 6 insertions(+), 38 deletions(-) diff --git a/cake/libs/view/helpers/html.php b/cake/libs/view/helpers/html.php index 353a78b8b..ec06ee016 100644 --- a/cake/libs/view/helpers/html.php +++ b/cake/libs/view/helpers/html.php @@ -373,14 +373,7 @@ class HtmlHelper extends AppHelper { $path .= '.css'; } } - $timestampEnabled = ( - (Configure::read('Asset.timestamp') === true && Configure::read() > 0) || - Configure::read('Asset.timestamp') === 'force' - ); - $url = $this->webroot($path); - 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); @@ -449,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); @@ -608,12 +590,7 @@ class HtmlHelper extends AppHelper { if ($path[0] !== '/') { $path = IMAGES_URL . $path; } - - if ((Configure::read('Asset.timestamp') == true && Configure::read() > 0) || Configure::read('Asset.timestamp') === 'force') { - $path = $this->webroot($path) . '?' . @filemtime(WWW_ROOT . str_replace('/', DS, $path)); - } else { - $path = $this->webroot($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 ef4b0ab79..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'; } } - $timestampEnabled = ( - (Configure::read('Asset.timestamp') === true && Configure::read() > 0) || - Configure::read('Asset.timestamp') === 'force' - ); - - if (strpos($url, '?') === false && $timestampEnabled) { - $url = $this->webroot($url) . '?' . @filemtime(WWW_ROOT . str_replace('/', DS, $url)); - } else { - $url = $this->webroot($url); - } + $url = $this->webroot($this->assetTimestamp($url)); if (Configure::read('Asset.filter.js')) { $url = str_replace(JS_URL, 'cjs/', $url); From ba7b2e9de61c3d0eaf14382fe0549e2ced927e5e Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 24 Sep 2009 00:28:27 -0400 Subject: [PATCH 10/22] Refactoring test cases to contain separate test methods for timestamped assets. --- .../cases/libs/view/helpers/html.test.php | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/cake/tests/cases/libs/view/helpers/html.test.php b/cake/tests/cases/libs/view/helpers/html.test.php index 831cb048b..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'); @@ -410,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]+/'; @@ -527,6 +539,7 @@ class HtmlHelperTest extends CakeTestCase { ); $this->assertTags($result, $expected); } + /** * test Script block generation * @@ -576,6 +589,7 @@ class HtmlHelperTest extends CakeTestCase { ); $this->assertTags($result, $expected); } + /** * test script tag output buffering when using scriptStart() and scriptEnd(); * @@ -622,6 +636,7 @@ class HtmlHelperTest extends CakeTestCase { $result = $this->Html->scriptEnd(); $this->assertNull($result); } + /** * testCharsetTag method * From ed74653d7206976a95049f01d8ac8193650fc7a2 Mon Sep 17 00:00:00 2001 From: jperras Date: Thu, 24 Sep 2009 16:23:24 -0400 Subject: [PATCH 11/22] Adding tests for ConnectionManager, and fixing a missing return value for ConnectionManager::loadDataSource(). --- cake/libs/model/connection_manager.php | 2 + .../libs/model/connection_manager.test.php | 180 ++++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 cake/tests/cases/libs/model/connection_manager.test.php diff --git a/cake/libs/model/connection_manager.php b/cake/libs/model/connection_manager.php index e9dbd8990..db7d9cf59 100644 --- a/cake/libs/model/connection_manager.php +++ b/cake/libs/model/connection_manager.php @@ -189,6 +189,8 @@ class ConnectionManager extends Object { trigger_error(sprintf($error, $conn['filename']), E_USER_ERROR); return null; } + + return true; } /** 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..4bc226854 --- /dev/null +++ b/cake/tests/cases/libs/model/connection_manager.test.php @@ -0,0 +1,180 @@ +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)); + + } + +/** + * 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); + } + +/** + * 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 load DataSource file/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 From fe32d383348672097a63f9a798ef83f1768423c2 Mon Sep 17 00:00:00 2001 From: jperras Date: Thu, 24 Sep 2009 16:32:31 -0400 Subject: [PATCH 12/22] Adding connection manager test to database group tests. --- cake/tests/groups/database.group.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cake/tests/groups/database.group.php b/cake/tests/groups/database.group.php index 8d31040fe..30d1b0724 100644 --- a/cake/tests/groups/database.group.php +++ b/cake/tests/groups/database.group.php @@ -53,7 +53,8 @@ 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 . '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'); } } From 23954a4b5e59d0f3528d4a948db4dbe9d2029c9d Mon Sep 17 00:00:00 2001 From: jperras Date: Thu, 24 Sep 2009 16:34:27 -0400 Subject: [PATCH 13/22] Fixing incorrect path to test file in database group test. --- cake/tests/groups/database.group.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cake/tests/groups/database.group.php b/cake/tests/groups/database.group.php index 30d1b0724..973227a66 100644 --- a/cake/tests/groups/database.group.php +++ b/cake/tests/groups/database.group.php @@ -53,7 +53,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 . 'schema'); + 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'); } From 0c0e5d111b42ceb648b7edc17ff81dc6ec539ce5 Mon Sep 17 00:00:00 2001 From: jperras Date: Thu, 24 Sep 2009 19:21:09 -0400 Subject: [PATCH 14/22] Adding stub datasource to test_app. --- .../models/datasources/test_source.php | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 cake/tests/test_app/models/datasources/test_source.php diff --git a/cake/tests/test_app/models/datasources/test_source.php b/cake/tests/test_app/models/datasources/test_source.php new file mode 100644 index 000000000..c2087f7a4 --- /dev/null +++ b/cake/tests/test_app/models/datasources/test_source.php @@ -0,0 +1,30 @@ + \ No newline at end of file From 11365e7a094a253fc4460848cc74c9801ef21c9e Mon Sep 17 00:00:00 2001 From: jperras Date: Thu, 24 Sep 2009 19:29:35 -0400 Subject: [PATCH 15/22] Fixing return by reference error on the use of ConnectionManager::getDataSource() on a non-existing datasource. --- cake/libs/model/connection_manager.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cake/libs/model/connection_manager.php b/cake/libs/model/connection_manager.php index db7d9cf59..8a9ea58b1 100644 --- a/cake/libs/model/connection_manager.php +++ b/cake/libs/model/connection_manager.php @@ -114,7 +114,8 @@ class ConnectionManager extends Object { $_this->_dataSources[$name]->configKeyName = $name; } else { trigger_error(sprintf(__("ConnectionManager::getDataSource - Non-existent data source %s", true), $name), E_USER_ERROR); - return null; + $null = null; + return $null; } $return =& $_this->_dataSources[$name]; From d94c7c2fe515da063ca0b29f52b6d27f2132028a Mon Sep 17 00:00:00 2001 From: jperras Date: Thu, 24 Sep 2009 19:36:04 -0400 Subject: [PATCH 16/22] Making gitignore entries absolute with respect to the repository root. --- .gitignore | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 From 12c5ebf5baa57f4652737b3d3979c163ff74815c Mon Sep 17 00:00:00 2001 From: jperras Date: Thu, 24 Sep 2009 19:37:07 -0400 Subject: [PATCH 17/22] Moving test plugin datasource to the correct location. --- .../{ => plugins/test_plugin}/models/datasources/test_source.php | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename cake/tests/test_app/{ => plugins/test_plugin}/models/datasources/test_source.php (100%) diff --git a/cake/tests/test_app/models/datasources/test_source.php b/cake/tests/test_app/plugins/test_plugin/models/datasources/test_source.php similarity index 100% rename from cake/tests/test_app/models/datasources/test_source.php rename to cake/tests/test_app/plugins/test_plugin/models/datasources/test_source.php From c3cd98af42c3e30ec3ba56bb5a781239cfd3aa66 Mon Sep 17 00:00:00 2001 From: jperras Date: Thu, 24 Sep 2009 22:56:02 -0400 Subject: [PATCH 18/22] Implementing loading datasources from plugins. --- cake/libs/model/connection_manager.php | 57 +++++++++++++------ .../libs/model/connection_manager.test.php | 24 +++++++- 2 files changed, 62 insertions(+), 19 deletions(-) diff --git a/cake/libs/model/connection_manager.php b/cake/libs/model/connection_manager.php index 8a9ea58b1..a3628056b 100644 --- a/cake/libs/model/connection_manager.php +++ b/cake/libs/model/connection_manager.php @@ -106,18 +106,32 @@ class ConnectionManager extends Object { } $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); $null = null; return $null; } + $conn = $connections[$name]; + + if (strpos($conn['classname'], '.') !== false) { + list($plugin, $class) = explode('.', $conn['classname']); + } else { + $class = $conn['classname']; + } + + $class = Inflector::classify($class); + + 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; } @@ -181,13 +195,12 @@ class ConnectionManager extends Object { 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); + $conn = array_merge(array('plugin' => null, 'classname' => null, 'parent' => null), $conn); + $class = "{$conn['plugin']}.{$conn['classname']}"; + + if (!App::import('Datasource', $class)) { + $error = __('ConnectionManager::loadDataSource - Unable to import DataSource class %s', true); + trigger_error(sprintf($error, $class), E_USER_ERROR); return null; } @@ -254,16 +267,24 @@ class ConnectionManager extends Object { $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'])); } 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($config['datasource'] . '_source')); + } } - return array('filename' => $filename, 'classname' => $classname, 'parent' => $parent); + + $driver = compact('filename', 'classname', 'parent', 'plugin'); + return $driver; } /** diff --git a/cake/tests/cases/libs/model/connection_manager.test.php b/cake/tests/cases/libs/model/connection_manager.test.php index 4bc226854..de9cc0b4f 100644 --- a/cake/tests/cases/libs/model/connection_manager.test.php +++ b/cake/tests/cases/libs/model/connection_manager.test.php @@ -88,6 +88,28 @@ class ConnectionManagerTest extends CakeTestCase { } +/** + * 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 * @@ -138,7 +160,7 @@ class ConnectionManagerTest extends CakeTestCase { } $connection = array('classname' => 'NonExistentDataSource', 'filename' => 'non_existent'); - $this->expectError(new PatternExpectation('/Unable to load DataSource file/i')); + $this->expectError(new PatternExpectation('/Unable to import DataSource class/i')); $loaded = ConnectionManager::loadDataSource($connection); $this->assertEqual($loaded, null); From c2ec96067a027661e1ea8fdd68d3853f9469de65 Mon Sep 17 00:00:00 2001 From: jperras Date: Thu, 24 Sep 2009 23:48:52 -0400 Subject: [PATCH 19/22] Refactoring ConnectionManager & tests. --- cake/libs/model/connection_manager.php | 40 +++++-------------- .../libs/model/connection_manager.test.php | 9 +++++ 2 files changed, 20 insertions(+), 29 deletions(-) diff --git a/cake/libs/model/connection_manager.php b/cake/libs/model/connection_manager.php index a3628056b..e2724924c 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,7 +104,6 @@ class ConnectionManager extends Object { $return =& $_this->_dataSources[$name]; return $return; } - $connections = $_this->enumConnectionObjects(); if (empty($connections[$name])) { @@ -112,23 +111,14 @@ class ConnectionManager extends Object { $null = null; return $null; } - $conn = $connections[$name]; - - if (strpos($conn['classname'], '.') !== false) { - list($plugin, $class) = explode('.', $conn['classname']); - } else { - $class = $conn['classname']; - } - - $class = Inflector::classify($class); + $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; @@ -152,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); } /** @@ -187,23 +172,22 @@ class ConnectionManager extends Object { $conn = $connections[$connName]; } - if (!empty($conn['parent'])) { - $_this->loadDataSource($conn['parent']); - } - if (class_exists($conn['classname'])) { return false; } + 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)) { + 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; } @@ -249,7 +233,6 @@ class ConnectionManager extends Object { $null = null; return $null; } - $_this->config->{$name} = $config; $_this->_connectionsEnum[$name] = $_this->__getDriver($config); $return =& $_this->getDataSource($name); @@ -282,7 +265,6 @@ class ConnectionManager extends Object { $classname = Inflector::camelize(strtolower($config['datasource'] . '_source')); } } - $driver = compact('filename', 'classname', 'parent', 'plugin'); return $driver; } diff --git a/cake/tests/cases/libs/model/connection_manager.test.php b/cake/tests/cases/libs/model/connection_manager.test.php index de9cc0b4f..58e0f0bda 100644 --- a/cake/tests/cases/libs/model/connection_manager.test.php +++ b/cake/tests/cases/libs/model/connection_manager.test.php @@ -86,6 +86,11 @@ class ConnectionManagerTest extends CakeTestCase { $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); + } /** @@ -137,6 +142,10 @@ class ConnectionManagerTest extends CakeTestCase { $result = ConnectionManager::getSourceName($source); $this->assertEqual($result, $name); + + $source =& new StdClass(); + $result = ConnectionManager::getSourceName($source); + $this->assertEqual($result, null); } /** From f3d0769912c522e79b22a62d4779211b9b1b9856 Mon Sep 17 00:00:00 2001 From: jperras Date: Fri, 25 Sep 2009 01:02:41 -0400 Subject: [PATCH 20/22] Renaming ConnectionManager::__getDriver() to ConnectionManager::__connectionData(). --- cake/libs/model/connection_manager.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/cake/libs/model/connection_manager.php b/cake/libs/model/connection_manager.php index e2724924c..bd1459ad1 100644 --- a/cake/libs/model/connection_manager.php +++ b/cake/libs/model/connection_manager.php @@ -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 { @@ -234,7 +234,7 @@ class ConnectionManager extends Object { return $null; } $_this->config->{$name} = $config; - $_this->_connectionsEnum[$name] = $_this->__getDriver($config); + $_this->_connectionsEnum[$name] = $_this->__connectionData($config); $return =& $_this->getDataSource($name); return $return; } @@ -242,31 +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 { if (strpos($config['datasource'], '.') !== false) { list($plugin, $classname) = explode('.', $config['datasource']); $filename = Inflector::underscore($classname); } else { $filename = $config['datasource'] . '_source'; - $classname = Inflector::camelize(strtolower($config['datasource'] . '_source')); + $classname = Inflector::camelize(strtolower($filename)); } } - $driver = compact('filename', 'classname', 'parent', 'plugin'); - return $driver; + return compact('filename', 'classname', 'parent', 'plugin'); } /** From f231b59cfb737908dcabc74b463a5d8f6f37c0ee Mon Sep 17 00:00:00 2001 From: jperras Date: Fri, 25 Sep 2009 14:31:05 -0400 Subject: [PATCH 21/22] Clarifying some Set documentation. Removing deprecated &get() method. --- cake/libs/set.php | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/cake/libs/set.php b/cake/libs/set.php index fbf4cd614..67a275a4d 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 @@ -1141,14 +1141,16 @@ class Set extends Object { * Allows the application of a callback method to elements of an * array extracted by a Set::extract() compatible path. * - * @param string $path A Set-compatible path to the array value - * @param array $data + * @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 + * @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 - * */ function apply($path, $data, $callback, $options = array()) { $defaults = array('type' => 'pass'); @@ -1170,13 +1172,5 @@ class Set extends Object { return $result; } - -/** - * Deprecated, Set class should be called statically - * - */ - function &get() { - trigger_error('get() is deprecated. Set class should be called statically', E_USER_WARNING); - } } ?> \ No newline at end of file From 03b1089f1d1a63f3c343a9f47da7be545573901e Mon Sep 17 00:00:00 2001 From: jperras Date: Fri, 25 Sep 2009 15:05:06 -0400 Subject: [PATCH 22/22] Updating docs for Set library. Deprecating Set::isEqual(). --- cake/libs/set.php | 18 +++++++++++------- cake/tests/cases/libs/set.test.php | 23 ----------------------- 2 files changed, 11 insertions(+), 30 deletions(-) diff --git a/cake/libs/set.php b/cake/libs/set.php index 67a275a4d..611d45a31 100644 --- a/cake/libs/set.php +++ b/cake/libs/set.php @@ -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) { @@ -1151,6 +1153,8 @@ class Set extends Object { * 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 apply($path, $data, $callback, $options = array()) { $defaults = array('type' => 'pass'); diff --git a/cake/tests/cases/libs/set.test.php b/cake/tests/cases/libs/set.test.php index 993692bbb..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 *