Browse Source

Merge remote-tracking branch 'origin/master' into 3.0

Conflicts:
	lib/Cake/Utility/Time.php
	lib/Cake/VERSION.txt
Jose Lorenzo Rodriguez 13 years ago
parent
commit
62cdb78616

+ 2 - 2
App/View/Pages/home.ctp

@@ -133,8 +133,8 @@ if (isset($filePresent)):
 <h3><?php echo __d('cake_dev', 'Editing this Page'); ?></h3>
 <p>
 <?php
-echo __d('cake_dev', 'To change the content of this page, create: APP/View/Pages/home.ctp.<br />
-To change its layout, create: APP/View/Layouts/default.ctp.<br />
+echo __d('cake_dev', 'To change the content of this page, edit: APP/View/Pages/home.ctp.<br />
+To change its layout, edit: APP/View/Layouts/default.ctp.<br />
 You can also add some CSS styles for your pages at: APP/webroot/css.');
 ?>
 </p>

+ 1 - 1
lib/Cake/Model/Validator/ValidationRule.php

@@ -84,7 +84,7 @@ class ValidationRule {
  *
  * @var boolean
  */
-	public $allowEmpty = false;
+	public $allowEmpty = null;
 
 /**
  * The 'on' key

+ 1 - 1
lib/Cake/Network/Request.php

@@ -659,7 +659,7 @@ class Request implements \ArrayAccess {
  *
  * #### Check for a single type:
  *
- * `$this->request->accepts('json');`
+ * `$this->request->accepts('application/json');`
  *
  * This method will order the returned content types by the preference values indicated
  * by the client.

+ 20 - 0
lib/Cake/Test/TestCase/Model/ModelValidationTest.php

@@ -2178,4 +2178,24 @@ class ModelValidationTest extends BaseModelTest {
 		$this->assertEquals($expected, $result);
 	}
 
+	public function testCustomMethodWithEmptyValue() {
+		$this->loadFixtures('Article');
+
+		$model = $this->getMock('Article', array('isLegit'));
+		$model->validate = array(
+			'title' => array(
+				'custom' => array(
+					'rule' => array('isLegit'),
+					'message' => 'is no good'
+				)
+			)
+		);
+		$model->expects($this->once())
+			->method('isLegit')
+			->will($this->returnValue(false));
+
+		$model->set(array('title' => ''));
+		$this->assertFalse($model->validates());
+	}
+
 }

+ 44 - 37
lib/Cake/Test/TestCase/Model/ModelWriteTest.php

@@ -3002,23 +3002,6 @@ class ModelWriteTest extends BaseModelTest {
 		), array('atomic' => false));
 		$this->assertSame($result, array(true, true, true));
 
-		$TestModel->validate = array('title' => 'notEmpty', 'author_id' => 'numeric');
-		$result = $TestModel->saveAll(array(
-			array(
-				'id' => '1',
-				'title' => 'Un-Baleeted First Post',
-				'body' => 'Not Baleeted!',
-				'published' => 'Y'
-			),
-			array(
-				'id' => '2',
-				'title' => '',
-				'body' => 'Trying to get away with an empty title'
-			)
-		), array('validate' => true, 'atomic' => false));
-
-		$this->assertSame(array(true, false), $result);
-
 		$result = $TestModel->saveAll(array(
 			'Article' => array('id' => 2),
 			'Comment' => array(
@@ -3034,6 +3017,25 @@ class ModelWriteTest extends BaseModelTest {
 			))
 		), array('validate' => true, 'atomic' => false));
 		$this->assertSame($result, array('Article' => true, 'Comment' => array(true, true)));
+
+		$TestModel->validate = array(
+			'title' => 'notEmpty',
+			'author_id' => 'numeric'
+		);
+		$result = $TestModel->saveAll(array(
+			array(
+				'id' => '1',
+				'title' => 'Un-Baleeted First Post',
+				'body' => 'Not Baleeted!',
+				'published' => 'Y'
+			),
+			array(
+				'id' => '2',
+				'title' => '',
+				'body' => 'Trying to get away with an empty title'
+			)
+		), array('validate' => true, 'atomic' => false));
+		$this->assertSame(array(true, false), $result);
 	}
 
 /**
@@ -3189,6 +3191,25 @@ class ModelWriteTest extends BaseModelTest {
 
 		$data = array(
 			array(
+				'Article' => array('id' => 1),
+				'Comment' => array(
+					array('comment' => 'First comment deepsaved article 1', 'published' => 'Y', 'User' => array('user' => 'savemany', 'password' => 'manysaved')),
+					array('comment' => 'Second comment deepsaved article 1', 'published' => 'Y', 'user_id' => 2)
+				)
+			),
+			array(
+				'Article' => array('id' => 2),
+				'Comment' => array(
+					array('comment' => 'First comment deepsaved article 2', 'published' => 'Y', 'User' => array('user' => 'savemore', 'password' => 'moresaved')),
+					array('comment' => 'Second comment deepsaved article 2', 'published' => 'Y', 'user_id' => 2)
+				)
+			)
+		);
+		$result = $TestModel->saveAll($data, array('deep' => true));
+		$this->assertTrue($result);
+
+		$data = array(
+			array(
 				'id' => 1, 'body' => '',
 				'Comment' => array(
 					array('comment' => '', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'manysaved')),
@@ -3220,6 +3241,7 @@ class ModelWriteTest extends BaseModelTest {
 				)
 			),
 			1 => array(
+				'body' => array('This field cannot be left blank'),
 				'Comment' => array(
 					0 => array(
 						'User' => array(
@@ -3234,25 +3256,6 @@ class ModelWriteTest extends BaseModelTest {
 		);
 		$result = $TestModel->validationErrors;
 		$this->assertSame($expected, $result);
-
-		$data = array(
-			array(
-				'Article' => array('id' => 1),
-				'Comment' => array(
-					array('comment' => 'First comment deepsaved article 1', 'published' => 'Y', 'User' => array('user' => 'savemany', 'password' => 'manysaved')),
-					array('comment' => 'Second comment deepsaved article 1', 'published' => 'Y', 'user_id' => 2)
-				)
-			),
-			array(
-				'Article' => array('id' => 2),
-				'Comment' => array(
-					array('comment' => 'First comment deepsaved article 2', 'published' => 'Y', 'User' => array('user' => 'savemore', 'password' => 'moresaved')),
-					array('comment' => 'Second comment deepsaved article 2', 'published' => 'Y', 'user_id' => 2)
-				)
-			)
-		);
-		$result = $TestModel->saveAll($data, array('deep' => true));
-		$this->assertTrue($result);
 	}
 /**
  * testSaveAllDeepValidateOnly
@@ -3661,7 +3664,8 @@ class ModelWriteTest extends BaseModelTest {
 
 		$data = array(
 			array(
-				'id' => 1, 'body' => '',
+				'id' => 1,
+				'body' => '',
 				'Comment' => array(
 					array('comment' => '', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'manysaved')),
 					array('comment' => 'Second comment deepsaved article 1', 'published' => 'Y', 'user_id' => 2)
@@ -3682,6 +3686,9 @@ class ModelWriteTest extends BaseModelTest {
 		$expected = array(
 			0 => array(
 				'body' => array('This field cannot be left blank')
+			),
+			1 => array(
+				'body' => array('This field cannot be left blank')
 			)
 		);
 		$result = $TestModel->validationErrors;

+ 1 - 1
lib/Cake/Test/TestCase/Model/Validator/CakeValidationRuleTest.php

@@ -129,7 +129,7 @@ class CakeValidationRuleTest extends CakeTestCase {
  *
  * @return void
  */
-	public function testIsEmplyAllowed() {
+	public function testIsEmptyAllowed() {
 		$def = array('rule' => 'aRule', 'allowEmpty' => true);
 		$Rule = new CakeValidationRule($def);
 		$this->assertTrue($Rule->isEmptyAllowed());

+ 5 - 1
lib/Cake/Test/TestCase/Model/models.php

@@ -276,7 +276,11 @@ class Article extends CakeTestModel {
  *
  * @var array
  */
-	public $validate = array('user_id' => 'numeric', 'title' => array('allowEmpty' => false, 'rule' => 'notEmpty'), 'body' => 'notEmpty');
+	public $validate = array(
+		'user_id' => 'numeric',
+		'title' => array('required' => false, 'rule' => 'notEmpty'),
+		'body' => 'notEmpty',
+	);
 
 /**
  * beforeSaveReturn property

+ 128 - 126
lib/Cake/Test/TestCase/Utility/TimeTest.php

@@ -67,6 +67,7 @@ class TimeTest extends TestCase {
 	protected function _restoreSystemTimezone() {
 		date_default_timezone_set($this->_systemTimezoneIdentifier);
 	}
+
 /**
  * testToQuarter method
  *
@@ -96,85 +97,103 @@ class TimeTest extends TestCase {
 	}
 
 /**
- * testTimeAgoInWords method
+ * provider for timeAgoInWords() tests
  *
- * @return void
+ * @return array
  */
-	public function testTimeAgoInWords() {
-		$result = $this->Time->timeAgoInWords('-1 week');
-		$this->assertEquals(date('l d/m, H:i', strtotime('-1 week')), $result);
-
-		$result = $this->Time->timeAgoInWords('+1 week');
-		$this->assertEquals('On ' . date('l d/m, H:i', strtotime('+1 week')), $result);
-
-		$result = $this->Time->timeAgoInWords(
-			strtotime('+4 months +2 weeks +3 days'),
-			array('end' => '8 years')
-		);
-		$this->assertEquals('4 months, 2 weeks, 3 days', $result);
-
-		$result = $this->Time->timeAgoInWords(
-			strtotime('+4 months +2 weeks +2 days'),
-			array('end' => '8 years')
-		);
-		$this->assertEquals('4 months, 2 weeks, 2 days', $result);
-
-		$result = $this->Time->timeAgoInWords(
-			strtotime('+4 months +2 weeks +1 day'),
-			array('end' => '8 years')
-		);
-		$this->assertEquals('4 months, 2 weeks, 1 day', $result);
-
-		$result = $this->Time->timeAgoInWords(
-			strtotime('+3 months +2 weeks +1 day'),
-			array('end' => '8 years')
-		);
-		$this->assertEquals('3 months, 2 weeks, 1 day', $result);
-
-		$result = $this->Time->timeAgoInWords(
-			strtotime('+3 months +2 weeks'),
-			array('end' => '8 years')
-		);
-		$this->assertEquals('3 months, 2 weeks', $result);
-
-		$result = $this->Time->timeAgoInWords(
-			strtotime('+3 months +1 week +6 days'),
-			array('end' => '8 years')
-		);
-		$this->assertEquals('3 months, 1 week, 6 days', $result);
-
-		$result = $this->Time->timeAgoInWords(
-			strtotime('+2 months +2 weeks +1 day'),
-			array('end' => '8 years')
+	public static function timeAgoProvider() {
+		return array(
+			array('-12 seconds', '12 seconds ago'),
+			array('-12 minutes', '12 minutes ago'),
+			array('-2 hours', '2 hours ago'),
+			array('-1 day', '1 day ago'),
+			array('-2 days', '2 days ago'),
+			array('-2 days -3 hours', '2 days, 3 hours ago'),
+			array('-1 week', '1 week ago'),
+			array('-2 weeks -2 days', '2 weeks, 2 days ago'),
+			array('+1 week', '1 week'),
+			array('+1 week 1 day', '1 week, 1 day'),
+			array('+2 weeks 2 day', '2 weeks, 2 days'),
+			array('2007-9-24', 'on 24/9/07'),
+			array('now', 'just now'),
 		);
-		$this->assertEquals('2 months, 2 weeks, 1 day', $result);
-
-		$result = $this->Time->timeAgoInWords(
-			strtotime('+2 months +2 weeks'),
-			array('end' => '8 years')
-		);
-		$this->assertEquals('2 months, 2 weeks', $result);
+	}
 
-		$result = $this->Time->timeAgoInWords(
-			strtotime('+2 months +1 week +6 days'),
-			array('end' => '8 years')
-		);
-		$this->assertEquals('2 months, 1 week, 6 days', $result);
+/**
+ * testTimeAgoInWords method
+ *
+ * @dataProvider timeAgoProvider
+ * @return void
+ */
+	public function testTimeAgoInWords($input, $expected) {
+		$result = $this->Time->timeAgoInWords($input);
+		$this->assertEquals($expected, $result);
+	}
 
-		$result = $this->Time->timeAgoInWords(
-			strtotime('-1 month -1 week -6 days'),
-			array('end' => '1 year', 'accuracy' => array('month' => 'month'))
+/**
+ * provider for timeAgo with an end date.
+ *
+ * @return void
+ */
+	public function timeAgoEndProvider() {
+		return array(
+			array(
+				'+4 months +2 weeks +3 days',
+				'4 months, 2 weeks, 3 days',
+				'8 years'
+			),
+			array(
+				'+4 months +2 weeks +1 day',
+				'4 months, 2 weeks, 1 day',
+				'8 years'
+			),
+			array(
+				'+3 months +2 weeks',
+				'3 months, 2 weeks',
+				'8 years'
+			),
+			array(
+				'+3 months +2 weeks +1 day',
+				'3 months, 2 weeks, 1 day',
+				'8 years'
+			),
+			array(
+				'+1 months +1 week +1 day',
+				'1 month, 1 week, 1 day',
+				'8 years'
+			),
+			array(
+				'+2 months +2 days',
+				'2 months, 2 days',
+				'on ' . date('j/n/y', strtotime('+2 months +2 days'))
+			),
+			array(
+				'+2 months +12 days',
+				'2 months, 1 week, 5 days',
+				'3 months'
+			),
 		);
-		$this->assertEquals('1 month ago', $result);
+	}
 
-		$timestamp = strtotime('-1 years -2 weeks -3 days');
+/**
+ * test the end option for timeAgoInWords
+ *
+ * @dataProvider timeAgoEndProvider
+ * @return void
+ */
+	public function testTimeAgoInWordsEnd($input, $expected, $end) {
 		$result = $this->Time->timeAgoInWords(
-			$timestamp,
-			array('accuracy' => array('year' => 'year'))
+			$input, array('end' => $end)
 		);
-		$expected = 'on ' . date('j/n/y', $timestamp);
 		$this->assertEquals($expected, $result);
+	}
 
+/**
+ * Test the accuracy option for timeAgoInWords()
+ *
+ * @return void
+ */
+	public function testTimeAgoInWordsAccuracy() {
 		$result = $this->Time->timeAgoInWords(
 			strtotime('+8 years +4 months +2 weeks +3 days'),
 			array('accuracy' => array('year' => 'year'), 'end' => '+10 years')
@@ -209,30 +228,14 @@ class TimeTest extends TestCase {
 		);
 		$expected = '1 year';
 		$this->assertEquals($expected, $result);
+	}
 
-		for ($i = 0; $i > -200; $i--) {
-			$seconds = round($i + ($i * $i));
-			$time = strtotime('+' . $seconds . ' seconds');
-			$result = $this->Time->timeAgoInWords($time);
-
-			if ($time == time()) {
-				$expected = 'just now';
-				$this->assertEquals($expected, $result);
-			} elseif (date("Y-m-d", $time) == date("Y-m-d")) {
-				$expected = 'Today, ' . date("H:i", $time);
-				$this->assertEquals($expected, $result);
-			}
-		}
-
-		$result = $this->Time->timeAgoInWords(
-			strtotime('-2 years -5 months -2 days'),
-			array('end' => '3 years')
-		);
-		$this->assertEquals('2 years, 5 months, 2 days ago', $result);
-
-		$result = $this->Time->timeAgoInWords('2007-9-25');
-		$this->assertEquals('on 25/9/07', $result);
-
+/**
+ * Test the format option of timeAgoInWords()
+ *
+ * @return void
+ */
+	public function testTimeAgoInWordsWithFormat() {
 		$result = $this->Time->timeAgoInWords('2007-9-25', 'Y-m-d');
 		$this->assertEquals('on 2007-09-25', $result);
 
@@ -240,12 +243,6 @@ class TimeTest extends TestCase {
 		$this->assertEquals('on 2007-09-25', $result);
 
 		$result = $this->Time->timeAgoInWords(
-			strtotime('-2 weeks -2 days'),
-			'Y-m-d'
-		);
-		$this->assertEquals('2 weeks, 2 days ago', $result);
-
-		$result = $this->Time->timeAgoInWords(
 			strtotime('+2 weeks +2 days'),
 			'Y-m-d'
 		);
@@ -253,60 +250,65 @@ class TimeTest extends TestCase {
 
 		$result = $this->Time->timeAgoInWords(
 			strtotime('+2 months +2 days'),
-			array('end' => '1 month')
-		);
-		$this->assertEquals(
-			'on ' . date('j/n/y', strtotime('+2 months +2 days')),
-			$result
+			array('end' => '1 month', 'format' => 'Y-m-d')
 		);
+		$this->assertEquals('on ' . date('Y-m-d', strtotime('+2 months +2 days')), $result);
+	}
 
+/**
+ * test timeAgoInWords() with negative values.
+ *
+ * @return void
+ */
+	public function testTimeAgoInWordsNegativeValues() {
 		$result = $this->Time->timeAgoInWords(
-			strtotime('+2 months +2 days'),
+			strtotime('-2 months -2 days'),
 			array('end' => '3 month')
 		);
-		$this->assertRegExp('/2 months/', $result);
+		$this->assertEquals('2 months, 2 days ago', $result);
 
 		$result = $this->Time->timeAgoInWords(
-			strtotime('+2 months +12 days'),
+			strtotime('-2 months -2 days'),
 			array('end' => '3 month')
 		);
-		$this->assertRegExp('/2 months, 1 week/', $result);
-
-		$result = $this->Time->timeAgoInWords(
-			strtotime('+3 months +5 days'),
-			array('end' => '4 month')
-		);
-		$this->assertEquals('3 months, 5 days', $result);
+		$this->assertEquals('2 months, 2 days ago', $result);
 
 		$result = $this->Time->timeAgoInWords(
 			strtotime('-2 months -2 days'),
-			array('end' => '3 month')
+			array('end' => '1 month', 'format' => 'Y-m-d')
 		);
-		$this->assertEquals('2 months, 2 days ago', $result);
+		$this->assertEquals('on ' . date('Y-m-d', strtotime('-2 months -2 days')), $result);
 
 		$result = $this->Time->timeAgoInWords(
-			strtotime('-2 months -2 days'),
-			array('end' => '3 month')
+			strtotime('-2 years -5 months -2 days'),
+			array('end' => '3 years')
 		);
-		$this->assertEquals('2 months, 2 days ago', $result);
+		$this->assertEquals('2 years, 5 months, 2 days ago', $result);
 
 		$result = $this->Time->timeAgoInWords(
-			strtotime('+2 months +2 days'),
-			array('end' => '3 month')
+			strtotime('-2 weeks -2 days'),
+			'Y-m-d'
 		);
-		$this->assertRegExp('/2 months/', $result);
+		$this->assertEquals('2 weeks, 2 days ago', $result);
+
+		$time = strtotime('-3 years -12 months');
+		$result = $this->Time->timeAgoInWords($time);
+		$expected = 'on ' . date('j/n/y', $time);
+		$this->assertEquals($expected, $result);
 
 		$result = $this->Time->timeAgoInWords(
-			strtotime('+2 months +2 days'),
-			array('end' => '1 month', 'format' => 'Y-m-d')
+			strtotime('-1 month -1 week -6 days'),
+			array('end' => '1 year', 'accuracy' => array('month' => 'month'))
 		);
-		$this->assertEquals('on ' . date('Y-m-d', strtotime('+2 months +2 days')), $result);
+		$this->assertEquals('1 month ago', $result);
 
+		$timestamp = strtotime('-1 years -2 weeks -3 days');
 		$result = $this->Time->timeAgoInWords(
-			strtotime('-2 months -2 days'),
-			array('end' => '1 month', 'format' => 'Y-m-d')
+			$timestamp,
+			array('accuracy' => array('year' => 'year'))
 		);
-		$this->assertEquals('on ' . date('Y-m-d', strtotime('-2 months -2 days')), $result);
+		$expected = 'on ' . date('j/n/y', $timestamp);
+		$this->assertEquals($expected, $result);
 
 		$result = $this->Time->timeAgoInWords(
 			strtotime('-13 months -5 days'),

+ 5 - 2
lib/Cake/TestSuite/Fixture/FixtureManager.php

@@ -162,12 +162,15 @@ class FixtureManager {
 
 		$sources = $db->listSources();
 		$table = $db->config['prefix'] . $fixture->table;
+		$exists = in_array($table, $sources);
 
-		if ($drop && in_array($table, $sources)) {
+		if ($drop && $exists) {
 			$fixture->drop($db);
 			$fixture->create($db);
-		} elseif (!in_array($table, $sources)) {
+		} elseif (!$exists) {
 			$fixture->create($db);
+		} else {
+			$fixture->created[] = $db->configKeyName;
 		}
 	}
 

+ 14 - 1
lib/Cake/TestSuite/Reporter/HtmlReporter.php

@@ -250,9 +250,22 @@ class HtmlReporter extends BaseReporter {
 		$trace = $this->_getStackTrace($message);
 		$testName = get_class($test) . '(' . $test->getName() . ')';
 
+		$actualMsg = $expectedMsg = null;
+		$failure = $message->getComparisonFailure();
+		if (is_object($failure)) {
+			$actualMsg = $message->getComparisonFailure()->getActualAsString();
+			$expectedMsg = $message->getComparisonFailure()->getExpectedAsString();
+		}
+
 		echo "<li class='fail'>\n";
 		echo "<span>Failed</span>";
-		echo "<div class='msg'><pre>" . $this->_htmlEntities($message->toString()) . "</pre></div>\n";
+		echo "<div class='msg'><pre>" . $this->_htmlEntities($message->toString());
+
+		if ((is_string($actualMsg) && is_string($expectedMsg)) || (is_array($actualMsg) && is_array($expectedMsg))) {
+			echo "<br />" . PHPUnit_Util_Diff::diff($expectedMsg, $actualMsg);
+		}
+
+		echo "</pre></div>\n";
 		echo "<div class='msg'>" . __d('cake_dev', 'Test case: %s', $testName) . "</div>\n";
 		echo "<div class='msg'>" . __d('cake_dev', 'Stack trace:') . '<br />' . $trace . "</div>\n";
 		echo "</li>\n";

+ 15 - 14
lib/Cake/Utility/Time.php

@@ -94,7 +94,7 @@ class Time {
 /**
  * Magic set method for backward compatibility.
  *
- * Used by TimeHelper to modify static variables in Cake Time
+ * Used by TimeHelper to modify static variables in this class
  */
 	public function __set($name, $value) {
 		switch ($name) {
@@ -703,10 +703,10 @@ class Time {
 		$accuracy = static::$wordAccuracy;
 
 		if (is_array($options)) {
-			if (isset($options['userOffset'])) {
-				$timezone = $options['userOffset'];
-			} elseif (isset($options['timezone'])) {
+			if (isset($options['timezone'])) {
 				$timezone = $options['timezone'];
+			} elseif (isset($options['userOffset'])) {
+				$timezone = $options['userOffset'];
 			}
 
 			if (isset($options['accuracy'])) {
@@ -721,12 +721,11 @@ class Time {
 
 			if (isset($options['format'])) {
 				$format = $options['format'];
-				unset($options['format']);
 			}
 			if (isset($options['end'])) {
 				$end = $options['end'];
-				unset($options['end']);
 			}
+			unset($options['end'], $options['format']);
 		} else {
 			$format = $options;
 		}
@@ -843,11 +842,6 @@ class Time {
 			}
 		}
 
-		// If within the last or next 7 days
-		if (static::wasWithinLast('7 days', $dateTime, $timezone) || static::isWithinNext('7 days', $dateTime, $timezone)) {
-			$relativeDate = static::niceShort($dateTime , $timezone);
-		}
-
 		// If now
 		if ($diff == 0) {
 			$relativeDate = __d('cake', 'just now', 'just now');
@@ -1001,10 +995,17 @@ class Time {
 			$regex = $filter;
 			$filter = null;
 		}
-		if ($filter === null) {
-			$filter = \DateTimeZone::ALL;
+		if (version_compare(PHP_VERSION, '5.3.0', '<')) {
+			if ($regex === null) {
+				$regex = '#^((Africa|America|Antartica|Arctic|Asia|Atlantic|Australia|Europe|Indian|Pacific)/|UTC)#';
+			}
+			$identifiers = \DateTimeZone::listIdentifiers();
+		} else {
+			if ($filter === null) {
+				$filter = \DateTimeZone::ALL;
+			}
+			$identifiers = \DateTimeZone::listIdentifiers($filter, $country);
 		}
-		$identifiers = \DateTimeZone::listIdentifiers($filter, $country);
 
 		if ($regex) {
 			foreach ($identifiers as $key => $tz) {

+ 3 - 4
lib/Cake/Utility/Validation.php

@@ -444,17 +444,16 @@ class Validation {
  * Check that value has a valid file extension.
  *
  * @param string|array $check Value to check
- * @param array $extensions file extensions to allow
+ * @param array $extensions file extensions to allow. By default extensions are 'gif', 'jpeg', 'png', 'jpg'
  * @return boolean Success
  */
 	public static function extension($check, $extensions = array('gif', 'jpeg', 'png', 'jpg')) {
 		if (is_array($check)) {
 			return static::extension(array_shift($check), $extensions);
 		}
-		$pathSegments = explode('.', $check);
-		$extension = strtolower(array_pop($pathSegments));
+		$extension = strtolower(pathinfo($check, PATHINFO_EXTENSION));
 		foreach ($extensions as $value) {
-			if ($extension == strtolower($value)) {
+			if ($extension === strtolower($value)) {
 				return true;
 			}
 		}