diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4559e4bc8fd7..f64afb62a99a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -8,8 +8,8 @@ on: jobs: linux_tests: - runs-on: ubuntu-latest + services: mysql: image: mysql:5.7 @@ -40,7 +40,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, gd + extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, gd, redis, memcached tools: composer:v2 coverage: none @@ -50,6 +50,14 @@ jobs: - name: Setup problem matchers run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + - name: Set Minimum Guzzle Version + uses: nick-invision/retry@v1 + with: + timeout_minutes: 5 + max_attempts: 5 + command: composer require guzzlehttp/guzzle:^7.2 --no-interaction --no-update + if: matrix.php >= 8 + - name: Install dependencies uses: nick-invision/retry@v1 with: @@ -64,8 +72,8 @@ jobs: DB_USERNAME: root windows_tests: - runs-on: windows-latest + strategy: fail-fast: true matrix: @@ -87,13 +95,21 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - extensions: dom, curl, libxml, mbstring, zip, pdo, sqlite, pdo_sqlite, gd, pdo_mysql, fileinfo, ftp + extensions: dom, curl, libxml, mbstring, zip, pdo, sqlite, pdo_sqlite, gd, pdo_mysql, fileinfo, ftp, redis, memcached tools: composer:v2 coverage: none - name: Setup problem matchers run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + - name: Set Minimum Guzzle Version + uses: nick-invision/retry@v1 + with: + timeout_minutes: 5 + max_attempts: 5 + command: composer require guzzlehttp/guzzle:^7.2 --no-interaction --no-update + if: matrix.php >= 8 + - name: Install dependencies uses: nick-invision/retry@v1 with: diff --git a/CHANGELOG-6.x.md b/CHANGELOG-6.x.md index 06e4a83add64..ae564658b926 100644 --- a/CHANGELOG-6.x.md +++ b/CHANGELOG-6.x.md @@ -1,8 +1,56 @@ # Release Notes for 6.x -## [Unreleased](https://github.com/laravel/framework/compare/v6.19.1...6.x) +## [Unreleased](https://github.com/laravel/framework/compare/v6.20.5...6.x) +## [v6.20.5 (2020-11-24)](https://github.com/laravel/framework/compare/v6.20.4...v6.20.5) + +### Fixed +- Fixing BroadcastException message in PusherBroadcaster@broadcast ([#35290](https://github.com/laravel/framework/pull/35290)) +- Fixed generic DetectsLostConnection string ([#35323](https://github.com/laravel/framework/pull/35323)) + +### Changed +- Updated `aws/aws-sdk-php` suggest to `^3.155` ([#35267](https://github.com/laravel/framework/pull/35267)) + + +## [v6.20.4 (2020-11-17)](https://github.com/laravel/framework/compare/v6.20.3...v6.20.4) + +### Fixed +- Fixed pivot restoration ([#35218](https://github.com/laravel/framework/pull/35218)) + + +## [v6.20.3 (2020-11-10)](https://github.com/laravel/framework/compare/v6.20.2...v6.20.3) + +### Fixed +- Turn the eloquent collection into a base collection if mapWithKeys loses models ([#35129](https://github.com/laravel/framework/pull/35129)) + + +## [v6.20.2 (2020-10-29)](https://github.com/laravel/framework/compare/v6.20.1...v6.20.2) + +### Fixed +- [Add some fixes](https://github.com/laravel/framework/compare/v6.20.1...v6.20.2) + + +## [v6.20.1 (2020-10-29)](https://github.com/laravel/framework/compare/v6.20.0...v6.20.1) + +### Fixed +- Fixed alias usage in `Eloquent` ([6091048](https://github.com/laravel/framework/commit/609104806b8b639710268c75c22f43034c2b72db)) +- Fixed `Illuminate\Support\Reflector::isCallable()` ([a90f344](https://github.com/laravel/framework/commit/a90f344c66f0a5bb1d718f8bbd20c257d4de9e02)) + + +## [v6.20.0 (2020-10-28)](https://github.com/laravel/framework/compare/v6.19.1...v6.20.0) + +### Added +- Full PHP 8.0 Support ([#33388](https://github.com/laravel/framework/pull/33388)) +- Added `Illuminate\Support\Reflector::isCallable()` ([#34994](https://github.com/laravel/framework/pull/34994), [8c16891](https://github.com/laravel/framework/commit/8c16891c6e7a4738d63788f4447614056ab5136e), [31917ab](https://github.com/laravel/framework/commit/31917abcfa0db6ec6221bb07fc91b6e768ff5ec8), [11cfa4d](https://github.com/laravel/framework/commit/11cfa4d4c92bf2f023544d58d51b35c5d31dece0), [#34999](https://github.com/laravel/framework/pull/34999)) + +### Changed +- Bump minimum PHP version to v7.2.5 ([#34928](https://github.com/laravel/framework/pull/34928)) + +### Fixed +- Fixed ambigious column on many to many with select load ([5007986](https://github.com/laravel/framework/commit/500798623d100a9746b2931ae6191cb756521f05)) + + ## [v6.19.1 (2020-10-20)](https://github.com/laravel/framework/compare/v6.19.0...v6.19.1) ### Fixed diff --git a/CHANGELOG-7.x.md b/CHANGELOG-7.x.md index 2e01e8407b79..8f668e3793ae 100644 --- a/CHANGELOG-7.x.md +++ b/CHANGELOG-7.x.md @@ -1,8 +1,40 @@ # Release Notes for 7.x -## [Unreleased](https://github.com/laravel/framework/compare/v7.28.4...7.x) +## [Unreleased](https://github.com/laravel/framework/compare/v7.29.3...7.x) +## [v7.29.3 (2020-11-03)](https://github.com/laravel/framework/compare/v7.29.2...v7.29.3) + +### Fixed +- Added php 8 support for Illuminate Testing 7.x ([#35045](https://github.com/laravel/framework/pull/35045)) + + +## [v7.29.2 (2020-10-29)](https://github.com/laravel/framework/compare/v7.29.1...v7.29.2) + +### Fixed +- [Add some fixes](https://github.com/laravel/framework/compare/v7.29.1...v7.29.2) + + +## [v7.29.1 (2020-10-29)](https://github.com/laravel/framework/compare/v7.29.0...v7.29.1) + +### Fixed +- Fixed alias usage in `Eloquent` ([6091048](https://github.com/laravel/framework/commit/609104806b8b639710268c75c22f43034c2b72db)) +- Fixed `Illuminate\Support\Reflector::isCallable()` ([a90f344](https://github.com/laravel/framework/commit/a90f344c66f0a5bb1d718f8bbd20c257d4de9e02)) + + +## [v7.29.0 (2020-10-29)](https://github.com/laravel/framework/compare/v7.28.4...v7.29.0) + +### Added +- Full PHP 8.0 Support ([#34884](https://github.com/laravel/framework/pull/34884), [28bb76e](https://github.com/laravel/framework/commit/28bb76efbcfc5fee57307ffa062b67ff709240dc), [#33388](https://github.com/laravel/framework/pull/33388)) +- Added `Illuminate\Support\Reflector::isCallable()` ([#34994](https://github.com/laravel/framework/pull/34994), [8c16891](https://github.com/laravel/framework/commit/8c16891c6e7a4738d63788f4447614056ab5136e), [31917ab](https://github.com/laravel/framework/commit/31917abcfa0db6ec6221bb07fc91b6e768ff5ec8), [11cfa4d](https://github.com/laravel/framework/commit/11cfa4d4c92bf2f023544d58d51b35c5d31dece0), [#34999](https://github.com/laravel/framework/pull/34999)) + +### Changed +- Bump minimum PHP version to v7.2.5 ([#34928](https://github.com/laravel/framework/pull/34928)) + +### Fixed +- Fixed ambigious column on many to many with select load ([5007986](https://github.com/laravel/framework/commit/500798623d100a9746b2931ae6191cb756521f05)) + + ## [v7.28.4 (2020-10-06)](https://github.com/laravel/framework/compare/v7.28.3...v7.28.4) ### Fixed diff --git a/composer.json b/composer.json index 98b532f57bb8..dea51b9ab5f1 100644 --- a/composer.json +++ b/composer.json @@ -77,7 +77,7 @@ "illuminate/view": "self.version" }, "require-dev": { - "aws/aws-sdk-php": "^3.0", + "aws/aws-sdk-php": "^3.155", "doctrine/dbal": "^2.6", "filp/whoops": "^2.8", "guzzlehttp/guzzle": "^6.3.1|^7.0.1", @@ -125,7 +125,7 @@ "ext-pcntl": "Required to use all features of the queue worker.", "ext-posix": "Required to use all features of the queue worker.", "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0).", - "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.0).", + "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.155).", "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.6).", "filp/whoops": "Required for friendly error pages in development (^2.8).", "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", diff --git a/src/Illuminate/Broadcasting/Broadcasters/PusherBroadcaster.php b/src/Illuminate/Broadcasting/Broadcasters/PusherBroadcaster.php index 68daf9da4b26..c39abbd6f61b 100644 --- a/src/Illuminate/Broadcasting/Broadcasters/PusherBroadcaster.php +++ b/src/Illuminate/Broadcasting/Broadcasters/PusherBroadcaster.php @@ -120,7 +120,7 @@ public function broadcast(array $channels, $event, array $payload = []) throw new BroadcastException( ! empty($response['body']) - ? sprintf('Pusher error: %s.', $response['status']) + ? sprintf('Pusher error: %s.', $response['body']) : 'Failed to connect to Pusher.' ); } diff --git a/src/Illuminate/Database/DetectsLostConnections.php b/src/Illuminate/Database/DetectsLostConnections.php index 72132c164df7..36b46099983f 100644 --- a/src/Illuminate/Database/DetectsLostConnections.php +++ b/src/Illuminate/Database/DetectsLostConnections.php @@ -40,7 +40,7 @@ protected function causedByLostConnection(Throwable $e) 'Communication link failure', 'connection is no longer usable', 'Login timeout expired', - 'Connection refused', + 'SQLSTATE[HY000] [2002] Connection refused', 'running with the --read-only option so it cannot execute this statement', 'The connection is broken and recovery is not possible. The connection is marked by the client driver as unrecoverable. No attempt was made to restore the connection.', 'SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed: Try again', diff --git a/src/Illuminate/Database/Eloquent/Collection.php b/src/Illuminate/Database/Eloquent/Collection.php index c1683679c0a0..17199e8b3d7e 100755 --- a/src/Illuminate/Database/Eloquent/Collection.php +++ b/src/Illuminate/Database/Eloquent/Collection.php @@ -280,6 +280,23 @@ public function map(callable $callback) }) ? $result->toBase() : $result; } + /** + * Run an associative map over each of the items. + * + * The callback should return an associative array with a single key / value pair. + * + * @param callable $callback + * @return \Illuminate\Support\Collection|static + */ + public function mapWithKeys(callable $callback) + { + $result = parent::mapWithKeys($callback); + + return $result->contains(function ($item) { + return ! $item instanceof Model; + }) ? $result->toBase() : $result; + } + /** * Reload a fresh model instance from the database for all the entities. * diff --git a/src/Illuminate/Database/Eloquent/Relations/Concerns/AsPivot.php b/src/Illuminate/Database/Eloquent/Relations/Concerns/AsPivot.php index a6fdd5af80b9..d7de34e2c348 100644 --- a/src/Illuminate/Database/Eloquent/Relations/Concerns/AsPivot.php +++ b/src/Illuminate/Database/Eloquent/Relations/Concerns/AsPivot.php @@ -286,6 +286,8 @@ public function newQueryForRestoration($ids) */ protected function newQueryForCollectionRestoration(array $ids) { + $ids = array_values($ids); + if (! Str::contains($ids[0], ':')) { return parent::newQueryForRestoration($ids); } diff --git a/src/Illuminate/Database/Eloquent/Relations/MorphPivot.php b/src/Illuminate/Database/Eloquent/Relations/MorphPivot.php index 0db82ba101bc..68489265f838 100644 --- a/src/Illuminate/Database/Eloquent/Relations/MorphPivot.php +++ b/src/Illuminate/Database/Eloquent/Relations/MorphPivot.php @@ -139,6 +139,8 @@ public function newQueryForRestoration($ids) */ protected function newQueryForCollectionRestoration(array $ids) { + $ids = array_values($ids); + if (! Str::contains($ids[0], ':')) { return parent::newQueryForRestoration($ids); } diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index 7633b00d5b12..6ef4be78946e 100755 --- a/src/Illuminate/Foundation/Application.php +++ b/src/Illuminate/Foundation/Application.php @@ -33,7 +33,7 @@ class Application extends Container implements ApplicationContract, CachesConfig * * @var string */ - const VERSION = '7.29.3'; + const VERSION = '7.30.0'; /** * The base path for the Laravel installation. diff --git a/src/Illuminate/Foundation/Exceptions/Handler.php b/src/Illuminate/Foundation/Exceptions/Handler.php index fe71e42b095e..923e6c6d17bf 100644 --- a/src/Illuminate/Foundation/Exceptions/Handler.php +++ b/src/Illuminate/Foundation/Exceptions/Handler.php @@ -323,7 +323,7 @@ protected function prepareResponse($request, Throwable $e) */ protected function convertExceptionToResponse(Throwable $e) { - return SymfonyResponse::create( + return new SymfonyResponse( $this->renderExceptionContent($e), $this->isHttpException($e) ? $e->getStatusCode() : 500, $this->isHttpException($e) ? $e->getHeaders() : [] diff --git a/src/Illuminate/Mail/composer.json b/src/Illuminate/Mail/composer.json index e95e97a3456e..0eb541fac7e3 100755 --- a/src/Illuminate/Mail/composer.json +++ b/src/Illuminate/Mail/composer.json @@ -35,7 +35,7 @@ } }, "suggest": { - "aws/aws-sdk-php": "Required to use the SES mail driver (^3.0).", + "aws/aws-sdk-php": "Required to use the SES mail driver (^3.155).", "guzzlehttp/guzzle": "Required to use the Mailgun mail driver (^6.3.1|^7.0.1).", "wildbit/swiftmailer-postmark": "Required to use Postmark mail driver (^3.0)." }, diff --git a/src/Illuminate/Queue/composer.json b/src/Illuminate/Queue/composer.json index 5c0aff9301a0..1132d414583f 100644 --- a/src/Illuminate/Queue/composer.json +++ b/src/Illuminate/Queue/composer.json @@ -40,7 +40,7 @@ "suggest": { "ext-pcntl": "Required to use all features of the queue worker.", "ext-posix": "Required to use all features of the queue worker.", - "aws/aws-sdk-php": "Required to use the SQS queue driver and DynamoDb failed job storage (^3.0).", + "aws/aws-sdk-php": "Required to use the SQS queue driver and DynamoDb failed job storage (^3.155).", "illuminate/redis": "Required to use the Redis queue driver (^7.0).", "pda/pheanstalk": "Required to use the Beanstalk queue driver (^4.0)." }, diff --git a/src/Illuminate/Redis/Connectors/PhpRedisConnector.php b/src/Illuminate/Redis/Connectors/PhpRedisConnector.php index d944d069267f..ba14ad87a928 100644 --- a/src/Illuminate/Redis/Connectors/PhpRedisConnector.php +++ b/src/Illuminate/Redis/Connectors/PhpRedisConnector.php @@ -129,7 +129,9 @@ protected function establishConnection($client, array $config) } if (version_compare(phpversion('redis'), '5.3.0', '>=')) { - $parameters[] = Arr::get($config, 'context', []); + if (! is_null($context = Arr::get($config, 'context'))) { + $parameters[] = $context; + } } $client->{($persistent ? 'pconnect' : 'connect')}(...$parameters); @@ -157,7 +159,9 @@ protected function createRedisClusterInstance(array $servers, array $options) } if (version_compare(phpversion('redis'), '5.3.2', '>=')) { - $parameters[] = Arr::get($options, 'context'); + if (! is_null($context = Arr::get($options, 'context'))) { + $parameters[] = $context; + } } return tap(new RedisCluster(...$parameters), function ($client) use ($options) { diff --git a/src/Illuminate/Support/Facades/Request.php b/src/Illuminate/Support/Facades/Request.php index ca3fcaa6f61e..05496d9ccd5d 100755 --- a/src/Illuminate/Support/Facades/Request.php +++ b/src/Illuminate/Support/Facades/Request.php @@ -28,6 +28,8 @@ * @method static array only(array|mixed $keys) * @method static array segments() * @method static array toArray() + * @method static array validate(array $rules, ...$params) + * @method static array validateWithBag(string $errorBag, array $rules, ...$params) * @method static bool accepts(string|array $contentTypes) * @method static bool acceptsAnyContentType() * @method static bool acceptsHtml() @@ -43,6 +45,7 @@ * @method static bool hasCookie(string $key) * @method static bool hasFile(string $key) * @method static bool hasHeader(string $key) + * @method static bool hasValidSignature(bool $absolute = true) * @method static bool is(mixed ...$patterns) * @method static bool isJson() * @method static bool matchesType(string $actual, string $type) diff --git a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php index 948110a7fbe8..b3f242a68d29 100644 --- a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php +++ b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php @@ -1064,7 +1064,7 @@ public function validateLte($attribute, $value, $parameters) */ public function validateImage($attribute, $value) { - return $this->validateMimes($attribute, $value, ['jpeg', 'png', 'gif', 'bmp', 'svg', 'webp']); + return $this->validateMimes($attribute, $value, ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg', 'webp']); } /** diff --git a/tests/Database/DatabaseEloquentCollectionTest.php b/tests/Database/DatabaseEloquentCollectionTest.php index 4ab2a4d7e3b6..ce216d705317 100755 --- a/tests/Database/DatabaseEloquentCollectionTest.php +++ b/tests/Database/DatabaseEloquentCollectionTest.php @@ -230,6 +230,35 @@ public function testMappingToNonModelsReturnsABaseCollection() $this->assertEquals(BaseCollection::class, get_class($c)); } + public function testMapWithKeys() + { + $one = m::mock(Model::class); + $two = m::mock(Model::class); + + $c = new Collection([$one, $two]); + + $key = 0; + $cAfterMap = $c->mapWithKeys(function ($item) use (&$key) { + return [$key++ => $item]; + }); + + $this->assertEquals($c->all(), $cAfterMap->all()); + $this->assertInstanceOf(Collection::class, $cAfterMap); + } + + public function testMapWithKeysToNonModelsReturnsABaseCollection() + { + $one = m::mock(Model::class); + $two = m::mock(Model::class); + + $key = 0; + $c = (new Collection([$one, $two]))->mapWithKeys(function ($item) use (&$key) { + return [$key++ => 'not-a-model']; + }); + + $this->assertEquals(BaseCollection::class, get_class($c)); + } + public function testCollectionDiffsWithGivenCollection() { $one = m::mock(Model::class); diff --git a/tests/Validation/ValidationValidatorTest.php b/tests/Validation/ValidationValidatorTest.php index b79e14857e3f..8737f262b729 100755 --- a/tests/Validation/ValidationValidatorTest.php +++ b/tests/Validation/ValidationValidatorTest.php @@ -2783,6 +2783,12 @@ public function testValidateImage() $file7->expects($this->any())->method('getClientOriginalExtension')->willReturn('webp'); $v = new Validator($trans, ['x' => $file7], ['x' => 'Image']); $this->assertTrue($v->passes()); + + $file2 = $this->getMockBuilder(UploadedFile::class)->setMethods(['guessExtension', 'getClientOriginalExtension'])->setConstructorArgs($uploadedFile)->getMock(); + $file2->expects($this->any())->method('guessExtension')->willReturn('jpg'); + $file2->expects($this->any())->method('getClientOriginalExtension')->willReturn('jpg'); + $v = new Validator($trans, ['x' => $file2], ['x' => 'Image']); + $this->assertTrue($v->passes()); } public function testValidateImageDoesNotAllowPhpExtensionsOnImageMime()