Browse Source

Merge branch 'master' into 4.next

Corey Taylor 6 years ago
parent
commit
e7d6371945

+ 2 - 1
src/Console/ConsoleIo.php

@@ -612,7 +612,8 @@ class ConsoleIo
         }
 
         $file->rewind();
-        if ($file->fwrite($contents) > 0) {
+        $file->fwrite($contents);
+        if (file_exists($path)) {
             $this->out("<success>Wrote</success> `{$path}`");
 
             return true;

+ 1 - 0
src/Core/StaticConfigTrait.php

@@ -105,6 +105,7 @@ trait StaticConfigTrait
             $config['className'] = $config['engine'];
             unset($config['engine']);
         }
+        /** @psalm-suppress InvalidPropertyAssignmentValue */
         static::$_config[$key] = $config;
     }
 

+ 0 - 1
src/Event/EventManager.php

@@ -157,7 +157,6 @@ class EventManager implements EventManagerInterface
      * @param array $function the array taken from a handler definition for an event
      * @param \Cake\Event\EventListenerInterface $object The handler object
      * @return array
-     * @psalm-return array{callable, array}
      */
     protected function _extractCallable(array $function, EventListenerInterface $object): array
     {

+ 1 - 0
src/I18n/Translator.php

@@ -105,6 +105,7 @@ class Translator extends BaseTranslator
                 return $message['_context'][''] === '' ? $key : $message['_context'][''];
             }
 
+            /** @psalm-suppress PossiblyUndefinedArrayOffset */
             return current($message['_context']);
         }
         if (!isset($message['_context'][$context])) {

+ 3 - 9
src/ORM/Behavior/CounterCacheBehavior.php

@@ -21,7 +21,7 @@ use Cake\Datasource\EntityInterface;
 use Cake\Event\EventInterface;
 use Cake\ORM\Association;
 use Cake\ORM\Behavior;
-use RuntimeException;
+use Closure;
 
 /**
  * CounterCache behavior
@@ -241,10 +241,7 @@ class CounterCacheBehavior extends Behavior
                 continue;
             }
 
-            if (is_callable($config)) {
-                if (is_string($config)) {
-                    throw new RuntimeException('You must not use a string as callable.');
-                }
+            if ($config instanceof Closure) {
                 $count = $config($event, $entity, $this->_table, false);
             } else {
                 $count = $this->_getCount($config, $countConditions);
@@ -254,10 +251,7 @@ class CounterCacheBehavior extends Behavior
             }
 
             if (isset($updateOriginalConditions)) {
-                if (is_callable($config)) {
-                    if (is_string($config)) {
-                        throw new RuntimeException('You must not use a string as callable.');
-                    }
+                if ($config instanceof Closure) {
                     $count = $config($event, $entity, $this->_table, true);
                 } else {
                     $count = $this->_getCount($config, $countOriginalConditions);

+ 1 - 0
src/ORM/TableRegistry.php

@@ -68,6 +68,7 @@ class TableRegistry
      * Default LocatorInterface implementation class.
      *
      * @var string
+     * @psalm-var class-string<\Cake\ORM\Locator\TableLocator>
      */
     protected static $_defaultLocatorClass = Locator\TableLocator::class;
 

+ 1 - 1
src/TestSuite/MiddlewareDispatcher.php

@@ -90,7 +90,7 @@ class MiddlewareDispatcher
             $app = $reflect->newInstanceArgs($this->_constructorArgs);
             $this->app = $app;
         } catch (ReflectionException $e) {
-            throw new LogicException(sprintf('Cannot load "%s" for use in integration testing.', $this->_class));
+            throw new LogicException("Cannot load `{$this->_class}` for use in integration testing.", 0, $e);
         }
     }
 

+ 30 - 0
src/TestSuite/TestCase.php

@@ -28,7 +28,10 @@ use Cake\Routing\Router;
 use Cake\TestSuite\Constraint\EventFired;
 use Cake\TestSuite\Constraint\EventFiredWith;
 use Cake\Utility\Inflector;
+use LogicException;
 use PHPUnit\Framework\TestCase as BaseTestCase;
+use ReflectionClass;
+use ReflectionException;
 use RuntimeException;
 
 /**
@@ -196,6 +199,33 @@ abstract class TestCase extends BaseTestCase
     }
 
     /**
+     * Load routes for the application.
+     *
+     * If no application class can be found an exception will be raised.
+     * Routes for plugins will *not* be loaded. Use `loadPlugins()` or use
+     * `Cake\TestSuite\IntegrationTestCaseTrait` to better simulate all routes
+     * and plugins being loaded.
+     *
+     * @param array|null $appArgs Constuctor parameters for the application class.
+     * @return void
+     * @since 4.0.1
+     */
+    public function loadRoutes(?array $appArgs = null): void
+    {
+        $appArgs = $appArgs ?? [rtrim(CONFIG, DIRECTORY_SEPARATOR)];
+        $className = Configure::read('App.namespace') . '\\Application';
+        try {
+            $reflect = new ReflectionClass($className);
+            /** @var \Cake\Routing\RoutingApplicationInterface $app */
+            $app = $reflect->newInstanceArgs($appArgs);
+        } catch (ReflectionException $e) {
+            throw new LogicException(sprintf('Cannot load "%s" to load routes from.', $className), 0, $e);
+        }
+        $builder = Router::createRouteBuilder('/');
+        $app->routes($builder);
+    }
+
+    /**
      * Load plugins into a simulated application.
      *
      * Useful to test how plugins being loaded/not loaded interact with other

+ 1 - 1
src/View/Helper/HtmlHelper.php

@@ -873,7 +873,7 @@ class HtmlHelper extends Helper
         if (!empty($options['escape'])) {
             $text = h($text);
         }
-        if ($class && !empty($class)) {
+        if ($class) {
             $options['class'] = $class;
         }
         $tag = 'para';

+ 1 - 0
src/View/HelperRegistry.php

@@ -96,6 +96,7 @@ class HelperRegistry extends ObjectRegistry implements EventDispatcherInterface
             return $this->_loaded[$name];
         }
         if (isset($this->{$name})) {
+            /** @psalm-suppress InvalidReturnStatement */
             return $this->_loaded[$name];
         }
 

+ 1 - 0
src/View/StringTemplateTrait.php

@@ -77,6 +77,7 @@ trait StringTemplateTrait
     public function templater(): StringTemplate
     {
         if ($this->_templater === null) {
+            /** @psalm-var class-string<\Cake\View\StringTemplate> $class */
             $class = $this->getConfig('templateClass') ?: StringTemplate::class;
             $this->_templater = new $class();
 

+ 16 - 0
tests/TestCase/Console/ConsoleIoTest.php

@@ -678,6 +678,22 @@ class ConsoleIoTest extends TestCase
         $this->assertStringEqualsFile($file, $contents);
     }
 
+    public function testCreateFileEmptySuccess()
+    {
+        $this->err->expects($this->never())
+            ->method('write');
+        $path = TMP . 'shell_test';
+        mkdir($path);
+
+        $file = $path . DS . 'file_empty.php';
+        $contents = '';
+        $result = $this->io->createFile($file, $contents);
+
+        $this->assertTrue($result);
+        $this->assertFileExists($file);
+        $this->assertStringEqualsFile($file, $contents);
+    }
+
     public function testCreateFileDirectoryCreation()
     {
         $this->err->expects($this->never())

+ 1 - 1
tests/TestCase/TestSuite/IntegrationTestTraitTest.php

@@ -381,7 +381,7 @@ class IntegrationTestTraitTest extends TestCase
     public function testConfigApplication()
     {
         $this->expectException(\LogicException::class);
-        $this->expectExceptionMessage('Cannot load "TestApp\MissingApp" for use in integration');
+        $this->expectExceptionMessage('Cannot load `TestApp\MissingApp` for use in integration');
         $this->configApplication('TestApp\MissingApp', []);
         $this->get('/request_action/test_request_action');
     }

+ 23 - 6
tests/TestCase/TestSuite/TestCaseTest.php

@@ -16,12 +16,15 @@ declare(strict_types=1);
  */
 namespace Cake\Test\TestCase\TestSuite;
 
+use Cake\Core\Configure;
 use Cake\Datasource\ConnectionManager;
 use Cake\Event\Event;
 use Cake\Event\EventList;
 use Cake\Event\EventManager;
 use Cake\ORM\Entity;
 use Cake\ORM\Table;
+use Cake\Routing\Exception\MissingRouteException;
+use Cake\Routing\Router;
 use Cake\Test\Fixture\FixturizedTestCase;
 use Cake\TestSuite\Fixture\FixtureManager;
 use Cake\TestSuite\TestCase;
@@ -236,7 +239,6 @@ class TestCaseTest extends TestCase
     public function testAssertTextStartsWith()
     {
         $stringDirty = "some\nstring\r\nwith\rdifferent\nline endings!";
-        $stringClean = "some\nstring\nwith\ndifferent\nline endings!";
 
         $this->assertStringStartsWith("some\nstring", $stringDirty);
         $this->assertStringStartsNotWith("some\r\nstring\r\nwith", $stringDirty);
@@ -254,7 +256,6 @@ class TestCaseTest extends TestCase
     public function testAssertTextStartsNotWith()
     {
         $stringDirty = "some\nstring\r\nwith\rdifferent\nline endings!";
-        $stringClean = "some\nstring\nwith\ndifferent\nline endings!";
 
         $this->assertTextStartsNotWith("some\nstring\nwithout", $stringDirty);
     }
@@ -267,7 +268,6 @@ class TestCaseTest extends TestCase
     public function testAssertTextEndsWith()
     {
         $stringDirty = "some\nstring\r\nwith\rdifferent\nline endings!";
-        $stringClean = "some\nstring\nwith\ndifferent\nline endings!";
 
         $this->assertTextEndsWith("string\nwith\r\ndifferent\rline endings!", $stringDirty);
         $this->assertTextEndsWith("string\r\nwith\ndifferent\nline endings!", $stringDirty);
@@ -281,7 +281,6 @@ class TestCaseTest extends TestCase
     public function testAssertTextEndsNotWith()
     {
         $stringDirty = "some\nstring\r\nwith\rdifferent\nline endings!";
-        $stringClean = "some\nstring\nwith\ndifferent\nline endings!";
 
         $this->assertStringEndsNotWith("different\nline endings", $stringDirty);
         $this->assertTextEndsNotWith("different\rline endings", $stringDirty);
@@ -295,7 +294,6 @@ class TestCaseTest extends TestCase
     public function testAssertTextContains()
     {
         $stringDirty = "some\nstring\r\nwith\rdifferent\nline endings!";
-        $stringClean = "some\nstring\nwith\ndifferent\nline endings!";
 
         $this->assertStringContainsString('different', $stringDirty);
         $this->assertStringNotContainsString("different\rline", $stringDirty);
@@ -311,7 +309,6 @@ class TestCaseTest extends TestCase
     public function testAssertTextNotContains()
     {
         $stringDirty = "some\nstring\r\nwith\rdifferent\nline endings!";
-        $stringClean = "some\nstring\nwith\ndifferent\nline endings!";
 
         $this->assertTextNotContains("different\rlines", $stringDirty);
     }
@@ -468,4 +465,24 @@ class TestCaseTest extends TestCase
         $Tags = $this->getMockForModel('Tags', ['save']);
         $this->assertSame('tags', $Tags->getTable());
     }
+
+    /**
+     * Test loadRoutes() helper
+     *
+     * @return void
+     */
+    public function testLoadRoutes()
+    {
+        $url = ['controller' => 'Articles', 'action' => 'index'];
+        try {
+            Router::url($url);
+            $this->fail('Missing URL should throw an exception');
+        } catch (MissingRouteException $e) {
+        }
+        Configure::write('App.namespace', 'TestApp');
+        $this->loadRoutes();
+
+        $result = Router::url($url);
+        $this->assertSame('/app/articles', $result);
+    }
 }