Browse Source

Merge branch 'master' into 3.next

ADmad 7 years ago
parent
commit
9d78fc4dd0

+ 1 - 1
src/Datasource/QueryCacher.php

@@ -67,7 +67,7 @@ class QueryCacher
      * Load the cached results from the cache or run the query.
      *
      * @param object $query The query the cache read is for.
-     * @return \Cake\ORM\ResultSet|null Either the cached results or null.
+     * @return \Cake\Datasource\ResultSetInterface|null Either the cached results or null.
      */
     public function fetch($query)
     {

+ 6 - 6
src/Datasource/QueryTrait.php

@@ -28,7 +28,7 @@ trait QueryTrait
     /**
      * Instance of a table object this query is bound to
      *
-     * @var \Cake\ORM\Table|\Cake\Datasource\RepositoryInterface
+     * @var \Cake\Datasource\RepositoryInterface
      */
     protected $_repository;
 
@@ -87,8 +87,8 @@ trait QueryTrait
      * When called with a Table argument, the default table object will be set
      * and this query object will be returned for chaining.
      *
-     * @param \Cake\Datasource\RepositoryInterface|\Cake\ORM\Table|null $table The default table object to use
-     * @return \Cake\Datasource\RepositoryInterface|\Cake\ORM\Table|$this
+     * @param \Cake\Datasource\RepositoryInterface|null $table The default table object to use
+     * @return \Cake\Datasource\RepositoryInterface|$this
      */
     public function repository(RepositoryInterface $table = null)
     {
@@ -110,7 +110,7 @@ trait QueryTrait
      * Returns the default table object that will be used by this query,
      * that is, the table that will appear in the from clause.
      *
-     * @return \Cake\Datasource\RepositoryInterface|\Cake\ORM\Table
+     * @return \Cake\Datasource\RepositoryInterface
      */
     public function getRepository()
     {
@@ -213,7 +213,7 @@ trait QueryTrait
      *
      * @deprecated 3.5.0 Use isEagerLoaded() for the getter part instead.
      * @param bool|null $value Whether or not to eager load.
-     * @return $this|\Cake\ORM\Query
+     * @return $this|bool
      */
     public function eagerLoaded($value = null)
     {
@@ -501,7 +501,7 @@ trait QueryTrait
      *  $query->getOptions(); // Returns ['doABarrelRoll' => true]
      * ```
      *
-     * @see \Cake\ORM\Query::applyOptions() to read about the options that will
+     * @see \Cake\Datasource\QueryInterface::applyOptions() to read about the options that will
      * be processed by this class and not returned by this function
      * @return array
      */

+ 2 - 7
src/Datasource/RepositoryInterface.php

@@ -45,14 +45,9 @@ interface RepositoryInterface
      * Creates a new Query for this repository and applies some defaults based on the
      * type of search that was selected.
      *
-     * ### Model.beforeFind event
-     *
-     * Each find() will trigger a `Model.beforeFind` event for all attached
-     * listeners. Any listener can set a valid result set using $query
-     *
      * @param string $type the type of query to perform
      * @param array|\ArrayAccess $options An array that will be passed to Query::applyOptions()
-     * @return \Cake\ORM\Query
+     * @return \Cake\Datasource\QueryInterface
      */
     public function find($type = 'all', $options = []);
 
@@ -81,7 +76,7 @@ interface RepositoryInterface
     /**
      * Creates a new Query instance for this repository
      *
-     * @return \Cake\ORM\Query
+     * @return \Cake\Datasource\QueryInterface
      */
     public function query();
 

+ 7 - 2
src/ORM/Table.php

@@ -1288,7 +1288,8 @@ class Table implements RepositoryInterface, EventListenerInterface, EventDispatc
     }
 
     /**
-     * {@inheritDoc}
+     * Creates a new Query for this repository and applies some defaults based on the
+     * type of search that was selected.
      *
      * ### Model.beforeFind event
      *
@@ -1340,6 +1341,8 @@ class Table implements RepositoryInterface, EventListenerInterface, EventDispatc
      *
      * Would invoke the `findPublished` method.
      *
+     * @param string $type the type of query to perform
+     * @param array|\ArrayAccess $options An array that will be passed to Query::applyOptions()
      * @return \Cake\ORM\Query The query builder
      */
     public function find($type = 'all', $options = [])
@@ -1746,7 +1749,9 @@ class Table implements RepositoryInterface, EventListenerInterface, EventDispatc
     }
 
     /**
-     * {@inheritDoc}
+     * Creates a new Query instance for a table.
+     *
+     * @return \Cake\ORM\Query
      */
     public function query()
     {

+ 1 - 1
src/TestSuite/ConsoleIntegrationTestCase.php

@@ -17,7 +17,7 @@ namespace Cake\TestSuite;
  * A test case class intended to make integration tests of cake console commands
  * easier.
  *
- * @deprecated use Cake\TestSuite\ConsoleIntegrationTestTrait instead
+ * @deprecated 3.7.0 Use Cake\TestSuite\ConsoleIntegrationTestTrait instead
  */
 abstract class ConsoleIntegrationTestCase extends TestCase
 {

+ 1 - 1
src/TestSuite/IntegrationTestCase.php

@@ -30,7 +30,7 @@ if (class_exists('PHPUnit_Runner_Version', false) && !interface_exists('PHPUnit\
  * more of your code easily and avoid some of the maintenance pitfalls
  * that mock objects create.
  *
- * @deprecated use Cake\TestSuite\IntegrationTestTrait instead
+ * @deprecated 3.7.0 Use Cake\TestSuite\IntegrationTestTrait instead
  */
 abstract class IntegrationTestCase extends TestCase
 {

+ 31 - 1
src/TestSuite/IntegrationTestTrait.php

@@ -626,7 +626,8 @@ trait IntegrationTestTrait
             $props['input'] = $data;
         }
         if (!isset($props['input'])) {
-            $props['post'] = $this->_addTokens($tokenUrl, $data);
+            $data = $this->_addTokens($tokenUrl, $data);
+            $props['post'] = $this->_castToString($data);
         }
         $props['cookies'] = $this->_cookie;
 
@@ -682,6 +683,35 @@ trait IntegrationTestTrait
     }
 
     /**
+     * Recursively casts all data to string as that is how data would be POSTed in
+     * the real world
+     *
+     * @param array $data POST data
+     * @return array
+     */
+    protected function _castToString($data)
+    {
+        foreach ($data as $key => $value) {
+            if (is_scalar($value)) {
+                $data[$key] = $value === false ? '0' : (string)$value;
+
+                continue;
+            }
+
+            if (is_array($value)) {
+                $looksLikeFile = isset($value['error']) && isset($value['tmp_name']) && isset($value['size']);
+                if ($looksLikeFile) {
+                    continue;
+                }
+
+                $data[$key] = $this->_castToString($value);
+            }
+        }
+
+        return $data;
+    }
+
+    /**
      * Creates a valid request url and parameter array more like Request::_url()
      *
      * @param string|array $url The URL

+ 71 - 8
tests/TestCase/TestSuite/IntegrationTestTraitTest.php

@@ -18,13 +18,13 @@ use Cake\Core\Configure;
 use Cake\Event\EventManager;
 use Cake\Http\Response;
 use Cake\Routing\DispatcherFactory;
-use Cake\Routing\RouteBuilder;
 use Cake\Routing\Router;
 use Cake\Routing\Route\InflectedRoute;
 use Cake\TestSuite\IntegrationTestCase;
 use Cake\Test\Fixture\AssertIntegrationTestCase;
 use Cake\Utility\Security;
 use PHPUnit\Framework\AssertionFailedError;
+use Zend\Diactoros\UploadedFile;
 
 /**
  * Self test of the IntegrationTestCase
@@ -70,6 +70,69 @@ class IntegrationTestTraitTest extends IntegrationTestCase
     }
 
     /**
+     * Tests that all data that used by the request is cast to strings
+     *
+     * @return void
+     */
+    public function testDataCastToString()
+    {
+        $data = [
+            'title' => 'Blog Post',
+            'status' => 1,
+            'published' => true,
+            'not_published' => false,
+            'comments' => [
+                [
+                    'body' => 'Comment',
+                    'status' => 1,
+                ]
+            ],
+            'file' => [
+                'tmp_name' => __FILE__,
+                'size' => 42,
+                'error' => 0,
+                'type' => 'text/plain',
+                'name' => 'Uploaded file'
+            ],
+            'pictures' => [
+                'name' => [
+                    ['file' => 'a-file.png'],
+                    ['file' => 'a-moose.png']
+                ],
+                'type' => [
+                    ['file' => 'image/png'],
+                    ['file' => 'image/jpg']
+                ],
+                'tmp_name' => [
+                    ['file' => __FILE__],
+                    ['file' => __FILE__]
+                ],
+                'error' => [
+                    ['file' => 0],
+                    ['file' => 0]
+                ],
+                'size' => [
+                    ['file' => 17188],
+                    ['file' => 2010]
+                ],
+            ],
+            'upload' => new UploadedFile(__FILE__, 42, 0)
+        ];
+        $request = $this->_buildRequest('/posts/add', 'POST', $data);
+        $this->assertInternalType('string', $request['post']['status']);
+        $this->assertInternalType('string', $request['post']['published']);
+        $this->assertSame('0', $request['post']['not_published']);
+        $this->assertInternalType('string', $request['post']['comments'][0]['status']);
+        $this->assertInternalType('integer', $request['post']['file']['error']);
+        $this->assertInternalType('integer', $request['post']['file']['size']);
+        $this->assertInternalType('integer', $request['post']['pictures']['error'][0]['file']);
+        $this->assertInternalType('integer', $request['post']['pictures']['error'][1]['file']);
+        $this->assertInternalType('integer', $request['post']['pictures']['size'][0]['file']);
+        $this->assertInternalType('integer', $request['post']['pictures']['size'][1]['file']);
+        $this->assertInstanceOf(UploadedFile::class, $request['post']['upload']);
+    }
+
+    /**
      * Test building a request.
      *
      * @return void
@@ -609,7 +672,7 @@ class IntegrationTestTraitTest extends IntegrationTestCase
      */
     public function testCookieNotSetFailure()
     {
-        $this->expectException(\PHPUnit\Framework\AssertionFailedError::class);
+        $this->expectException(AssertionFailedError::class);
         $this->expectExceptionMessage('Failed asserting that \'remember_me\' cookie was not set');
         $this->post('/posts/index');
         $this->assertCookieNotSet('remember_me');
@@ -623,7 +686,7 @@ class IntegrationTestTraitTest extends IntegrationTestCase
      */
     public function testCookieNotSetFailureNoResponse()
     {
-        $this->expectException(\PHPUnit\Framework\AssertionFailedError::class);
+        $this->expectException(AssertionFailedError::class);
         $this->expectExceptionMessage('No response set, cannot assert content.');
         $this->assertCookieNotSet('remember_me');
     }
@@ -759,7 +822,7 @@ class IntegrationTestTraitTest extends IntegrationTestCase
      */
     public function testWithUnexpectedException()
     {
-        $this->expectException(\PHPUnit\Framework\AssertionFailedError::class);
+        $this->expectException(AssertionFailedError::class);
         $this->get('/tests_apps/throw_exception');
         $this->assertResponseCode(501);
     }
@@ -1036,7 +1099,7 @@ class IntegrationTestTraitTest extends IntegrationTestCase
      */
     public function testAssertResponseRegExpNoResponse()
     {
-        $this->expectException(\PHPUnit\Framework\AssertionFailedError::class);
+        $this->expectException(AssertionFailedError::class);
         $this->expectExceptionMessage('No response set');
         $this->assertResponseRegExp('/cont/');
     }
@@ -1061,7 +1124,7 @@ class IntegrationTestTraitTest extends IntegrationTestCase
      */
     public function testAssertResponseNotRegExpNoResponse()
     {
-        $this->expectException(\PHPUnit\Framework\AssertionFailedError::class);
+        $this->expectException(AssertionFailedError::class);
         $this->expectExceptionMessage('No response set');
         $this->assertResponseNotRegExp('/cont/');
     }
@@ -1124,7 +1187,7 @@ class IntegrationTestTraitTest extends IntegrationTestCase
      */
     public function testAssertFileNoResponse()
     {
-        $this->expectException(\PHPUnit\Framework\AssertionFailedError::class);
+        $this->expectException(AssertionFailedError::class);
         $this->expectExceptionMessage('No response set, cannot assert content');
         $this->assertFileResponse('foo');
     }
@@ -1136,7 +1199,7 @@ class IntegrationTestTraitTest extends IntegrationTestCase
      */
     public function testAssertFileNoFile()
     {
-        $this->expectException(\PHPUnit\Framework\AssertionFailedError::class);
+        $this->expectException(AssertionFailedError::class);
         $this->expectExceptionMessage('Failed asserting that file was sent.');
         $this->get('/posts/get');
         $this->assertFileResponse('foo');