Browse Source

Merge remote-tracking branch 'origin/2.0' into 2.0-api-doc

Conflicts:
	lib/Cake/Model/Model.php
	lib/Cake/View/Helper/CacheHelper.php
Juan Basso 14 years ago
parent
commit
a1a049c700

+ 22 - 1
lib/Cake/Cache/Engine/MemcacheEngine.php

@@ -191,7 +191,28 @@ class MemcacheEngine extends CacheEngine {
  * @return boolean True if the cache was successfully cleared, false otherwise
  */
 	public function clear($check) {
-		return $this->_Memcache->flush();
+		if ($check) {
+			return true;
+		}
+		foreach ($this->_Memcache->getExtendedStats('slabs') as $slabs) {
+			foreach (array_keys($slabs) as $slabId) {
+				if (!is_numeric($slabId)) {
+					continue;
+				}
+
+				foreach ($this->_Memcache->getExtendedStats('cachedump', $slabId) as $stats) {
+					if (!is_array($stats)) {
+						continue;
+					}
+					foreach (array_keys($stats) as $key) {
+						if (strpos($key, $this->settings['prefix']) === 0) {
+							$this->_Memcache->delete($key);
+						}
+					}
+				}
+			}
+		}
+		return true;
 	}
 
 /**

+ 1 - 1
lib/Cake/Controller/Component/EmailComponent.php

@@ -333,7 +333,7 @@ class EmailComponent extends Component {
 			$lib->attachments($this->_formatAttachFiles());
 		}
 
-		$lib->transport($this->delivery);
+		$lib->transport(ucfirst($this->delivery));
 		if ($this->delivery === 'mail') {
 			$lib->config(array('eol' => $this->lineFeed, 'additionalParameters' => $this->additionalParams));
 		} elseif ($this->delivery === 'smtp') {

+ 61 - 36
lib/Cake/Model/Model.php

@@ -1759,45 +1759,59 @@ class Model extends Object {
 		$keys['old'] = isset($keys['old']) ? $keys['old'] : array();
 
 		foreach ($this->belongsTo as $parent => $assoc) {
-			$foreignKey = $assoc['foreignKey'];
-			$fkQuoted = $this->escapeField($assoc['foreignKey']);
-
 			if (!empty($assoc['counterCache'])) {
-				if ($assoc['counterCache'] === true) {
-					$assoc['counterCache'] = Inflector::underscore($this->alias) . '_count';
-				}
-				if (!$this->{$parent}->hasField($assoc['counterCache'])) {
-					continue;
+				if (!is_array($assoc['counterCache'])) {
+					if (isset($assoc['counterScope'])) {
+						$assoc['counterCache'] = array($assoc['counterCache'] => $assoc['counterScope']);
+					} else {
+						$assoc['counterCache'] = array($assoc['counterCache'] => array());
+					}
 				}
 
-				if (!array_key_exists($foreignKey, $keys)) {
-					$keys[$foreignKey] = $this->field($foreignKey);
-				}
-				$recursive = (isset($assoc['counterScope']) ? 1 : -1);
-				$conditions = ($recursive == 1) ? (array)$assoc['counterScope'] : array();
-
-				if (isset($keys['old'][$foreignKey])) {
-					if ($keys['old'][$foreignKey] != $keys[$foreignKey]) {
-						$conditions[$fkQuoted] = $keys['old'][$foreignKey];
-						$count = intval($this->find('count', compact('conditions', 'recursive')));
-
-						$this->{$parent}->updateAll(
-							array($assoc['counterCache'] => $count),
-							array($this->{$parent}->escapeField() => $keys['old'][$foreignKey])
-						);
+				$foreignKey = $assoc['foreignKey'];
+				$fkQuoted = $this->escapeField($assoc['foreignKey']);
+
+				foreach ($assoc['counterCache'] as $field => $conditions) {
+					if (!is_string($field)) {
+						$field = Inflector::underscore($this->alias) . '_count';
+					}
+					if (!$this->{$parent}->hasField($field)) {
+						continue;
+					}
+					if ($conditions === true) {
+						$conditions = array();
+					} else {
+						$conditions = (array)$conditions;
 					}
-				}
-				$conditions[$fkQuoted] = $keys[$foreignKey];
 
-				if ($recursive == 1) {
-					$conditions = array_merge($conditions, (array)$assoc['counterScope']);
-				}
-				$count = intval($this->find('count', compact('conditions', 'recursive')));
+					if (!array_key_exists($foreignKey, $keys)) {
+						$keys[$foreignKey] = $this->field($foreignKey);
+					}
+					$recursive = (empty($conditions) ? -1 : 0);
 
-				$this->{$parent}->updateAll(
-					array($assoc['counterCache'] => $count),
-					array($this->{$parent}->escapeField() => $keys[$foreignKey])
-				);
+					if (isset($keys['old'][$foreignKey])) {
+						if ($keys['old'][$foreignKey] != $keys[$foreignKey]) {
+							$conditions[$fkQuoted] = $keys['old'][$foreignKey];
+							$count = intval($this->find('count', compact('conditions', 'recursive')));
+
+							$this->{$parent}->updateAll(
+								array($field => $count),
+								array($this->{$parent}->escapeField() => $keys['old'][$foreignKey])
+							);
+						}
+					}
+					$conditions[$fkQuoted] = $keys[$foreignKey];
+
+					if ($recursive === 0) {
+						$conditions = array_merge($conditions, (array)$conditions);
+					}
+					$count = intval($this->find('count', compact('conditions', 'recursive')));
+
+					$this->{$parent}->updateAll(
+						array($field => $count),
+						array($this->{$parent}->escapeField() => $keys[$foreignKey])
+					);
+				}
 			}
 		}
 	}
@@ -2180,15 +2194,25 @@ class Model extends Object {
 			$this->_deleteLinks($id);
 			$this->id = $id;
 
+			$updateCounterCache = false;
 			if (!empty($this->belongsTo)) {
+				foreach ($this->belongsTo as $parent => $assoc) {
+					if (!empty($assoc['counterCache'])) {
+						$updateCounterCache = true;
+						break;
+					}
+				}
+
 				$keys = $this->find('first', array(
 					'fields' => $this->_collectForeignKeys(),
-					'conditions' => array($this->alias . '.' . $this->primaryKey => $id)
+					'conditions' => array($this->alias . '.' . $this->primaryKey => $id),
+					'recursive' => -1,
+					'callbacks' => false
 				));
 			}
 
 			if ($db->delete($this, array($this->alias . '.' . $this->primaryKey => $id))) {
-				if (!empty($this->belongsTo)) {
+				if ($updateCounterCache) {
 					$this->updateCounterCache($keys[$this->alias]);
 				}
 				$this->Behaviors->trigger('afterDelete', array(&$this));
@@ -2255,7 +2279,8 @@ class Model extends Object {
 			$records = $this->{$joinModel}->find('all', array(
 				'conditions' => array_merge(array($this->{$joinModel}->escapeField($data['foreignKey']) => $id)),
 				'fields' => $this->{$joinModel}->primaryKey,
-				'recursive' => -1
+				'recursive' => -1,
+				'callbacks' => false
 			));
 			if (!empty($records)) {
 				foreach ($records as $record) {

+ 14 - 1
lib/Cake/Test/Case/Cache/Engine/MemcacheTest.php

@@ -334,11 +334,24 @@ class MemcacheEngineTest extends CakeTestCase {
  * @return void
  */
 	public function testClear() {
-		Cache::write('some_value', 'value', 'memcache');
+		Cache::config('memcache2', array(
+			'engine' => 'Memcache',
+			'prefix' => 'cake2_',
+			'duration' => 3600
+		));
 
+		Cache::write('some_value', 'cache1', 'memcache');
+		$result = Cache::clear(true, 'memcache');
+		$this->assertTrue($result);
+		$this->assertEquals('cache1', Cache::read('some_value', 'memcache'));
+
+		Cache::write('some_value', 'cache2', 'memcache2');
 		$result = Cache::clear(false, 'memcache');
 		$this->assertTrue($result);
 		$this->assertFalse(Cache::read('some_value', 'memcache'));
+		$this->assertEquals('cache2', Cache::read('some_value', 'memcache2'));
+
+		Cache::clear(false, 'memcache2');
 	}
 /**
  * test that a 0 duration can succesfully write.

+ 1 - 1
lib/Cake/Test/Case/Controller/Component/SecurityComponentTest.php

@@ -458,7 +458,7 @@ class SecurityComponentTest extends CakeTestCase {
  *
  * @return void
  */
-	function testValidatePostNoSession() {
+	public function testValidatePostNoSession() {
 		$this->Controller->Security->startup($this->Controller);
 		$this->Controller->Session->delete('_Token');
 

+ 64 - 0
lib/Cake/Test/Case/Model/ModelWriteTest.php

@@ -458,6 +458,70 @@ class ModelWriteTest extends BaseModelTest {
 	}
 
 /**
+ * Tests having multiple counter caches for an associated model
+ *
+ * @access public
+ * @return void
+ */
+	public function testCounterCacheMultipleCaches() {
+		$this->loadFixtures('CounterCacheUser', 'CounterCachePost');
+		$User = new CounterCacheUser();
+		$Post = new CounterCachePost();
+		$Post->unbindModel(array('belongsTo' => array('User')), false);
+		$Post->bindModel(array(
+			'belongsTo' => array(
+				'User' => array(
+					'className' => 'CounterCacheUser',
+					'foreignKey' => 'user_id',
+					'counterCache' => array(
+						true,
+						'posts_published' => array('Post.published' => true)
+					)
+				)
+			)
+		), false);
+
+		// Count Increase
+		$user = $User->find('first', array(
+			'conditions' => array('id' => 66),
+			'recursive' => -1
+		));
+		$data = array('Post' => array(
+			'id' => 22,
+			'title' => 'New Post',
+			'user_id' => 66,
+			'published' => true
+		));
+		$Post->save($data);
+		$result = $User->find('first', array(
+			'conditions' => array('id' => 66),
+			'recursive' => -1
+		));
+		$this->assertEquals(3, $result[$User->alias]['post_count']);
+		$this->assertEquals(2, $result[$User->alias]['posts_published']);
+
+		// Count decrease
+		$Post->delete(1);
+		$result = $User->find('first', array(
+			'conditions' => array('id' => 66),
+			'recursive' => -1
+		));
+		$this->assertEquals(2, $result[$User->alias]['post_count']);
+		$this->assertEquals(2, $result[$User->alias]['posts_published']);
+
+		// Count update
+		$data = $Post->find('first', array(
+			'conditions' => array('id' => 1),
+			'recursive' => -1
+		));
+		$data[$Post->alias]['user_id'] = 301;
+		$Post->save($data);
+		$result = $User->find('all',array('order' => 'User.id'));
+		$this->assertEquals(2, $result[0]['User']['post_count']);
+		$this->assertEquals(1, $result[1]['User']['posts_published']);
+	}
+
+/**
  * test that beforeValidate returning false can abort saves.
  *
  * @return void

+ 7 - 2
lib/Cake/Test/Case/View/Helper/CacheHelperTest.php

@@ -317,8 +317,13 @@ class CacheHelperTest extends CakeTestCase {
 
 		@unlink($filename);
 	}
-	
-	function testCacheCallbacks() {
+
+/**
+ * Test that callback code is generated correctly.
+ *
+ * @return void
+ */
+	public function testCacheCallbacks() {
 		$this->Controller->cache_parsing();
 		$this->Controller->params = array(
 			'controller' => 'cache_test',

+ 26 - 6
lib/Cake/Test/Case/View/Helper/FormHelperTest.php

@@ -799,7 +799,7 @@ class FormHelperTest extends CakeTestCase {
 	}
 
 /**
- * Tests correct generation of text fields for double and float fields
+ * Tests correct generation of number fields for double and float fields
  *
  * @return void
  */
@@ -815,20 +815,39 @@ class FormHelperTest extends CakeTestCase {
 		$this->Form->create('Contact');
 		$result = $this->Form->input('foo');
 		$expected = array(
-			'div' => array('class' => 'input text'),
+			'div' => array('class' => 'input number'),
 			'label' => array('for' => 'ContactFoo'),
 			'Foo',
 			'/label',
 			array('input' => array(
-				'type' => 'text', 'name' => 'data[Contact][foo]',
-				'id' => 'ContactFoo'
+				'type' => 'number',
+				'name' => 'data[Contact][foo]',
+				'id' => 'ContactFoo',
+				'step' => 'any'
 			)),
 			'/div'
 		);
+		$this->assertTags($result, $expected);
+
+		$result = $this->Form->input('foo', array('step' => 0.5));
+		$expected = array(
+			'div' => array('class' => 'input number'),
+			'label' => array('for' => 'ContactFoo'),
+			'Foo',
+			'/label',
+			array('input' => array(
+				'type' => 'number',
+				'name' => 'data[Contact][foo]',
+				'id' => 'ContactFoo',
+				'step' => '0.5'
+			)),
+			'/div'
+		);
+		$this->assertTags($result, $expected);
 	}
 	
 /**
- * Tests correct generation of text fields for double and float fields
+ * Tests correct generation of number fields for integer fields
  *
  * @access public
  * @return void
@@ -845,7 +864,7 @@ class FormHelperTest extends CakeTestCase {
 		$this->Form->create('Contact');
 		$result = $this->Form->input('foo');
 		$expected = array(
-			'div' => array('class' => 'input text'),
+			'div' => array('class' => 'input number'),
 			'label' => array('for' => 'ContactFoo'),
 			'Foo',
 			'/label',
@@ -855,6 +874,7 @@ class FormHelperTest extends CakeTestCase {
 			)),
 			'/div'
 		);
+		$this->assertTags($result, $expected);
 	}
 
 /**

+ 5 - 3
lib/Cake/Test/Fixture/CounterCachePostFixture.php

@@ -30,11 +30,13 @@ class CounterCachePostFixture extends CakeTestFixture {
 		'id' => array('type' => 'integer', 'key' => 'primary'),
 		'title' => array('type' => 'string', 'length' => 255, 'null' => false),
 		'user_id' => array('type' => 'integer', 'null' => true),
+		'user_id' => array('type' => 'integer', 'null' => true),
+		'published' => array('type' => 'boolean', 'null' => false)
 	);
 
     public $records = array(
-		array('id' => 1, 'title' => 'Rock and Roll',  'user_id' => 66),
-		array('id' => 2, 'title' => 'Music',   'user_id' => 66),
-		array('id' => 3, 'title' => 'Food',   'user_id' => 301),
+		array('id' => 1, 'title' => 'Rock and Roll',  'user_id' => 66, 'published' => false),
+		array('id' => 2, 'title' => 'Music',   'user_id' => 66, 'published' => true),
+		array('id' => 3, 'title' => 'Food',   'user_id' => 301, 'published' => true),
     );
 }

+ 4 - 3
lib/Cake/Test/Fixture/CounterCacheUserFixture.php

@@ -29,11 +29,12 @@ class CounterCacheUserFixture extends CakeTestFixture {
 	public $fields = array(
 		'id' => array('type' => 'integer', 'key' => 'primary'),
 		'name' => array('type' => 'string', 'length' => 255, 'null' => false),
-		'post_count' => array('type' => 'integer', 'null' => true)
+		'post_count' => array('type' => 'integer', 'null' => true),
+		'posts_published' => array('type' => 'integer', 'null' => true)
 	);
 
 	public $records = array(
-		array('id' => 66, 'name' => 'Alexander','post_count' => 2),
-		array('id' => 301, 'name' => 'Steven','post_count' => 1),
+		array('id' => 66, 'name' => 'Alexander', 'post_count' => 2, 'posts_published' => 1),
+		array('id' => 301, 'name' => 'Steven', 'post_count' => 1, 'posts_published' => 1),
 	);
 }

+ 2 - 2
lib/Cake/Test/test_app/View/Layouts/xml/default.ctp

@@ -1,2 +1,2 @@
-<?php echo $xml->header(); ?>
-<?php echo $content_for_layout; ?>
+<?php echo '<?xml version="1.0" encoding="' . Configure::read('App.encoding') . '"?>'; ?>
+<?php echo $content_for_layout; ?>

+ 7 - 0
lib/Cake/View/Helper/FormHelper.php

@@ -933,6 +933,13 @@ class FormHelper extends AppHelper {
 				if ($fieldKey == $primaryKey) {
 					$options['type'] = 'hidden';
 				}
+				if (
+					$options['type'] === 'number' && 
+					$type === 'float' &&
+					!isset($options['step'])
+				) {
+					$options['step'] = 'any';
+				}
 			}
 			if (preg_match('/_id$/', $fieldKey) && $options['type'] !== 'hidden') {
 				$options['type'] = 'select';

+ 2 - 2
lib/Cake/View/Layouts/xml/default.ctp

@@ -1,2 +1,2 @@
-<?php echo $this->Xml->header(); ?>
-<?php echo $content_for_layout; ?>
+<?php echo '<?xml version="1.0" encoding="' . Configure::read('App.encoding') . '"?>'; ?>
+<?php echo $content_for_layout; ?>