Browse Source

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

Conflicts:
	VERSION.txt
	lib/Cake/Console/Command/SchemaShell.php
	lib/Cake/Controller/Component/Auth/BaseAuthenticate.php
	lib/Cake/Controller/Component/AuthComponent.php
	lib/Cake/Controller/Component/CookieComponent.php
	lib/Cake/Controller/Component/EmailComponent.php
	lib/Cake/Controller/Component/SecurityComponent.php
	lib/Cake/Controller/Controller.php
	lib/Cake/Core/App.php
	lib/Cake/I18n/Multibyte.php
	lib/Cake/Model/Behavior/AclBehavior.php
	lib/Cake/Model/Behavior/TreeBehavior.php
	lib/Cake/Model/ConnectionManager.php
	lib/Cake/Model/Datasource/DataSource.php
	lib/Cake/Model/Datasource/Database/Mysql.php
	lib/Cake/Model/Datasource/Database/Sqlite.php
	lib/Cake/Model/Datasource/DboSource.php
	lib/Cake/Model/Model.php
	lib/Cake/Model/ModelValidator.php
	lib/Cake/Model/Validator/CakeValidationRule.php
	lib/Cake/Network/Http/HttpSocket.php
	lib/Cake/Routing/Route/CakeRoute.php
	lib/Cake/Routing/Router.php
	lib/Cake/Test/Case/Console/Command/SchemaShellTest.php
	lib/Cake/Test/Case/Controller/Component/Auth/BasicAuthenticateTest.php
	lib/Cake/Test/Case/Model/Behavior/TreeBehaviorNumberTest.php
	lib/Cake/Test/Case/Model/Behavior/TreeBehaviorScopedTest.php
	lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php
	lib/Cake/Test/Case/Model/Datasource/Database/SqliteTest.php
	lib/Cake/Test/Case/Network/Http/HttpSocketTest.php
	lib/Cake/Test/Case/View/Helper/PaginatorHelperTest.php
	lib/Cake/Utility/Set.php
	lib/Cake/View/Errors/fatal_error.ctp
	lib/Cake/View/Helper.php
	lib/Cake/View/Helper/FormHelper.php
	lib/Cake/View/Helper/PaginatorHelper.php
	lib/Cake/View/Helper/TimeHelper.php
	lib/Cake/basics.php
	src/Auth/DigestAuthenticate.php
	tests/TestCase/Network/Email/EmailTest.php
	tests/TestCase/Routing/Route/RouteTest.php
Mark Story 11 years ago
parent
commit
fca548fb49

+ 1 - 1
src/Auth/DigestAuthenticate.php

@@ -142,7 +142,7 @@ class DigestAuthenticate extends BasicAuthenticate {
  * Parse the digest authentication headers and split them up.
  *
  * @param string $digest The raw digest authentication headers.
- * @return array An array of digest authentication headers
+ * @return array|null An array of digest authentication headers
  */
 	public function parseAuthData($digest) {
 		if (substr($digest, 0, 7) === 'Digest ') {

+ 10 - 3
src/Filesystem/Folder.php

@@ -491,10 +491,13 @@ class Folder {
 	}
 
 /**
- * Create a directory structure recursively. Can be used to create
- * deep path structures like `/foo/bar/baz/shoe/horn`
+ * Create a directory structure recursively.
  *
- * @param string $pathname The directory structure to create
+ * Can be used to create deep path structures like `/foo/bar/baz/shoe/horn`
+ *
+ * @param string $pathname The directory structure to create. Either an absolute or relative
+ *   path. If the path is relative and exists in the process' cwd it will not be created.
+ *   Otherwise relative paths will be prefixed with the current pwd().
  * @param int $mode octal value 0755
  * @return bool Returns TRUE on success, FALSE on failure
  */
@@ -503,6 +506,10 @@ class Folder {
 			return true;
 		}
 
+		if (!self::isAbsolute($pathname)) {
+			$pathname = self::addPathElement($this->pwd(), $pathname);
+		}
+
 		if (!$mode) {
 			$mode = $this->mode;
 		}

+ 6 - 7
src/Network/Response.php

@@ -1393,18 +1393,17 @@ class Response {
 				$name = $options['name'];
 			}
 			$this->download($name);
-			$this->header('Accept-Ranges', 'bytes');
 			$this->header('Content-Transfer-Encoding', 'binary');
+		}
 
-			$httpRange = env('HTTP_RANGE');
-			if (isset($httpRange)) {
-				$this->_fileRange($file, $httpRange);
-			} else {
-				$this->header('Content-Length', $fileSize);
-			}
+		$this->header('Accept-Ranges', 'bytes');
+		$httpRange = env('HTTP_RANGE');
+		if (isset($httpRange)) {
+			$this->_fileRange($file, $httpRange);
 		} else {
 			$this->header('Content-Length', $fileSize);
 		}
+
 		$this->_clearBuffer();
 		$this->_file = $file;
 	}

+ 18 - 0
src/Routing/Route/Route.php

@@ -601,4 +601,22 @@ class Route {
 		return $this->template;
 	}
 
+/**
+ * Set state magic method to support var_export
+ *
+ * This method helps for applications that want to implement
+ * router caching.
+ *
+ * @param array $fields Key/Value of object attributes
+ * @return CakeRoute A new instance of the route
+ */
+	public static function __set_state($fields) {
+		$class = get_called_class();
+		$obj = new $class('');
+		foreach ($fields as $field => $value) {
+			$obj->$field = $value;
+		}
+		return $obj;
+	}
+
 }

+ 1 - 1
src/Template/Element/exception_stack_trace.ctp

@@ -42,7 +42,7 @@ use Cake\Error\Debugger;
 		if (!empty($stack['args'])):
 			foreach ((array)$stack['args'] as $arg):
 				$args[] = Debugger::getType($arg);
-				$params[] = Debugger::exportVar($arg, 2);
+				$params[] = Debugger::exportVar($arg, 4);
 			endforeach;
 		endif;
 

+ 3 - 4
src/View/Helper/HtmlHelper.php

@@ -171,7 +171,7 @@ class HtmlHelper extends Helper {
  *  - xhtml11: XHTML1.1.
  *
  * @param string $type Doctype to use.
- * @return string Doctype string
+ * @return string|null Doctype string
  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::docType
  */
 	public function docType($type = 'html5') {
@@ -576,7 +576,6 @@ class HtmlHelper extends Helper {
 		$options += array('safe' => true, 'block' => null);
 		$this->_scriptBlockOptions = $options;
 		ob_start();
-		return null;
 	}
 
 /**
@@ -635,7 +634,7 @@ class HtmlHelper extends Helper {
  * @param string $separator Text to separate crumbs.
  * @param string|array|bool $startText This will be the first crumb, if false it defaults to first crumb in array. Can
  *   also be an array, see above for details.
- * @return string Composed bread crumbs
+ * @return string|null Composed bread crumbs
  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#creating-breadcrumb-trails-with-htmlhelper
  */
 	public function getCrumbs($separator = '»', $startText = false) {
@@ -670,7 +669,7 @@ class HtmlHelper extends Helper {
  * @param array $options Array of html attributes to apply to the generated list elements.
  * @param string|array|bool $startText This will be the first crumb, if false it defaults to first crumb in array. Can
  *   also be an array, see `HtmlHelper::getCrumbs` for details.
- * @return string breadcrumbs html list
+ * @return string|null breadcrumbs html list
  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#creating-breadcrumb-trails-with-htmlhelper
  */
 	public function getCrumbList(array $options = array(), $startText = false) {

+ 16 - 0
tests/TestCase/Filesystem/FolderTest.php

@@ -151,6 +151,22 @@ class FolderTest extends TestCase {
 	}
 
 /**
+ * Test that relative paths to create() are added to cwd.
+ *
+ * @return void
+ */
+	public function testCreateRelative() {
+		$folder = new Folder(TMP);
+		$path = TMP . 'tests' . DS . 'relative-test';
+		$result = $folder->create('tests' . DS . 'relative-test');
+		$this->assertTrue($result, 'should create');
+
+		$this->assertTrue(is_dir($path), 'Folder was not made');
+		$folder = new Folder($path);
+		$folder->delete();
+	}
+
+/**
  * test recursive directory create failure.
  *
  * @return void

+ 157 - 19
tests/TestCase/Network/ResponseTest.php

@@ -1199,6 +1199,10 @@ class ResponseTest extends TestCase {
 
 		$response->expects($this->at(1))
 			->method('header')
+			->with('Accept-Ranges', 'bytes');
+
+		$response->expects($this->at(2))
+			->method('header')
 			->with('Content-Length', 38);
 
 		$response->expects($this->once())->method('_clearBuffer');
@@ -1245,11 +1249,11 @@ class ResponseTest extends TestCase {
 
 		$response->expects($this->at(2))
 			->method('header')
-			->with('Accept-Ranges', 'bytes');
+			->with('Content-Transfer-Encoding', 'binary');
 
 		$response->expects($this->at(3))
 			->method('header')
-			->with('Content-Transfer-Encoding', 'binary');
+			->with('Accept-Ranges', 'bytes');
 
 		$response->expects($this->at(4))
 			->method('header')
@@ -1274,7 +1278,7 @@ class ResponseTest extends TestCase {
 		$result = $response->send();
 		$output = ob_get_clean();
 		$this->assertEquals("/* this is the test asset css file */\n", $output);
-		$this->assertTrue($result !== false);
+		$this->assertNotSame(false, $result);
 	}
 
 /**
@@ -1308,11 +1312,11 @@ class ResponseTest extends TestCase {
 
 		$response->expects($this->at(2))
 			->method('header')
-			->with('Accept-Ranges', 'bytes');
+			->with('Content-Transfer-Encoding', 'binary');
 
 		$response->expects($this->at(3))
 			->method('header')
-			->with('Content-Transfer-Encoding', 'binary');
+			->with('Accept-Ranges', 'bytes');
 
 		$response->expects($this->at(4))
 			->method('header')
@@ -1331,7 +1335,7 @@ class ResponseTest extends TestCase {
 		$result = $response->send();
 		$output = ob_get_clean();
 		$this->assertEquals("some_key = some_value\nbool_key = 1\n", $output);
-		$this->assertTrue($result !== false);
+		$this->assertNotSame(false, $result);
 		if ($currentUserAgent !== null) {
 			$_SERVER['HTTP_USER_AGENT'] = $currentUserAgent;
 		}
@@ -1373,11 +1377,11 @@ class ResponseTest extends TestCase {
 
 		$response->expects($this->at(3))
 			->method('header')
-			->with('Accept-Ranges', 'bytes');
+			->with('Content-Transfer-Encoding', 'binary');
 
 		$response->expects($this->at(4))
 			->method('header')
-			->with('Content-Transfer-Encoding', 'binary');
+			->with('Accept-Ranges', 'bytes');
 
 		$response->expects($this->at(5))
 			->method('header')
@@ -1395,7 +1399,7 @@ class ResponseTest extends TestCase {
 		$result = $response->send();
 		$output = ob_get_clean();
 		$this->assertEquals("some_key = some_value\nbool_key = 1\n", $output);
-		$this->assertTrue($result !== false);
+		$this->assertNotSame(false, $result);
 		if ($currentUserAgent !== null) {
 			$_SERVER['HTTP_USER_AGENT'] = $currentUserAgent;
 		}
@@ -1437,11 +1441,11 @@ class ResponseTest extends TestCase {
 
 		$response->expects($this->at(3))
 			->method('header')
-			->with('Accept-Ranges', 'bytes');
+			->with('Content-Transfer-Encoding', 'binary');
 
 		$response->expects($this->at(4))
 			->method('header')
-			->with('Content-Transfer-Encoding', 'binary');
+			->with('Accept-Ranges', 'bytes');
 
 		$response->expects($this->at(5))
 			->method('header')
@@ -1461,7 +1465,7 @@ class ResponseTest extends TestCase {
 		$result = $response->send();
 		$output = ob_get_clean();
 		$this->assertEquals("some_key = some_value\nbool_key = 1\n", $output);
-		$this->assertTrue($result !== false);
+		$this->assertNotSame(false, $result);
 		if ($currentUserAgent !== null) {
 			$_SERVER['HTTP_USER_AGENT'] = $currentUserAgent;
 		}
@@ -1491,6 +1495,10 @@ class ResponseTest extends TestCase {
 			->with('ini')
 			->will($this->returnValue(false));
 
+		$response->expects($this->at(1))
+			->method('header')
+			->with('Accept-Ranges', 'bytes');
+
 		$response->expects($this->never())
 			->method('download');
 
@@ -1643,11 +1651,11 @@ class ResponseTest extends TestCase {
 
 		$response->expects($this->at(2))
 			->method('header')
-			->with('Accept-Ranges', 'bytes');
+			->with('Content-Transfer-Encoding', 'binary');
 
 		$response->expects($this->at(3))
 			->method('header')
-			->with('Content-Transfer-Encoding', 'binary');
+			->with('Accept-Ranges', 'bytes');
 
 		$response->expects($this->at(4))
 			->method('header')
@@ -1698,11 +1706,11 @@ class ResponseTest extends TestCase {
 
 		$response->expects($this->at(2))
 			->method('header')
-			->with('Accept-Ranges', 'bytes');
+			->with('Content-Transfer-Encoding', 'binary');
 
 		$response->expects($this->at(3))
 			->method('header')
-			->with('Content-Transfer-Encoding', 'binary');
+			->with('Accept-Ranges', 'bytes');
 
 		$response->expects($this->at(4))
 			->method('header')
@@ -1727,7 +1735,7 @@ class ResponseTest extends TestCase {
 		$output = ob_get_clean();
 		$this->assertEquals(206, $response->statusCode());
 		$this->assertEquals("is the test asset ", $output);
-		$this->assertTrue($result !== false);
+		$this->assertNotSame(false, $result);
 	}
 
 /**
@@ -1753,11 +1761,11 @@ class ResponseTest extends TestCase {
 
 		$response->expects($this->at(2))
 			->method('header')
-			->with('Accept-Ranges', 'bytes');
+			->with('Content-Transfer-Encoding', 'binary');
 
 		$response->expects($this->at(3))
 			->method('header')
-			->with('Content-Transfer-Encoding', 'binary');
+			->with('Accept-Ranges', 'bytes');
 
 		$response->expects($this->at(4))
 			->method('header')
@@ -1775,6 +1783,136 @@ class ResponseTest extends TestCase {
 	}
 
 /**
+ * testFileRangeOffsetsNoDownload method
+ *
+ * @dataProvider rangeProvider
+ * @return void
+ */
+	public function testFileRangeOffsetsNoDownload($range, $length, $offsetResponse) {
+		$_SERVER['HTTP_RANGE'] = $range;
+		$response = $this->getMock('Cake\Network\Response', array(
+			'header',
+			'type',
+			'_sendHeader',
+			'_isActive',
+			'_clearBuffer',
+			'_flushBuffer'
+		));
+
+		$response->expects($this->at(1))
+			->method('header')
+			->with('Accept-Ranges', 'bytes');
+
+		$response->expects($this->at(2))
+			->method('header')
+			->with(array(
+				'Content-Length' => $length,
+				'Content-Range' => $offsetResponse,
+			));
+
+		$response->expects($this->any())
+			->method('_isActive')
+			->will($this->returnValue(true));
+
+		$response->file(
+			TEST_APP . 'vendor' . DS . 'css' . DS . 'test_asset.css',
+			array('download' => false)
+		);
+
+		ob_start();
+		$result = $response->send();
+		ob_get_clean();
+	}
+
+/**
+ * testFileRangeNoDownload method
+ *
+ * @return void
+ */
+	public function testFileRangeNoDownload() {
+		$_SERVER['HTTP_RANGE'] = 'bytes=8-25';
+		$response = $this->getMock('Cake\Network\Response', array(
+			'header',
+			'type',
+			'_sendHeader',
+			'_setContentType',
+			'_isActive',
+			'_clearBuffer',
+			'_flushBuffer'
+		));
+
+		$response->expects($this->exactly(1))
+			->method('type')
+			->with('css')
+			->will($this->returnArgument(0));
+
+		$response->expects($this->at(1))
+			->method('header')
+			->with('Accept-Ranges', 'bytes');
+
+		$response->expects($this->at(2))
+			->method('header')
+			->with(array(
+				'Content-Length' => 18,
+				'Content-Range' => 'bytes 8-25/38',
+			));
+
+		$response->expects($this->once())->method('_clearBuffer');
+
+		$response->expects($this->any())
+			->method('_isActive')
+			->will($this->returnValue(true));
+
+		$response->file(
+			TEST_APP . 'vendor' . DS . 'css' . DS . 'test_asset.css',
+			array('download' => false)
+		);
+
+		ob_start();
+		$result = $response->send();
+		$output = ob_get_clean();
+		$this->assertEquals(206, $response->statusCode());
+		$this->assertEquals("is the test asset ", $output);
+		$this->assertNotSame(false, $result);
+	}
+
+/**
+ * testFileRangeInvalidNoDownload method
+ *
+ * @return void
+ */
+	public function testFileRangeInvalidNoDownload() {
+		$_SERVER['HTTP_RANGE'] = 'bytes=30-2';
+		$response = $this->getMock('Cake\Network\Response', array(
+			'header',
+			'type',
+			'_sendHeader',
+			'_setContentType',
+			'_isActive',
+			'_clearBuffer',
+			'_flushBuffer'
+		));
+
+		$response->expects($this->at(1))
+			->method('header')
+			->with('Accept-Ranges', 'bytes');
+
+		$response->expects($this->at(2))
+			->method('header')
+			->with(array(
+				'Content-Range' => 'bytes 0-37/38',
+			));
+
+		$response->file(
+			TEST_APP . 'vendor' . DS . 'css' . DS . 'test_asset.css',
+			array('download' => false)
+		);
+
+		$this->assertEquals(416, $response->statusCode());
+		$result = $response->send();
+	}
+
+/**
  * Test the location method.
  *
  * @return void

+ 25 - 0
tests/TestCase/Routing/Route/RouteTest.php

@@ -1085,4 +1085,29 @@ class RouteTest extends TestCase {
 		$this->assertEquals('/books/reviews', $route->staticPath());
 	}
 
+/**
+ * Test for __set_state magic method on CakeRoute
+ *
+ * @return void
+ */
+	public function testSetState() {
+		$route = Route::__set_state([
+			'keys' => [],
+			'options' => [],
+			'defaults' => [
+				'controller' => 'pages',
+				'action' => 'display',
+				'home',
+			],
+			'template' => '/',
+			'_greedy' => false,
+			'_compiledRoute' => null,
+		]);
+		$this->assertInstanceOf('Cake\Routing\Route\Route', $route);
+		$this->assertSame('/', $route->match(['controller' => 'pages', 'action' => 'display', 'home']));
+		$this->assertFalse($route->match(['controller' => 'pages', 'action' => 'display', 'about']));
+		$expected = ['controller' => 'pages', 'action' => 'display', 'pass' => ['home']];
+		$this->assertEquals($expected, $route->parse('/'));
+	}
+
 }

+ 14 - 4
tests/TestCase/View/Helper/TextHelperTest.php

@@ -333,6 +333,16 @@ class TextHelperTest extends TestCase {
  * @return void
  */
 	public function testAutoLinkUrlsEscape() {
+		$text = 'Text with a partial <a href="http://www.example.com">http://www.example.com</a> link';
+		$expected = 'Text with a partial <a href="http://www.example.com">http://www.example.com</a> link';
+		$result = $this->Text->autoLinkUrls($text, array('escape' => false));
+		$this->assertEquals($expected, $result);
+
+		$text = 'Text with a partial <a href="http://www.example.com">www.example.com</a> link';
+		$expected = 'Text with a partial <a href="http://www.example.com">www.example.com</a> link';
+		$result = $this->Text->autoLinkUrls($text, array('escape' => false));
+		$this->assertEquals($expected, $result);
+
 		$text = 'Text with a partial <a href="http://www.cakephp.org">link</a> link';
 		$expected = 'Text with a partial <a href="http://www.cakephp.org">link</a> link';
 		$result = $this->Text->autoLinkUrls($text, array('escape' => false));
@@ -350,22 +360,22 @@ class TextHelperTest extends TestCase {
 
 		$text = 'Text with a url <a href="http://www.not-working-www.com">www.not-working-www.com</a> and more';
 		$expected = 'Text with a url &lt;a href=&quot;http://www.not-working-www.com&quot;&gt;www.not-working-www.com&lt;/a&gt; and more';
-		$result = $this->Text->autoLinkUrls($text);
+		$result = $this->Text->autoLinkUrls($text, array('escape' => true));
 		$this->assertEquals($expected, $result);
 
 		$text = 'Text with a url www.not-working-www.com and more';
 		$expected = 'Text with a url <a href="http://www.not-working-www.com">www.not-working-www.com</a> and more';
-		$result = $this->Text->autoLinkUrls($text);
+		$result = $this->Text->autoLinkUrls($text, array('escape' => false));
 		$this->assertEquals($expected, $result);
 
 		$text = 'Text with a url http://www.not-working-www.com and more';
 		$expected = 'Text with a url <a href="http://www.not-working-www.com">http://www.not-working-www.com</a> and more';
-		$result = $this->Text->autoLinkUrls($text);
+		$result = $this->Text->autoLinkUrls($text, array('escape' => false));
 		$this->assertEquals($expected, $result);
 
 		$text = 'Text with a url http://www.www.not-working-www.com and more';
 		$expected = 'Text with a url <a href="http://www.www.not-working-www.com">http://www.www.not-working-www.com</a> and more';
-		$result = $this->Text->autoLinkUrls($text);
+		$result = $this->Text->autoLinkUrls($text, array('escape' => false));
 		$this->assertEquals($expected, $result);
 	}