Browse Source

Merge remote-tracking branch 'origin/3.next' into 4.x

Mark Story 6 years ago
parent
commit
02cd928cb2

+ 1 - 1
src/Form/Form.php

@@ -181,7 +181,7 @@ class Form implements EventListenerInterface, EventDispatcherInterface, Validato
     public function validate(array $data): bool
     {
         $validator = $this->getValidator();
-        $this->_errors = $validator->errors($data);
+        $this->_errors = $validator->validate($data);
 
         return count($this->_errors) === 0;
     }

+ 3 - 0
src/Http/Client.php

@@ -120,6 +120,7 @@ class Client implements ClientInterface
         'ssl_verify_depth' => 5,
         'ssl_verify_host' => true,
         'redirect' => false,
+        'protocolVersion' => '1.1',
     ];
 
     /**
@@ -162,6 +163,7 @@ class Client implements ClientInterface
      * - adapter - The adapter class name or instance. Defaults to
      *   \Cake\Http\Client\Adapter\Curl if `curl` extension is loaded else
      *   \Cake\Http\Client\Adapter\Stream.
+     * - protocolVersion - The HTTP protocol version to use. Defaults to 1.1
      *
      * @param array $config Config options for scoped clients.
      * @throws \InvalidArgumentException
@@ -535,6 +537,7 @@ class Client implements ClientInterface
         }
 
         $request = new Request($url, $method, $headers, $data);
+        $request = $request->withProtocolVersion($this->getConfig('protocolVersion'));
         $cookies = $options['cookies'] ?? [];
         /** @var \Cake\Http\Client\Request $request */
         $request = $this->_cookies->addToRequest($request, $cookies);

+ 5 - 1
src/Http/Client/Adapter/Curl.php

@@ -166,11 +166,15 @@ class Curl implements AdapterInterface
                 return CURL_HTTP_VERSION_1_0;
             case '1.1':
                 return CURL_HTTP_VERSION_1_1;
+            case '2':
             case '2.0':
+                if (defined('CURL_HTTP_VERSION_2TLS')) {
+                    return CURL_HTTP_VERSION_2TLS;
+                }
                 if (defined('CURL_HTTP_VERSION_2_0')) {
                     return CURL_HTTP_VERSION_2_0;
                 }
-                throw new HttpException('libcurl 7.33 needed for HTTP 2.0 support');
+                throw new HttpException('libcurl 7.33 or greater required for HTTP/2 support');
         }
 
         return CURL_HTTP_VERSION_NONE;

+ 1 - 1
src/Mailer/Email.php

@@ -616,6 +616,6 @@ class Email implements JsonSerializable, Serializable
      */
     public static function __callStatic($name, $arguments)
     {
-        return call_user_func_array('\Cake\Mailer\Mailer::' . $name, $arguments);
+        return call_user_func_array([Mailer::class, $name], $arguments);
     }
 }

+ 1 - 1
src/ORM/Marshaller.php

@@ -259,7 +259,7 @@ class Marshaller
             );
         }
 
-        return $validator->errors($data, $isNew);
+        return $validator->validate($data, $isNew);
     }
 
     /**

+ 4 - 1
src/ORM/Table.php

@@ -881,8 +881,11 @@ class Table implements RepositoryInterface, EventListenerInterface, EventDispatc
             return $this->_associations->get($name);
         }
 
+        $result = null;
         [$name, $next] = array_pad(explode('.', $name, 2), 2, null);
-        $result = $this->_associations->get($name);
+        if ($name !== null) {
+            $result = $this->_associations->get($name);
+        }
 
         if ($result !== null && $next !== null) {
             $result = $result->getTarget()->getAssociation($next);

+ 7 - 0
src/TestSuite/ConsoleIntegrationTestTrait.php

@@ -28,6 +28,7 @@ use Cake\TestSuite\Constraint\Console\ContentsRegExp;
 use Cake\TestSuite\Constraint\Console\ExitCode;
 use Cake\TestSuite\Stub\ConsoleInput;
 use Cake\TestSuite\Stub\ConsoleOutput;
+use Cake\TestSuite\Stub\MissingConsoleInputException;
 
 /**
  * A test case class intended to make integration tests of cake console commands
@@ -104,6 +105,12 @@ trait ConsoleIntegrationTestTrait
 
         try {
             $this->_exitCode = $runner->run($args, $io);
+        } catch (MissingConsoleInputException $e) {
+            $messages = $this->_out->messages();
+            if (count($messages)) {
+                $e->setQuestion($messages[count($messages) - 1]);
+            }
+            throw $e;
         } catch (StopException $exception) {
             $this->_exitCode = $exception->getCode();
         }

+ 3 - 3
src/TestSuite/Stub/ConsoleInput.php

@@ -16,7 +16,7 @@ declare(strict_types=1);
 namespace Cake\TestSuite\Stub;
 
 use Cake\Console\ConsoleInput as ConsoleInputBase;
-use Cake\Console\Exception\ConsoleException;
+use Cake\TestSuite\Stub\MissingConsoleInputException;
 use NumberFormatter;
 
 /**
@@ -69,8 +69,8 @@ class ConsoleInput extends ConsoleInputBase
 
             $replies = implode(', ', $this->replies);
             $message = "There are no more input replies available. This is the {$nth} read operation, " .
-                "only {$total} replies were set. The provided replies are: {$replies}";
-            throw new ConsoleException($message);
+                "only {$total} replies were set.\nThe provided replies are: {$replies}";
+            throw new MissingConsoleInputException($message);
         }
 
         return $this->replies[$this->currentIndex];

+ 33 - 0
src/TestSuite/Stub/MissingConsoleInputException.php

@@ -0,0 +1,33 @@
+<?php
+/**
+ * CakePHP :  Rapid Development Framework (https://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
+ * @link          https://cakephp.org CakePHP Project
+ * @license       https://opensource.org/licenses/mit-license.php MIT License
+ */
+namespace Cake\TestSuite\Stub;
+
+use RuntimeException;
+
+/**
+ * Exception class used to indicate missing console input.
+ */
+class MissingConsoleInputException extends RuntimeException
+{
+    /**
+     * Update the exception message with the question text
+     *
+     * @param string $question The question text.
+     * @return void
+     */
+    public function setQuestion($question)
+    {
+        $this->message .= "\nThe question asked was: " . $question;
+    }
+}

+ 1 - 1
src/Validation/README.md

@@ -26,7 +26,7 @@ $validator
     ->requirePresence('comment')
     ->notEmpty('comment', 'You need to give a comment.');
 
-$errors = $validator->errors($_POST);
+$errors = $validator->validate($_POST);
 if (!empty($errors)) {
     // display errors.
 }

+ 17 - 4
src/Validation/Validator.php

@@ -184,15 +184,28 @@ class Validator implements ArrayAccess, IteratorAggregate, Countable
     }
 
     /**
-     * Returns an array of fields that have failed validation. On the current model. This method will
-     * actually run validation rules over data, not just return the messages.
+     * Validates and returns an array of failed fields and their error messages.
      *
      * @param array $data The data to be checked for errors
      * @param bool $newRecord whether the data to be validated is new or to be updated.
      * @return array[] Array of invalid fields
+     * @deprecated 3.9.0 Renamed to validate()
      */
     public function errors(array $data, bool $newRecord = true): array
     {
+        deprecationWarning('`Validator::errors()` is deprecated. Use `Validator::validate()` instead.');
+        return $this->validate($data, $newRecord);
+    }
+
+    /**
+     * Validates and returns an array of failed fields and their error messages.
+     *
+     * @param array $data The data to be checked for errors
+     * @param bool $newRecord whether the data to be validated is new or to be updated.
+     * @return array Array of failed fields
+     */
+    public function validate(array $data, $newRecord = true)
+    {
         $errors = [];
 
         foreach ($this->_fields as $name => $field) {
@@ -497,7 +510,7 @@ class Validator implements ArrayAccess, IteratorAggregate, Countable
                 /** @psalm-suppress PossiblyNullArgument */
                 $validator->setProvider($provider, $this->getProvider($provider));
             }
-            $errors = $validator->errors($value, $context['newRecord']);
+            $errors = $validator->validate($value, $context['newRecord']);
 
             $message = $message ? [static::NESTED => $message] : [];
 
@@ -545,7 +558,7 @@ class Validator implements ArrayAccess, IteratorAggregate, Countable
                 if (!is_array($row)) {
                     return false;
                 }
-                $check = $validator->errors($row, $context['newRecord']);
+                $check = $validator->validate($row, $context['newRecord']);
                 if (!empty($check)) {
                     $errors[$i] = $check;
                 }

+ 16 - 0
tests/TestCase/Http/Client/Adapter/CurlTest.php

@@ -341,4 +341,20 @@ class CurlTest extends TestCase
 
         $this->curl->send($request, $options);
     }
+
+    /**
+     * Test converting client options into curl ones.
+     *
+     * @return void
+     */
+    public function testBuildOptionsProtocolVersion()
+    {
+        $this->skipIf(!defined('CURL_HTTP_VERSION_2TLS'), 'Requires libcurl 7.42');
+        $options = [];
+        $request = new Request('http://localhost/things', 'GET');
+        $request = $request->withProtocolVersion('2');
+
+        $result = $this->curl->buildOptions($request, $options);
+        $this->assertSame(CURL_HTTP_VERSION_2TLS, $result[CURLOPT_HTTP_VERSION]);
+    }
 }

+ 4 - 2
tests/TestCase/Http/ClientTest.php

@@ -56,6 +56,7 @@ class ClientTest extends TestCase
             'scheme' => 'http',
             'host' => 'example.org',
             'auth' => ['username' => 'mark', 'password' => 'secret'],
+            'protocolVersion' => '1.1',
         ];
         foreach ($expected as $key => $val) {
             $this->assertEquals($val, $result[$key]);
@@ -211,9 +212,10 @@ class ClientTest extends TestCase
             ->getMock();
         $mock->expects($this->once())
             ->method('send')
-            ->with($this->callback(function ($request) use ($cookies, $headers) {
+            ->with($this->callback(function ($request) use ($headers) {
                 $this->assertInstanceOf('Cake\Http\Client\Request', $request);
                 $this->assertEquals(Request::METHOD_GET, $request->getMethod());
+                $this->assertSame('2', $request->getProtocolVersion());
                 $this->assertSame('http://cakephp.org/test.html', $request->getUri() . '');
                 $this->assertSame('split=value', $request->getHeaderLine('Cookie'));
                 $this->assertEquals($headers['Content-Type'], $request->getHeaderLine('content-type'));
@@ -223,7 +225,7 @@ class ClientTest extends TestCase
             }))
             ->will($this->returnValue([$response]));
 
-        $http = new Client(['adapter' => $mock]);
+        $http = new Client(['adapter' => $mock, 'protocolVersion' => '2']);
         $result = $http->get('http://cakephp.org/test.html', [], [
             'headers' => $headers,
             'cookies' => $cookies,

+ 11 - 11
tests/TestCase/ORM/TableTest.php

@@ -6063,28 +6063,28 @@ class TableTest extends TestCase
         $validator->setProvider('table', $table);
 
         $data = ['username' => ['larry', 'notthere']];
-        $this->assertNotEmpty($validator->errors($data));
+        $this->assertNotEmpty($validator->validate($data));
 
         $data = ['username' => 'larry'];
-        $this->assertNotEmpty($validator->errors($data));
+        $this->assertNotEmpty($validator->validate($data));
 
         $data = ['username' => 'jose'];
-        $this->assertEmpty($validator->errors($data));
+        $this->assertEmpty($validator->validate($data));
 
         $data = ['username' => 'larry', 'id' => 3];
-        $this->assertEmpty($validator->errors($data, false));
+        $this->assertEmpty($validator->validate($data, false));
 
         $data = ['username' => 'larry', 'id' => 3];
-        $this->assertNotEmpty($validator->errors($data));
+        $this->assertNotEmpty($validator->validate($data));
 
         $data = ['username' => 'larry'];
-        $this->assertNotEmpty($validator->errors($data, false));
+        $this->assertNotEmpty($validator->validate($data, false));
 
         $validator->add('username', 'unique', [
             'rule' => 'validateUnique', 'provider' => 'table',
         ]);
         $data = ['username' => 'larry'];
-        $this->assertNotEmpty($validator->errors($data, false));
+        $this->assertNotEmpty($validator->validate($data, false));
     }
 
     /**
@@ -6102,13 +6102,13 @@ class TableTest extends TestCase
         ]);
         $validator->setProvider('table', $table);
         $data = ['username' => 'larry', 'id' => 3];
-        $this->assertNotEmpty($validator->errors($data));
+        $this->assertNotEmpty($validator->validate($data));
 
         $data = ['username' => 'larry', 'id' => 1];
-        $this->assertEmpty($validator->errors($data));
+        $this->assertEmpty($validator->validate($data));
 
         $data = ['username' => 'jose'];
-        $this->assertEmpty($validator->errors($data));
+        $this->assertEmpty($validator->validate($data));
     }
 
     /**
@@ -6144,7 +6144,7 @@ class TableTest extends TestCase
 
         $data = ['site_id' => 1, 'author_id' => null, 'title' => 'Null dupe'];
         $expected = ['site_id' => ['unique' => 'Must be unique.']];
-        $this->assertEquals($expected, $validator->errors($data));
+        $this->assertEquals($expected, $validator->validate($data));
     }
 
     /**

+ 2 - 1
tests/TestCase/TestSuite/ConsoleIntegrationTestTraitTest.php

@@ -18,6 +18,7 @@ namespace Cake\Test\TestCase\TestSuite;
 use Cake\Console\Exception\ConsoleException;
 use Cake\Console\Shell;
 use Cake\TestSuite\ConsoleIntegrationTestCase;
+use Cake\TestSuite\Stub\MissingConsoleInputException;
 use PHPUnit\Framework\AssertionFailedError;
 
 class ConsoleIntegrationTestTraitTest extends ConsoleIntegrationTestCase
@@ -151,7 +152,7 @@ class ConsoleIntegrationTestTraitTest extends ConsoleIntegrationTestCase
      */
     public function testExecWithMissingInput()
     {
-        $this->expectException(ConsoleException::class);
+        $this->expectException(MissingConsoleInputException::class);
         $this->expectExceptionMessage('no more input');
         $this->exec('integration bridge', ['cake']);
     }

File diff suppressed because it is too large
+ 246 - 229
tests/TestCase/Validation/ValidatorTest.php