Browse Source

Merge branch 'master' into 3.next

ADmad 7 years ago
parent
commit
6dfc5a43f1

+ 2 - 0
src/Collection/CollectionInterface.php

@@ -21,6 +21,8 @@ use JsonSerializable;
  * Describes the methods a Collection should implement. A collection is an immutable
  * list of elements exposing a number of traversing and extracting method for
  * generating other collections.
+ *
+ * @method \Cake\Collection\CollectionInterface cartesianProduct(callable $operation = null, callable $filter = null)
  */
 interface CollectionInterface extends Iterator, JsonSerializable
 {

+ 11 - 2
src/Collection/CollectionTrait.php

@@ -283,10 +283,12 @@ trait CollectionTrait
         $callback = $this->_propertyExtractor($callback);
 
         $mapper = function ($value, $key, $mr) use ($callback) {
+            /** @var \Cake\Collection\Iterator\MapReduce $mr */
             $mr->emitIntermediate($value, $callback($value));
         };
 
         $reducer = function ($values, $key, $mr) {
+            /** @var \Cake\Collection\Iterator\MapReduce $mr */
             $mr->emit(count($values), $key);
         };
 
@@ -558,6 +560,7 @@ trait CollectionTrait
         ];
 
         $mapper = function ($value, $key, $mapReduce) use ($options) {
+            /** @var \Cake\Collection\Iterator\MapReduce $mapReduce */
             $rowKey = $options['keyPath'];
             $rowVal = $options['valuePath'];
 
@@ -579,6 +582,7 @@ trait CollectionTrait
             foreach ($values as $value) {
                 $result += $value;
             }
+            /** @var \Cake\Collection\Iterator\MapReduce $mapReduce */
             $mapReduce->emit($result, $key);
         };
 
@@ -600,6 +604,7 @@ trait CollectionTrait
             $id = $idPath($row, $key);
             $parentId = $parentPath($row, $key);
             $parents[$id] =& $row;
+            /** @var \Cake\Collection\Iterator\MapReduce $mapReduce */
             $mapReduce->emitIntermediate($id, $parentId);
         };
 
@@ -612,6 +617,7 @@ trait CollectionTrait
             if (empty($key) || !isset($parents[$key])) {
                 foreach ($values as $id) {
                     $parents[$id] = $isObject ? $parents[$id] : new ArrayIterator($parents[$id], 1);
+                    /** @var \Cake\Collection\Iterator\MapReduce $mapReduce */
                     $mapReduce->emit($parents[$id]);
                 }
 
@@ -627,6 +633,7 @@ trait CollectionTrait
 
         return (new Collection(new MapReduce($this->unwrap(), $mapper, $reducer)))
             ->map(function ($value) use (&$isObject) {
+                /** @var \ArrayIterator $value */
                 return $isObject ? $value : $value->getArrayCopy();
             });
     }
@@ -885,9 +892,10 @@ trait CollectionTrait
     }
 
     /**
-     * {@inheritDoc}
-     *
+     * @param callable|null $operation Operation
+     * @param callable|null $filter Filter
      * @return \Cake\Collection\CollectionInterface
+     * @throws \LogicException
      */
     public function cartesianProduct(callable $operation = null, callable $filter = null)
     {
@@ -941,6 +949,7 @@ trait CollectionTrait
      * {@inheritDoc}
      *
      * @return \Cake\Collection\CollectionInterface
+     * @throws \LogicException
      */
     public function transpose()
     {

+ 1 - 1
src/Collection/Iterator/FilterIterator.php

@@ -43,7 +43,7 @@ class FilterIterator extends Collection
      * in the current iteration, the key of the element and the passed $items iterator
      * as arguments, in that order.
      *
-     * @param \Iterator $items The items to be filtered.
+     * @param \Traversable|array $items The items to be filtered.
      * @param callable $callback Callback.
      */
     public function __construct($items, callable $callback)

+ 3 - 0
src/Database/Type/DecimalType.php

@@ -157,6 +157,9 @@ class DecimalType extends Type implements TypeInterface, BatchCastingInterface
         if (is_numeric($value)) {
             return (float)$value;
         }
+        if (is_string($value) && preg_match('/^[0-9,. ]+$/', $value)) {
+            return $value;
+        }
 
         return null;
     }

+ 3 - 0
src/Database/Type/FloatType.php

@@ -146,6 +146,9 @@ class FloatType extends Type implements TypeInterface, BatchCastingInterface
         if (is_numeric($value)) {
             return (float)$value;
         }
+        if (is_string($value) && preg_match('/^[0-9,. ]+$/', $value)) {
+            return $value;
+        }
 
         return null;
     }

+ 19 - 12
src/Database/Type/IntegerType.php

@@ -52,6 +52,23 @@ class IntegerType extends Type implements TypeInterface, BatchCastingInterface
     }
 
     /**
+     * Checks if the value is not a numeric value
+     *
+     * @throws \InvalidArgumentException
+     * @param mixed $value Value to check
+     * @return void
+     */
+    protected function checkNumeric($value)
+    {
+        if (!is_numeric($value)) {
+            throw new InvalidArgumentException(sprintf(
+                'Cannot convert value of type `%s` to integer',
+                getTypeName($value)
+            ));
+        }
+    }
+
+    /**
      * Convert integer data into the database format.
      *
      * @param mixed $value The value to convert.
@@ -64,12 +81,7 @@ class IntegerType extends Type implements TypeInterface, BatchCastingInterface
             return null;
         }
 
-        if (!is_numeric($value)) {
-            throw new InvalidArgumentException(sprintf(
-                'Cannot convert value of type `%s` to integer',
-                getTypeName($value)
-            ));
-        }
+        $this->checkNumeric($value);
 
         return (int)$value;
     }
@@ -102,12 +114,7 @@ class IntegerType extends Type implements TypeInterface, BatchCastingInterface
                 continue;
             }
 
-            if (!is_numeric($values[$field])) {
-                throw new InvalidArgumentException(sprintf(
-                    'Cannot convert value of type `%s` to integer',
-                    getTypeName($values[$field])
-                ));
-            }
+            $this->checkNumeric($values[$field]);
 
             $values[$field] = (int)$values[$field];
         }

+ 3 - 1
src/Routing/Router.php

@@ -206,6 +206,7 @@ class Router
     {
         static::$initialized = true;
         static::scope('/', function ($routes) use ($route, $defaults, $options) {
+            /** @var \Cake\Routing\RouteBuilder $routes */
             $routes->connect($route, $defaults, $options);
         });
     }
@@ -216,7 +217,7 @@ class Router
      * Compatibility proxy to \Cake\Routing\RouteBuilder::redirect() in the `/` scope.
      *
      * @param string $route A string describing the template of the route
-     * @param array $url A URL to redirect to. Can be a string or a Cake array-based URL
+     * @param array|string $url A URL to redirect to. Can be a string or a Cake array-based URL
      * @param array $options An array matching the named elements in the route to regular expressions which that
      *   element should match. Also contains additional parameters such as which routed parameters should be
      *   shifted into the passed arguments. As well as supplying patterns for routing parameters.
@@ -313,6 +314,7 @@ class Router
             }
 
             $callback = function ($routes) use ($name, $options) {
+                /** @var \Cake\Routing\RouteBuilder $routes */
                 $routes->resources($name, $options);
             };
 

+ 6 - 5
tests/TestCase/Controller/Component/AuthComponentTest.php

@@ -22,6 +22,7 @@ use Cake\Event\Event;
 use Cake\Event\EventManager;
 use Cake\Http\Response;
 use Cake\Http\ServerRequest;
+use Cake\Routing\RouteBuilder;
 use Cake\Routing\Router;
 use Cake\Routing\Route\InflectedRoute;
 use Cake\TestSuite\TestCase;
@@ -61,7 +62,7 @@ class AuthComponentTest extends TestCase
         Security::setSalt('YJfIxfs2guVoUubWDYhG93b0qyJfIxfs2guwvniR2G0FgaC9mi');
         static::setAppNamespace();
 
-        Router::scope('/', function ($routes) {
+        Router::scope('/', function (RouteBuilder $routes) {
             $routes->fallbacks(InflectedRoute::class);
         });
 
@@ -1112,10 +1113,10 @@ class AuthComponentTest extends TestCase
     {
         $event = new Event('Controller.startup', $this->Controller);
         Router::reload();
-        Router::prefix('admin', function ($routes) {
+        Router::prefix('admin', function (RouteBuilder $routes) {
             $routes->fallbacks(InflectedRoute::class);
         });
-        Router::scope('/', function ($routes) {
+        Router::scope('/', function (RouteBuilder $routes) {
             $routes->fallbacks(InflectedRoute::class);
         });
         $this->Controller->request = new ServerRequest([
@@ -1211,10 +1212,10 @@ class AuthComponentTest extends TestCase
     {
         $event = new Event('Controller.startup', $this->Controller);
         Router::reload();
-        Router::prefix('admin', function ($routes) {
+        Router::prefix('admin', function (RouteBuilder $routes) {
             $routes->fallbacks(InflectedRoute::class);
         });
-        Router::scope('/', function ($routes) {
+        Router::scope('/', function (RouteBuilder $routes) {
             $routes->fallbacks(InflectedRoute::class);
         });
 

+ 4 - 0
tests/TestCase/Database/Type/DecimalTypeTest.php

@@ -167,6 +167,10 @@ class DecimalTypeTest extends TestCase
         $result = $this->type->marshal('2.51');
         $this->assertSame(2.51, $result);
 
+        // allow custom decimal format (@see https://github.com/cakephp/cakephp/issues/12800)
+        $result = $this->type->marshal('1 230,73');
+        $this->assertSame('1 230,73', $result);
+
         $result = $this->type->marshal('3.5 bears');
         $this->assertNull($result);
 

+ 4 - 0
tests/TestCase/Database/Type/FloatTypeTest.php

@@ -156,6 +156,10 @@ class FloatTypeTest extends TestCase
         $result = $this->type->marshal('2.51');
         $this->assertSame(2.51, $result);
 
+        // allow custom decimal format (@see https://github.com/cakephp/cakephp/issues/12800)
+        $result = $this->type->marshal('1 230,73');
+        $this->assertSame('1 230,73', $result);
+
         $result = $this->type->marshal('3.5 bears');
         $this->assertNull($result);
 

+ 4 - 3
tests/TestCase/ORM/Behavior/TranslateBehaviorTest.php

@@ -15,6 +15,7 @@
 namespace Cake\Test\TestCase\ORM\Behavior;
 
 use Cake\Collection\Collection;
+use Cake\Datasource\EntityInterface;
 use Cake\I18n\I18n;
 use Cake\ORM\Behavior\Translate\TranslateTrait;
 use Cake\ORM\Entity;
@@ -67,14 +68,14 @@ class TranslateBehaviorTest extends TestCase
      */
     protected function _extractTranslations($data)
     {
-        return (new Collection($data))->map(function ($row) {
+        return (new Collection($data))->map(function (EntityInterface $row) {
             $translations = $row->get('_translations');
             if (!$translations) {
                 return [];
             }
 
-            return array_map(function ($t) {
-                return $t->toArray();
+            return array_map(function (EntityInterface $entity) {
+                return $entity->toArray();
             }, $translations);
         });
     }

+ 16 - 15
tests/TestCase/Routing/Middleware/RoutingMiddlewareTest.php

@@ -23,6 +23,7 @@ use Cake\TestSuite\TestCase;
 use TestApp\Application;
 use TestApp\Middleware\DumbMiddleware;
 use Zend\Diactoros\Response;
+use Zend\Diactoros\ServerRequest;
 use Zend\Diactoros\ServerRequestFactory;
 
 /**
@@ -52,7 +53,7 @@ class RoutingMiddlewareTest extends TestCase
      */
     public function testRedirectResponse()
     {
-        Router::scope('/', function ($routes) {
+        Router::scope('/', function (RouteBuilder $routes) {
             $routes->redirect('/testpath', '/pages');
         });
         $request = ServerRequestFactory::fromGlobals(['REQUEST_URI' => '/testpath']);
@@ -75,7 +76,7 @@ class RoutingMiddlewareTest extends TestCase
      */
     public function testRedirectResponseWithHeaders()
     {
-        Router::scope('/', function ($routes) {
+        Router::scope('/', function (RouteBuilder $routes) {
             $routes->redirect('/testpath', '/pages');
         });
         $request = ServerRequestFactory::fromGlobals(['REQUEST_URI' => '/testpath']);
@@ -99,7 +100,7 @@ class RoutingMiddlewareTest extends TestCase
     {
         $request = ServerRequestFactory::fromGlobals(['REQUEST_URI' => '/articles']);
         $response = new Response();
-        $next = function ($req, $res) {
+        $next = function (ServerRequest $req, $res) {
             $expected = [
                 'controller' => 'Articles',
                 'action' => 'index',
@@ -123,7 +124,7 @@ class RoutingMiddlewareTest extends TestCase
         $request = ServerRequestFactory::fromGlobals(['REQUEST_URI' => '/articles']);
         $request = $request->withAttribute('params', ['_csrfToken' => 'i-am-groot']);
         $response = new Response();
-        $next = function ($req, $res) {
+        $next = function (ServerRequest $req, $res) {
             $expected = [
                 'controller' => 'Articles',
                 'action' => 'index',
@@ -150,7 +151,7 @@ class RoutingMiddlewareTest extends TestCase
 
         $request = ServerRequestFactory::fromGlobals(['REQUEST_URI' => '/app/articles']);
         $response = new Response();
-        $next = function ($req, $res) {
+        $next = function (ServerRequest $req, $res) {
             $expected = [
                 'controller' => 'Articles',
                 'action' => 'index',
@@ -204,7 +205,7 @@ class RoutingMiddlewareTest extends TestCase
         $request = ServerRequestFactory::fromGlobals(['REQUEST_URI' => '/articles']);
         $request = $request->withAttribute('params', ['controller' => 'Articles']);
         $response = new Response();
-        $next = function ($req, $res) {
+        $next = function (ServerRequest $req, $res) {
             $this->assertEquals(['controller' => 'Articles'], $req->getAttribute('params'));
         };
         $middleware = new RoutingMiddleware($this->app());
@@ -247,7 +248,7 @@ class RoutingMiddlewareTest extends TestCase
             ['_method' => 'PATCH']
         );
         $response = new Response();
-        $next = function ($req, $res) {
+        $next = function (ServerRequest $req, $res) {
             $expected = [
                 'controller' => 'Articles',
                 'action' => 'index',
@@ -270,7 +271,7 @@ class RoutingMiddlewareTest extends TestCase
      */
     public function testInvokeScopedMiddleware()
     {
-        Router::scope('/api', function ($routes) {
+        Router::scope('/api', function (RouteBuilder $routes) {
             $routes->registerMiddleware('first', function ($req, $res, $next) {
                 $this->log[] = 'first';
 
@@ -315,7 +316,7 @@ class RoutingMiddlewareTest extends TestCase
      */
     public function testInvokeScopedMiddlewareReturnResponse()
     {
-        Router::scope('/', function ($routes) {
+        Router::scope('/', function (RouteBuilder $routes) {
             $routes->registerMiddleware('first', function ($req, $res, $next) {
                 $this->log[] = 'first';
 
@@ -330,7 +331,7 @@ class RoutingMiddlewareTest extends TestCase
             $routes->applyMiddleware('first');
             $routes->connect('/', ['controller' => 'Home']);
 
-            $routes->scope('/api', function ($routes) {
+            $routes->scope('/api', function (RouteBuilder $routes) {
                 $routes->applyMiddleware('second');
                 $routes->connect('/articles', ['controller' => 'Articles']);
             });
@@ -358,7 +359,7 @@ class RoutingMiddlewareTest extends TestCase
      */
     public function testInvokeScopedMiddlewareReturnResponseMainScope()
     {
-        Router::scope('/', function ($routes) {
+        Router::scope('/', function (RouteBuilder $routes) {
             $routes->registerMiddleware('first', function ($req, $res, $next) {
                 $this->log[] = 'first';
 
@@ -373,7 +374,7 @@ class RoutingMiddlewareTest extends TestCase
             $routes->applyMiddleware('first');
             $routes->connect('/', ['controller' => 'Home']);
 
-            $routes->scope('/api', function ($routes) {
+            $routes->scope('/api', function (RouteBuilder $routes) {
                 $routes->applyMiddleware('second');
                 $routes->connect('/articles', ['controller' => 'Articles']);
             });
@@ -405,7 +406,7 @@ class RoutingMiddlewareTest extends TestCase
      */
     public function testInvokeScopedMiddlewareIsolatedScopes($url, $expected)
     {
-        Router::scope('/', function ($routes) {
+        Router::scope('/', function (RouteBuilder $routes) {
             $routes->registerMiddleware('first', function ($req, $res, $next) {
                 $this->log[] = 'first';
 
@@ -417,12 +418,12 @@ class RoutingMiddlewareTest extends TestCase
                 return $next($req, $res);
             });
 
-            $routes->scope('/api', function ($routes) {
+            $routes->scope('/api', function (RouteBuilder $routes) {
                 $routes->applyMiddleware('first');
                 $routes->connect('/ping', ['controller' => 'Pings']);
             });
 
-            $routes->scope('/api', function ($routes) {
+            $routes->scope('/api', function (RouteBuilder $routes) {
                 $routes->applyMiddleware('second');
                 $routes->connect('/version', ['controller' => 'Version']);
             });

+ 8 - 8
tests/TestCase/Routing/RouteBuilderTest.php

@@ -665,7 +665,7 @@ class RouteBuilderTest extends TestCase
         $routes->resources(
             'NetworkObjects',
             ['inflect' => 'dasherize'],
-            function ($routes) {
+            function (RouteBuilder $routes) {
                 $routes->resources('Attributes');
             }
         );
@@ -721,7 +721,7 @@ class RouteBuilderTest extends TestCase
      */
     public function testResourcesInScope()
     {
-        Router::scope('/api', ['prefix' => 'api'], function ($routes) {
+        Router::scope('/api', ['prefix' => 'api'], function (RouteBuilder $routes) {
             $routes->setExtensions(['json']);
             $routes->resources('Articles');
         });
@@ -873,7 +873,7 @@ class RouteBuilderTest extends TestCase
     public function testResourcesNested()
     {
         $routes = new RouteBuilder($this->collection, '/api', ['prefix' => 'api']);
-        $routes->resources('Articles', function ($routes) {
+        $routes->resources('Articles', function (RouteBuilder $routes) {
             $this->assertEquals('/api/articles/', $routes->path());
             $this->assertEquals(['prefix' => 'api'], $routes->params());
 
@@ -938,7 +938,7 @@ class RouteBuilderTest extends TestCase
     public function testScope()
     {
         $routes = new RouteBuilder($this->collection, '/api', ['prefix' => 'api']);
-        $routes->scope('/v1', ['version' => 1], function ($routes) {
+        $routes->scope('/v1', ['version' => 1], function (RouteBuilder $routes) {
             $this->assertEquals('/api/v1', $routes->path());
             $this->assertEquals(['prefix' => 'api', 'version' => 1], $routes->params());
         });
@@ -952,7 +952,7 @@ class RouteBuilderTest extends TestCase
     public function testScopeWithAction()
     {
         $routes = new RouteBuilder($this->collection, '/api', ['prefix' => 'api']);
-        $routes->scope('/prices', ['controller' => 'Prices', 'action' => 'view'], function ($routes) {
+        $routes->scope('/prices', ['controller' => 'Prices', 'action' => 'view'], function (RouteBuilder $routes) {
             $routes->connect('/shared', ['shared' => true]);
             $routes->get('/exclusive', ['exclusive' => true]);
         });
@@ -978,7 +978,7 @@ class RouteBuilderTest extends TestCase
             ['prefix' => 'api'],
             ['middleware' => ['auth']]
         );
-        $routes->scope('/v1', function ($routes) {
+        $routes->scope('/v1', function (RouteBuilder $routes) {
             $this->assertAttributeEquals(['auth'], 'middleware', $routes, 'Should inherit middleware');
             $this->assertEquals('/api/v1', $routes->path());
             $this->assertEquals(['prefix' => 'api'], $routes->params());
@@ -993,7 +993,7 @@ class RouteBuilderTest extends TestCase
     public function testNamePrefixes()
     {
         $routes = new RouteBuilder($this->collection, '/api', [], ['namePrefix' => 'api:']);
-        $routes->scope('/v1', ['version' => 1, '_namePrefix' => 'v1:'], function ($routes) {
+        $routes->scope('/v1', ['version' => 1, '_namePrefix' => 'v1:'], function (RouteBuilder $routes) {
             $this->assertEquals('api:v1:', $routes->namePrefix());
             $routes->connect('/ping', ['controller' => 'Pings'], ['_name' => 'ping']);
 
@@ -1215,7 +1215,7 @@ class RouteBuilderTest extends TestCase
     public function testHttpMethodIntegration()
     {
         $routes = new RouteBuilder($this->collection, '/');
-        $routes->scope('/', function ($routes) {
+        $routes->scope('/', function (RouteBuilder $routes) {
             $routes->get('/faq/:page', ['controller' => 'Pages', 'action' => 'faq'], 'faq')
                 ->setPatterns(['page' => '[a-z0-9_]+'])
                 ->setHost('docs.example.com');

+ 23 - 23
tests/TestCase/Routing/RouterTest.php

@@ -106,7 +106,7 @@ class RouterTest extends TestCase
     {
         Configure::write('App.base', '/cakephp');
         Router::fullBaseUrl('http://example.com');
-        Router::scope('/', function ($routes) {
+        Router::scope('/', function (RouteBuilder $routes) {
             $routes->get('/:controller/:action', []);
         });
 
@@ -1103,8 +1103,8 @@ class RouterTest extends TestCase
      */
     public function testUrlGenerationPrefixedPlugin()
     {
-        Router::prefix('admin', function ($routes) {
-            $routes->plugin('MyPlugin', function ($routes) {
+        Router::prefix('admin', function (RouteBuilder $routes) {
+            $routes->plugin('MyPlugin', function (RouteBuilder $routes) {
                 $routes->fallbacks('InflectedRoute');
             });
         });
@@ -1120,8 +1120,8 @@ class RouterTest extends TestCase
      */
     public function testUrlGenerationMultiplePrefixes()
     {
-        Router::prefix('admin', function ($routes) {
-            $routes->prefix('backoffice', function ($routes) {
+        Router::prefix('admin', function (RouteBuilder $routes) {
+            $routes->prefix('backoffice', function (RouteBuilder $routes) {
                 $routes->fallbacks('InflectedRoute');
             });
         });
@@ -1871,11 +1871,11 @@ class RouterTest extends TestCase
     {
         Router::extensions(['json']);
 
-        Router::scope('/', function ($routes) {
+        Router::scope('/', function (RouteBuilder $routes) {
             $routes->setExtensions('rss');
             $routes->connect('/', ['controller' => 'Pages', 'action' => 'index']);
 
-            $routes->scope('/api', function ($routes) {
+            $routes->scope('/api', function (RouteBuilder $routes) {
                 $routes->setExtensions('xml');
                 $routes->connect('/docs', ['controller' => 'ApiDocs', 'action' => 'index']);
             });
@@ -1891,7 +1891,7 @@ class RouterTest extends TestCase
      */
     public function testResourcesInScope()
     {
-        Router::scope('/api', ['prefix' => 'api'], function ($routes) {
+        Router::scope('/api', ['prefix' => 'api'], function (RouteBuilder $routes) {
             $routes->setExtensions(['json']);
             $routes->resources('Articles');
         });
@@ -3154,7 +3154,7 @@ class RouterTest extends TestCase
      */
     public function testScope()
     {
-        Router::scope('/path', ['param' => 'value'], function ($routes) {
+        Router::scope('/path', ['param' => 'value'], function (RouteBuilder $routes) {
             $this->assertInstanceOf('Cake\Routing\RouteBuilder', $routes);
             $this->assertEquals('/path', $routes->path());
             $this->assertEquals(['param' => 'value'], $routes->params());
@@ -3184,7 +3184,7 @@ class RouterTest extends TestCase
     public function testScopeExtensionsContained()
     {
         Router::extensions(['json']);
-        Router::scope('/', function ($routes) {
+        Router::scope('/', function (RouteBuilder $routes) {
             $this->assertEquals(['json'], $routes->getExtensions(), 'Should default to global extensions.');
             $routes->setExtensions(['rss']);
 
@@ -3198,13 +3198,13 @@ class RouterTest extends TestCase
 
         $this->assertEquals(['json', 'rss'], array_values(Router::extensions()));
 
-        Router::scope('/api', function ($routes) {
+        Router::scope('/api', function (RouteBuilder $routes) {
             $this->assertEquals(['json'], $routes->getExtensions(), 'Should default to global extensions.');
 
             $routes->setExtensions(['json', 'csv']);
             $routes->connect('/export', []);
 
-            $routes->scope('/v1', function ($routes) {
+            $routes->scope('/v1', function (RouteBuilder $routes) {
                 $this->assertEquals(['json', 'csv'], $routes->getExtensions());
             });
         });
@@ -3220,7 +3220,7 @@ class RouterTest extends TestCase
     public function testScopeOptions()
     {
         $options = ['param' => 'value', 'routeClass' => 'InflectedRoute', 'extensions' => ['json']];
-        Router::scope('/path', $options, function ($routes) {
+        Router::scope('/path', $options, function (RouteBuilder $routes) {
             $this->assertSame('InflectedRoute', $routes->getRouteClass());
             $this->assertSame(['json'], $routes->getExtensions());
             $this->assertEquals('/path', $routes->path());
@@ -3235,7 +3235,7 @@ class RouterTest extends TestCase
      */
     public function testScopeNamePrefix()
     {
-        Router::scope('/path', ['param' => 'value', '_namePrefix' => 'path:'], function ($routes) {
+        Router::scope('/path', ['param' => 'value', '_namePrefix' => 'path:'], function (RouteBuilder $routes) {
             $this->assertInstanceOf('Cake\Routing\RouteBuilder', $routes);
             $this->assertEquals('/path', $routes->path());
             $this->assertEquals(['param' => 'value'], $routes->params());
@@ -3252,13 +3252,13 @@ class RouterTest extends TestCase
      */
     public function testPrefix()
     {
-        Router::prefix('admin', function ($routes) {
+        Router::prefix('admin', function (RouteBuilder $routes) {
             $this->assertInstanceOf('Cake\Routing\RouteBuilder', $routes);
             $this->assertEquals('/admin', $routes->path());
             $this->assertEquals(['prefix' => 'admin'], $routes->params());
         });
 
-        Router::prefix('admin', ['_namePrefix' => 'admin:'], function ($routes) {
+        Router::prefix('admin', ['_namePrefix' => 'admin:'], function (RouteBuilder $routes) {
             $this->assertInstanceOf('Cake\Routing\RouteBuilder', $routes);
             $this->assertEquals('admin:', $routes->namePrefix());
             $this->assertEquals(['prefix' => 'admin'], $routes->params());
@@ -3272,13 +3272,13 @@ class RouterTest extends TestCase
      */
     public function testPrefixOptions()
     {
-        Router::prefix('admin', ['param' => 'value'], function ($routes) {
+        Router::prefix('admin', ['param' => 'value'], function (RouteBuilder $routes) {
             $this->assertInstanceOf('Cake\Routing\RouteBuilder', $routes);
             $this->assertEquals('/admin', $routes->path());
             $this->assertEquals(['prefix' => 'admin', 'param' => 'value'], $routes->params());
         });
 
-        Router::prefix('CustomPath', ['path' => '/custom-path'], function ($routes) {
+        Router::prefix('CustomPath', ['path' => '/custom-path'], function (RouteBuilder $routes) {
             $this->assertInstanceOf('Cake\Routing\RouteBuilder', $routes);
             $this->assertEquals('/custom-path', $routes->path());
             $this->assertEquals(['prefix' => 'custom_path'], $routes->params());
@@ -3292,7 +3292,7 @@ class RouterTest extends TestCase
      */
     public function testPlugin()
     {
-        Router::plugin('DebugKit', function ($routes) {
+        Router::plugin('DebugKit', function (RouteBuilder $routes) {
             $this->assertInstanceOf('Cake\Routing\RouteBuilder', $routes);
             $this->assertEquals('/debug_kit', $routes->path());
             $this->assertEquals(['plugin' => 'DebugKit'], $routes->params());
@@ -3306,13 +3306,13 @@ class RouterTest extends TestCase
      */
     public function testPluginOptions()
     {
-        Router::plugin('DebugKit', ['path' => '/debugger'], function ($routes) {
+        Router::plugin('DebugKit', ['path' => '/debugger'], function (RouteBuilder $routes) {
             $this->assertInstanceOf('Cake\Routing\RouteBuilder', $routes);
             $this->assertEquals('/debugger', $routes->path());
             $this->assertEquals(['plugin' => 'DebugKit'], $routes->params());
         });
 
-        Router::plugin('Contacts', ['_namePrefix' => 'contacts:'], function ($routes) {
+        Router::plugin('Contacts', ['_namePrefix' => 'contacts:'], function (RouteBuilder $routes) {
             $this->assertInstanceOf('Cake\Routing\RouteBuilder', $routes);
             $this->assertEquals('contacts:', $routes->namePrefix());
         });
@@ -3342,7 +3342,7 @@ class RouterTest extends TestCase
 
         Router::reload();
         Router::defaultRouteClass('DashedRoute');
-        Router::scope('/', function ($routes) {
+        Router::scope('/', function (RouteBuilder $routes) {
             $routes->fallbacks();
         });
 
@@ -3481,7 +3481,7 @@ class RouterTest extends TestCase
      */
     protected function _connectDefaultRoutes()
     {
-        Router::scope('/', function ($routes) {
+        Router::scope('/', function (RouteBuilder $routes) {
             $routes->fallbacks('InflectedRoute');
         });
     }

+ 17 - 3
tests/TestCase/Shell/Helper/ProgressHelperTest.php

@@ -24,6 +24,20 @@ use Cake\TestSuite\TestCase;
  */
 class ProgressHelperTest extends TestCase
 {
+    /**
+     * @var \Cake\Shell\Helper\ProgressHelper
+     */
+    protected $helper;
+
+    /**
+     * @var \Cake\TestSuite\Stub\ConsoleOutput
+     */
+    protected $stub;
+
+    /**
+     * @var \Cake\Console\ConsoleIo
+     */
+    protected $io;
 
     /**
      * setUp method
@@ -50,7 +64,7 @@ class ProgressHelperTest extends TestCase
             'total' => 200,
             'width' => 50
         ]);
-        $this->assertSame($helper, $this->helper, 'init should be chainable');
+        $this->assertSame($helper, $this->helper, 'Should be chainable');
     }
 
     /**
@@ -70,7 +84,7 @@ class ProgressHelperTest extends TestCase
      */
     public function testOutputSuccess()
     {
-        $this->helper->output([function ($progress) {
+        $this->helper->output([function (ProgressHelper $progress) {
             $progress->increment(20);
         }]);
         $expected = [
@@ -100,7 +114,7 @@ class ProgressHelperTest extends TestCase
         $this->helper->output([
             'total' => 10,
             'width' => 20,
-            'callback' => function ($progress) {
+            'callback' => function (ProgressHelper $progress) {
                 $progress->increment(2);
             }
         ]);