Browse Source

Merge branch 'master' into 2.3

mark_story 13 years ago
parent
commit
e59555a66f

+ 5 - 2
lib/Cake/Console/Command/AclShell.php

@@ -70,12 +70,15 @@ class AclShell extends AppShell {
 			$this->connection = $this->params['connection'];
 		}
 
-		if (!in_array(Configure::read('Acl.classname'), array('DbAcl', 'DB_ACL'))) {
+		$class = Configure::read('Acl.classname');
+		list($plugin, $class) = pluginSplit($class, true);
+		App::uses($class, $plugin . 'Controller/Component/Acl');
+		if (!in_array($class, array('DbAcl', 'DB_ACL')) && !is_subclass_of($class, 'DbAcl')) {
 			$out = "--------------------------------------------------\n";
 			$out .= __d('cake_console', 'Error: Your current Cake configuration is set to an ACL implementation other than DB.') . "\n";
 			$out .= __d('cake_console', 'Please change your core config to reflect your decision to use DbAcl before attempting to use this script') . "\n";
 			$out .= "--------------------------------------------------\n";
-			$out .= __d('cake_console', 'Current ACL Classname: %s', Configure::read('Acl.classname')) . "\n";
+			$out .= __d('cake_console', 'Current ACL Classname: %s', $class) . "\n";
 			$out .= "--------------------------------------------------\n";
 			$this->err($out);
 			$this->_stop();

+ 13 - 13
lib/Cake/Model/Behavior/TreeBehavior.php

@@ -71,8 +71,8 @@ class TreeBehavior extends ModelBehavior {
 
 		if (in_array($settings['scope'], $Model->getAssociated('belongsTo'))) {
 			$data = $Model->getAssociated($settings['scope']);
-			$parent = $Model->{$settings['scope']};
-			$settings['scope'] = $Model->alias . '.' . $data['foreignKey'] . ' = ' . $parent->alias . '.' . $parent->primaryKey;
+			$Parent = $Model->{$settings['scope']};
+			$settings['scope'] = $Model->escapeField($data['foreignKey']) . ' = ' . $Parent->escapeField();
 			$settings['recursive'] = 0;
 		}
 		$this->settings[$Model->alias] = $settings;
@@ -126,8 +126,8 @@ class TreeBehavior extends ModelBehavior {
 	public function beforeDelete(Model $Model, $cascade = true) {
 		extract($this->settings[$Model->alias]);
 		$data = $Model->find('first', array(
-			'conditions' => array($Model->alias . '.' . $Model->primaryKey => $Model->id),
-			'fields' => array($Model->alias . '.' . $left, $Model->alias . '.' . $right),
+			'conditions' => array($Model->escapeField($Model->primaryKey) => $Model->id),
+			'fields' => array($Model->escapeField($left), $Model->escapeField($right)),
 			'recursive' => -1));
 		if ($data) {
 			$this->_deletedRow = current($data);
@@ -157,7 +157,7 @@ class TreeBehavior extends ModelBehavior {
 			if (is_string($scope)) {
 				$scope = array($scope);
 			}
-			$scope[]["{$Model->alias}.{$left} BETWEEN ? AND ?"] = array($data[$left] + 1, $data[$right] - 1);
+			$scope[][$Model->escapeField($left) . " BETWEEN ? AND ?"] = array($data[$left] + 1, $data[$right] - 1);
 			$Model->deleteAll($scope);
 		}
 		$this->_sync($Model, $diff, '-', '> ' . $data[$right]);
@@ -309,7 +309,7 @@ class TreeBehavior extends ModelBehavior {
 			$recursive = $overrideRecursive;
 		}
 		if (!$order) {
-			$order = $Model->alias . '.' . $left . ' asc';
+			$order = $Model->escapeField($left) . " asc";
 		}
 		if ($direct) {
 			$conditions = array($scope, $Model->escapeField($parent) => $id);
@@ -374,7 +374,7 @@ class TreeBehavior extends ModelBehavior {
 		} else {
 			array_unshift($valuePath, '%s' . $valuePath[0], '{n}.tree_prefix');
 		}
-		$order = $Model->alias . '.' . $left . ' asc';
+		$order = $Model->escapeField($left) . " asc";
 		$results = $Model->find('all', compact('conditions', 'fields', 'order', 'recursive'));
 		$stack = array();
 
@@ -934,13 +934,13 @@ class TreeBehavior extends ModelBehavior {
 		$db = ConnectionManager::getDataSource($Model->useDbConfig);
 		if ($created) {
 			if (is_string($scope)) {
-				$scope .= " AND {$Model->alias}.{$Model->primaryKey} <> ";
+				$scope .= " AND " . $Model->escapeField() . " <> ";
 				$scope .= $db->value($Model->id, $Model->getColumnType($Model->primaryKey));
 			} else {
 				$scope['NOT'][$Model->alias . '.' . $Model->primaryKey] = $Model->id;
 			}
 		}
-		$name = $Model->alias . '.' . $right;
+		$name = $Model->escapeField($right);
 		list($edge) = array_values($Model->find('first', array(
 			'conditions' => $scope,
 			'fields' => $db->calculate($Model, 'max', array($name, $right)),
@@ -960,7 +960,7 @@ class TreeBehavior extends ModelBehavior {
  */
 	protected function _getMin(Model $Model, $scope, $left, $recursive = -1) {
 		$db = ConnectionManager::getDataSource($Model->useDbConfig);
-		$name = $Model->alias . '.' . $left;
+		$name = $Model->escapeField($left);
 		list($edge) = array_values($Model->find('first', array(
 			'conditions' => $scope,
 			'fields' => $db->calculate($Model, 'min', array($name, $left)),
@@ -992,15 +992,15 @@ class TreeBehavior extends ModelBehavior {
 			$field = $right;
 		}
 		if (is_string($conditions)) {
-			$conditions = array("{$Model->alias}.{$field} {$conditions}");
+			$conditions = array($Model->escapeField($field) . " {$conditions}");
 		}
 		if (($scope != '1 = 1' && $scope !== true) && $scope) {
 			$conditions[] = $scope;
 		}
 		if ($created) {
-			$conditions['NOT'][$Model->alias . '.' . $Model->primaryKey] = $Model->id;
+			$conditions['NOT'][$Model->escapeField()] = $Model->id;
 		}
-		$Model->updateAll(array($Model->alias . '.' . $field => $Model->escapeField($field) . ' ' . $dir . ' ' . $shift), $conditions);
+		$Model->updateAll(array($Model->escapeField($field) => $Model->escapeField($field) . ' ' . $dir . ' ' . $shift), $conditions);
 		$Model->recursive = $ModelRecursive;
 	}
 

+ 2 - 0
lib/Cake/Model/Datasource/Session/DatabaseSession.php

@@ -137,6 +137,8 @@ class DatabaseSession implements CakeSessionHandlerInterface {
 	public function gc($expires = null) {
 		if (!$expires) {
 			$expires = time();
+		} else {
+			$expires = time() - $expires;
 		}
 		return $this->_model->deleteAll(array($this->_model->alias . ".expires <" => $expires), false, false);
 	}

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

@@ -2863,7 +2863,7 @@ class Model extends Object implements CakeEventListener {
 			$query['order'] = $field . ' ASC';
 			$neighbors = $this->find('all', $query);
 			if (!array_key_exists('prev', $return)) {
-				$return['prev'] = $neighbors[0];
+				$return['prev'] = isset($neighbors[0]) ? $neighbors[0] : null;
 			}
 			if (count($neighbors) === 2) {
 				$return['next'] = $neighbors[1];

+ 2 - 2
lib/Cake/Routing/Dispatcher.php

@@ -143,9 +143,9 @@ class Dispatcher implements CakeEventListener {
 		$request = $beforeEvent->data['request'];
 		if ($beforeEvent->result instanceof CakeResponse) {
 			if (isset($request->params['return'])) {
-				return $response->body();
+				return $beforeEvent->result->body();
 			}
-			$response->send();
+			$beforeEvent->result->send();
 			return;
 		}
 

+ 24 - 0
lib/Cake/Test/Case/Model/ModelReadTest.php

@@ -3737,6 +3737,30 @@ class ModelReadTest extends BaseModelTest {
 	}
 
 /**
+ * Test find(neighbors) with missing fields so no neighbors are found.
+ *
+ * @return
+ */
+	public function testFindNeighborsNoPrev() {
+		$this->loadFixtures('User', 'Article', 'Comment', 'Tag', 'ArticlesTag', 'Attachment');
+		$Article = new Article();
+
+		$result = $Article->find('neighbors', array(
+			'field' => 'Article.title',
+			'value' => 'Second Article',
+			'fields' => array('id'),
+			'conditions' => array(
+				'Article.title LIKE' => '%Article%'
+			),
+			'recursive' => 0,
+		));
+		$expected = array(
+			'prev' => null,
+			'next' => null
+		);
+		$this->assertEquals($expected, $result);
+	}
+/**
  * testFindCombinedRelations method
  *
  * @return void

+ 58 - 0
lib/Cake/Test/Case/View/Helper/RssHelperTest.php

@@ -717,4 +717,62 @@ class RssHelperTest extends CakeTestCase {
 		$this->assertTags($result, $expected);
 	}
 
+	public function testElementNamespaceWithoutPrefix() {
+		$item = array(
+				'creator' => 'Alex',
+			);
+		$attributes = array(
+				'namespace' => 'http://link.com'
+		);
+		$result = $this->Rss->item($attributes, $item);
+		$expected = array(
+			'item' => array(
+					'xmlns' => 'http://link.com'
+			),
+			'creator' => array(
+					'xmlns' => 'http://link.com'
+			),
+			'Alex',
+			'/creator',
+			'/item'
+		);
+		$this->assertTags($result, $expected, true);
+	}
+
+	public function testElementNamespaceWithPrefix() {
+		$item = array(
+				'title'   => 'Title',
+				'dc:creator' => 'Alex',
+				'xy:description' => 'descriptive words'
+			);
+		$attributes = array(
+				'namespace' => array(
+						'prefix' => 'dc',
+						'url' => 'http://link.com'
+				)
+		);
+		$result = $this->Rss->item($attributes, $item);
+		$expected = array(
+			'item' => array(
+					'xmlns:dc' => 'http://link.com'
+			),
+			'title' => array(
+					'xmlns:dc' => 'http://link.com'
+			),
+			'Title',
+			'/title',
+			'dc:creator' => array(
+					'xmlns:dc' => 'http://link.com'
+			),
+			'Alex',
+			'/dc:creator',
+			'description' => array(
+					'xmlns:dc' => 'http://link.com'
+			),
+			'descriptive words',
+			'/description',
+			'/item'
+		);
+		$this->assertTags($result, $expected, true);
+	}
 }

+ 10 - 0
lib/Cake/Test/Case/View/Helper/TextHelperTest.php

@@ -181,6 +181,16 @@ class TextHelperTest extends CakeTestCase {
 		$result = $this->Text->autoLinkUrls($text);
 		$this->assertEquals($expected, $result);
 
+		$text = 'This is a test that includes http://de.wikipedia.org/wiki/Kanton_(Schweiz)#fragment';
+		$expected = 'This is a test that includes <a href="http://de.wikipedia.org/wiki/Kanton_(Schweiz)#fragment">http://de.wikipedia.org/wiki/Kanton_(Schweiz)#fragment</a>';
+		$result = $this->Text->autoLinkUrls($text);
+		$this->assertEquals($expected, $result);
+
+		$text = 'This is a test that includes www.wikipedia.org/wiki/Kanton_(Schweiz)#fragment';
+		$expected = 'This is a test that includes <a href="http://www.wikipedia.org/wiki/Kanton_(Schweiz)#fragment">www.wikipedia.org/wiki/Kanton_(Schweiz)#fragment</a>';
+		$result = $this->Text->autoLinkUrls($text);
+		$this->assertEquals($expected, $result);
+
 		$text = 'Text with a partial www.cakephp.org URL';
 		$expected = 'Text with a partial <a href="http://www.cakephp.org"\s*>www.cakephp.org</a> URL';
 		$result = $this->Text->autoLinkUrls($text);

+ 1 - 1
lib/Cake/TestSuite/ControllerTestCase.php

@@ -246,7 +246,7 @@ abstract class ControllerTestCase extends CakeTestCase {
 		}
 		$Dispatch->loadRoutes = $this->loadRoutes;
 		$Dispatch->parseParams(new CakeEvent('ControllerTestCase', $Dispatch, array('request' => $request)));
-		if (!isset($request->params['controller'])) {
+		if (!isset($request->params['controller']) && Router::currentRoute()) {
 			$this->headers = Router::currentRoute()->response->header();
 			return;
 		}

+ 11 - 1
lib/Cake/View/Helper/CacheHelper.php

@@ -150,7 +150,17 @@ class CacheHelper extends AppHelper {
 
 		if ($cacheTime != '' && $cacheTime > 0) {
 			$cached = $this->_parseOutput($out);
-			$this->_writeFile($cached, $cacheTime, $useCallbacks);
+			try {
+				$this->_writeFile($cached, $cacheTime, $useCallbacks);
+			} catch (Exception $e) {
+				$message = __d(
+					'cake_dev',
+					'Unable to write view cache file: "%s" for "%s"',
+					$e->getMessage(),
+					$this->request->here
+				);
+				$this->log($message, 'error');
+			}
 			$out = $this->_stripTags($out);
 		}
 		return $out;

+ 12 - 3
lib/Cake/View/Helper/RssHelper.php

@@ -256,6 +256,8 @@ class RssHelper extends AppHelper {
 					$attrib = $val;
 					$val = null;
 				break;
+				default:
+					$attrib = $att;
 			}
 			if (!is_null($val) && $escape) {
 				$val = h($val);
@@ -312,7 +314,12 @@ class RssHelper extends AppHelper {
 
 		$xml = '<' . $name;
 		if (!empty($namespace)) {
-			$xml .= ' xmlns:"' . $namespace . '"';
+			$xml .= ' xmlns';
+			if (is_array($namespace)) {
+				$xml .= ':' . $namespace['prefix'];
+				$namespace = $namespace['url'];
+			}
+			$xml .= '="' . $namespace . '"';
 		}
 		$bareName = $name;
 		if (strpos($name, ':') !== false) {
@@ -329,8 +336,10 @@ class RssHelper extends AppHelper {
 		$xml .= '>' . $content . '</' . $name . '>';
 		$elem = Xml::build($xml, array('return' => 'domdocument'));
 		$nodes = $elem->getElementsByTagName($bareName);
-		foreach ($attrib as $key => $value) {
-			$nodes->item(0)->setAttribute($key, $value);
+		if ($attrib) {
+			foreach ($attrib as $key => $value) {
+				$nodes->item(0)->setAttribute($key, $value);
+			}
 		}
 		foreach ($children as $k => $child) {
 			$child = $elem->createElement($name, $child);

+ 2 - 1
lib/Cake/View/Helper/TextHelper.php

@@ -101,8 +101,9 @@ class TextHelper extends AppHelper {
 		$this->_placeholders = array();
 		$options += array('escape' => true);
 
+		$pattern = '#(?<!href="|src="|">)((?:https?|ftp|nntp)://[^\s<>()]+\.[a-z]+(?:\/[^\s]+)?)#i';
 		$text = preg_replace_callback(
-			'#(?<!href="|src="|">)((?:https?|ftp|nntp)://[^\s<>()]+)#i',
+			$pattern,
 			array(&$this, '_insertPlaceHolder'),
 			$text
 		);