From 2cd4fd8110865c4ea98a26e273c8da4a61bdf17e Mon Sep 17 00:00:00 2001 From: Patrick O'Meara Date: Thu, 14 Jan 2021 01:18:20 +1100 Subject: [PATCH 01/23] [8.x] Allow a specific seeder to be used in tests (#35864) * Allow a specific seeder to be used in tests * if $seeder is set within a test use it instead of the default. * Update RefreshDatabase.php Co-authored-by: Taylor Otwell --- .../Foundation/Testing/RefreshDatabase.php | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/Illuminate/Foundation/Testing/RefreshDatabase.php b/src/Illuminate/Foundation/Testing/RefreshDatabase.php index f62fad83c559..d66fd0f94911 100644 --- a/src/Illuminate/Foundation/Testing/RefreshDatabase.php +++ b/src/Illuminate/Foundation/Testing/RefreshDatabase.php @@ -79,11 +79,15 @@ protected function refreshTestDatabase() */ protected function migrateFreshUsing() { - return [ - '--drop-views' => $this->shouldDropViews(), - '--drop-types' => $this->shouldDropTypes(), - '--seed' => $this->shouldSeed(), - ]; + $seeder = $this->seeder(); + + return array_merge( + [ + '--drop-views' => $this->shouldDropViews(), + '--drop-types' => $this->shouldDropTypes(), + ], + $seeder ? ['--seeder' => $seeder] : ['--seed' => $this->shouldSeed()] + ); } /** @@ -157,4 +161,14 @@ protected function shouldSeed() { return property_exists($this, 'seed') ? $this->seed : false; } + + /** + * Determine the specific seeder class that should be used when refreshing the database. + * + * @return mixed + */ + protected function seeder() + { + return property_exists($this, 'seeder') ? $this->seeder : false; + } } From 8c6f18188a4d971312610315b7f1aa7b2261f170 Mon Sep 17 00:00:00 2001 From: Mohamed Said Date: Wed, 13 Jan 2021 16:48:18 +0200 Subject: [PATCH 02/23] add sole to the query builder --- .../Database/Concerns/BuildsQueries.php | 26 ++++++++++++++++++ .../MultipleRecordsFoundException.php | 10 +++++++ .../Database/NoRecordsFoundException.php | 10 +++++++ .../Integration/Database/QueryBuilderTest.php | 27 +++++++++++++++++++ 4 files changed, 73 insertions(+) create mode 100755 src/Illuminate/Database/MultipleRecordsFoundException.php create mode 100755 src/Illuminate/Database/NoRecordsFoundException.php diff --git a/src/Illuminate/Database/Concerns/BuildsQueries.php b/src/Illuminate/Database/Concerns/BuildsQueries.php index 6a39b4cb8fc4..f74782c16a4e 100644 --- a/src/Illuminate/Database/Concerns/BuildsQueries.php +++ b/src/Illuminate/Database/Concerns/BuildsQueries.php @@ -3,6 +3,8 @@ namespace Illuminate\Database\Concerns; use Illuminate\Container\Container; +use Illuminate\Database\MultipleRecordsFoundException; +use Illuminate\Database\NoRecordsFoundException; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Pagination\Paginator; @@ -147,6 +149,30 @@ public function first($columns = ['*']) return $this->take(1)->get($columns)->first(); } + /** + * Execute the query and get the first result if it's the sole. + * + * @param array|string $columns + * @return \Illuminate\Database\Eloquent\Model|object|static|null + * + * @throws \Illuminate\Database\NoRecordsFoundException + * @throws \Illuminate\Database\MultipleRecordsFoundException + */ + public function sole($columns = ['*']) + { + $result = $this->get($columns); + + if ($result->isEmpty()) { + throw new NoRecordsFoundException(); + } + + if ($result->count() > 1) { + throw new MultipleRecordsFoundException(); + } + + return $result->first(); + } + /** * Apply the callback's query changes if the given "value" is true. * diff --git a/src/Illuminate/Database/MultipleRecordsFoundException.php b/src/Illuminate/Database/MultipleRecordsFoundException.php new file mode 100755 index 000000000000..390976d8db9a --- /dev/null +++ b/src/Illuminate/Database/MultipleRecordsFoundException.php @@ -0,0 +1,10 @@ + '1', 'title' => 'Foo Post']; + + $this->assertEquals(1, DB::table('posts')->where('title', 'Foo Post')->sole()->id); + } + + public function testSoleFailsForMultipleRecords() + { + DB::table('posts')->insert([ + ['title' => 'Foo Post', 'content' => 'Lorem Ipsum.', 'created_at' => new Carbon('2017-11-12 13:14:15')], + ]); + + $this->expectException(MultipleRecordsFoundException::class); + + DB::table('posts')->where('title', 'Foo Post')->sole(); + } + + public function testSoleFailsIfNoRecords() + { + $this->expectException(NoRecordsFoundException::class); + + DB::table('posts')->where('title', 'Baz Post')->sole(); + } + public function testSelect() { $expected = ['id' => '1', 'title' => 'Foo Post']; From bcf818fa71eba69cc75e1de003a30ac058d860fa Mon Sep 17 00:00:00 2001 From: Mohamed Said Date: Wed, 13 Jan 2021 16:58:00 +0200 Subject: [PATCH 03/23] fix style --- src/Illuminate/Database/MultipleRecordsFoundException.php | 2 +- src/Illuminate/Database/NoRecordsFoundException.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/Database/MultipleRecordsFoundException.php b/src/Illuminate/Database/MultipleRecordsFoundException.php index 390976d8db9a..cccb7e4177bf 100755 --- a/src/Illuminate/Database/MultipleRecordsFoundException.php +++ b/src/Illuminate/Database/MultipleRecordsFoundException.php @@ -6,5 +6,5 @@ class MultipleRecordsFoundException extends RuntimeException { - + // } diff --git a/src/Illuminate/Database/NoRecordsFoundException.php b/src/Illuminate/Database/NoRecordsFoundException.php index 938d4c36293d..b45266c8e9bf 100755 --- a/src/Illuminate/Database/NoRecordsFoundException.php +++ b/src/Illuminate/Database/NoRecordsFoundException.php @@ -6,5 +6,5 @@ class NoRecordsFoundException extends RuntimeException { - + // } From b1fd05eaa3b7b59677fddd6b6caad407c6bbecce Mon Sep 17 00:00:00 2001 From: Mohamed Said Date: Wed, 13 Jan 2021 17:15:07 +0200 Subject: [PATCH 04/23] take 2 --- src/Illuminate/Database/Concerns/BuildsQueries.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Concerns/BuildsQueries.php b/src/Illuminate/Database/Concerns/BuildsQueries.php index f74782c16a4e..9aa590654b83 100644 --- a/src/Illuminate/Database/Concerns/BuildsQueries.php +++ b/src/Illuminate/Database/Concerns/BuildsQueries.php @@ -160,7 +160,7 @@ public function first($columns = ['*']) */ public function sole($columns = ['*']) { - $result = $this->get($columns); + $result = $this->take(2)->get($columns); if ($result->isEmpty()) { throw new NoRecordsFoundException(); From 32ec62102e93a1d9bb9b8f4f2f83a633a9255fb8 Mon Sep 17 00:00:00 2001 From: Joseph Silber Date: Wed, 13 Jan 2021 12:36:07 -0500 Subject: [PATCH 05/23] Add @JosephSilber as codeowner on Collections (#35872) --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000000..c3d39f873292 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +/src/Illuminate/Collections/ @JosephSilber From bb957035dda413a22791609724b9ded26feee6ed Mon Sep 17 00:00:00 2001 From: Joseph Silber Date: Wed, 13 Jan 2021 15:29:22 -0500 Subject: [PATCH 06/23] Add @JosephSilber as codeowner on Collections tests (#35873) --- .github/CODEOWNERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c3d39f873292..e89cb3511502 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1,4 @@ /src/Illuminate/Collections/ @JosephSilber +/tests/Support/SupportCollectionTest/ @JosephSilber +/tests/Support/SupportLazyCollectionTest/ @JosephSilber +/tests/Support/SupportLazyCollectionIsLazyTest/ @JosephSilber From 290ca48b2d2ed1eca9cf078038706b9683e0d4f9 Mon Sep 17 00:00:00 2001 From: Harry Gulliford Date: Thu, 14 Jan 2021 10:59:36 +1100 Subject: [PATCH 07/23] Update supported versions --- .github/SECURITY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/SECURITY.md b/.github/SECURITY.md index 444b8e623703..1ce441d0affb 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -6,6 +6,8 @@ Version | Security Fixes Until --- | --- +8 | September 8th, 2021 +7 | March 3rd, 2021 6 (LTS) | September 3rd, 2022 5.8 | February 26th, 2020 5.7 | September 4th, 2019 From 49ee16b9ee784d425205fa456b43581de7cf804a Mon Sep 17 00:00:00 2001 From: iamgergo Date: Thu, 14 Jan 2021 13:07:07 +0100 Subject: [PATCH 08/23] [8.x] Formatting some docblocks --- src/Illuminate/Collections/Collection.php | 2 +- src/Illuminate/Collections/LazyCollection.php | 2 +- src/Illuminate/Database/Eloquent/Relations/Relation.php | 2 +- src/Illuminate/Routing/Exceptions/UrlGenerationException.php | 2 +- src/Illuminate/Testing/AssertableJsonString.php | 3 +-- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Illuminate/Collections/Collection.php b/src/Illuminate/Collections/Collection.php index 6a8ab88818aa..f708a3ee28bd 100644 --- a/src/Illuminate/Collections/Collection.php +++ b/src/Illuminate/Collections/Collection.php @@ -888,7 +888,7 @@ public function reduce(callable $callback, $initial = null) * Reduce an associative collection to a single value. * * @param callable $callback - * @param mixed $initial + * @param mixed $initial * @return mixed */ public function reduceWithKeys(callable $callback, $initial = null) diff --git a/src/Illuminate/Collections/LazyCollection.php b/src/Illuminate/Collections/LazyCollection.php index ca51626b071e..c7995fb27e1b 100644 --- a/src/Illuminate/Collections/LazyCollection.php +++ b/src/Illuminate/Collections/LazyCollection.php @@ -849,7 +849,7 @@ public function reduce(callable $callback, $initial = null) * Reduce an associative collection to a single value. * * @param callable $callback - * @param mixed $initial + * @param mixed $initial * @return mixed */ public function reduceWithKeys(callable $callback, $initial = null) diff --git a/src/Illuminate/Database/Eloquent/Relations/Relation.php b/src/Illuminate/Database/Eloquent/Relations/Relation.php index 3fcb75e67ab5..2185ec641ac6 100755 --- a/src/Illuminate/Database/Eloquent/Relations/Relation.php +++ b/src/Illuminate/Database/Eloquent/Relations/Relation.php @@ -223,7 +223,7 @@ public function getRelationExistenceQuery(Builder $query, Builder $parentQuery, /** * Get a relationship join table hash. * - * @param bool $incrementJoinCount + * @param bool $incrementJoinCount * @return string */ public function getRelationCountHash($incrementJoinCount = true) diff --git a/src/Illuminate/Routing/Exceptions/UrlGenerationException.php b/src/Illuminate/Routing/Exceptions/UrlGenerationException.php index e0057c9d6bbf..eadda8010c0f 100644 --- a/src/Illuminate/Routing/Exceptions/UrlGenerationException.php +++ b/src/Illuminate/Routing/Exceptions/UrlGenerationException.php @@ -12,7 +12,7 @@ class UrlGenerationException extends Exception * Create a new exception for missing route parameters. * * @param \Illuminate\Routing\Route $route - * @param array $parameters + * @param array $parameters * @return static */ public static function forMissingParameters(Route $route, array $parameters = []) diff --git a/src/Illuminate/Testing/AssertableJsonString.php b/src/Illuminate/Testing/AssertableJsonString.php index 5a73afe50c7f..e36c84aa300d 100644 --- a/src/Illuminate/Testing/AssertableJsonString.php +++ b/src/Illuminate/Testing/AssertableJsonString.php @@ -276,8 +276,7 @@ public function assertSubset(array $data, $strict = false) /** * Reorder associative array keys to make it easy to compare arrays. * - * @param array $data - * + * @param array $data * @return array */ protected function reorderAssocKeys(array $data) From 83ec510eef7c4e40c6a4c776041e0a1d04ea1c9e Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Thu, 14 Jan 2021 08:30:21 -0600 Subject: [PATCH 09/23] [8.x] Fix extra space on blade class components that are inline (#35874) This fixes extra spacing before and after Blade class components. --- .../View/Compilers/BladeCompiler.php | 5 +- .../View/Compilers/ComponentTagCompiler.php | 6 +- tests/Integration/View/BladeTest.php | 10 ++- .../View/templates/components/link.blade.php | 3 + .../View/templates/uses-link.blade.php | 1 + .../Blade/BladeComponentTagCompilerTest.php | 74 +++++++++---------- 6 files changed, 56 insertions(+), 43 deletions(-) create mode 100644 tests/Integration/View/templates/components/link.blade.php create mode 100644 tests/Integration/View/templates/uses-link.blade.php diff --git a/src/Illuminate/View/Compilers/BladeCompiler.php b/src/Illuminate/View/Compilers/BladeCompiler.php index 4482036072fd..1d08d0c0821c 100644 --- a/src/Illuminate/View/Compilers/BladeCompiler.php +++ b/src/Illuminate/View/Compilers/BladeCompiler.php @@ -251,7 +251,10 @@ public function compileString($value) $result = $this->addFooters($result); } - return $result; + return str_replace( + ['##BEGIN-COMPONENT-CLASS##', '##END-COMPONENT-CLASS##'], + '', + $result); } /** diff --git a/src/Illuminate/View/Compilers/ComponentTagCompiler.php b/src/Illuminate/View/Compilers/ComponentTagCompiler.php index b7b5300535b6..9e079ac8a07c 100644 --- a/src/Illuminate/View/Compilers/ComponentTagCompiler.php +++ b/src/Illuminate/View/Compilers/ComponentTagCompiler.php @@ -193,7 +193,7 @@ protected function compileSelfClosingTags(string $value) $attributes = $this->getAttributesFromAttributeString($matches['attributes']); - return $this->componentString($matches[1], $attributes)."\n@endcomponentClass "; + return $this->componentString($matches[1], $attributes)."\n@endComponentClass##END-COMPONENT-CLASS##"; }, $value); } @@ -230,7 +230,7 @@ protected function componentString(string $component, array $attributes) $parameters = $data->all(); } - return " @component('{$class}', '{$component}', [".$this->attributesToString($parameters, $escapeBound = false).']) + return "##BEGIN-COMPONENT-CLASS##@component('{$class}', '{$component}', [".$this->attributesToString($parameters, $escapeBound = false).']) withAttributes(['.$this->attributesToString($attributes->all(), $escapeAttributes = $class !== DynamicComponent::class).']); ?>'; } @@ -384,7 +384,7 @@ public function partitionDataAndAttributes($class, array $attributes) */ protected function compileClosingTags(string $value) { - return preg_replace("/<\/\s*x[-\:][\w\-\:\.]*\s*>/", ' @endcomponentClass ', $value); + return preg_replace("/<\/\s*x[-\:][\w\-\:\.]*\s*>/", ' @endComponentClass##END-COMPONENT-CLASS##', $value); } /** diff --git a/tests/Integration/View/BladeTest.php b/tests/Integration/View/BladeTest.php index a26460ba90ec..864a041f5d21 100644 --- a/tests/Integration/View/BladeTest.php +++ b/tests/Integration/View/BladeTest.php @@ -42,12 +42,18 @@ public function test_rendering_the_same_dynamic_component_with_different_attribu $this->assertSame(' Hello Taylor - - + Hello Samuel ', trim($view)); } + public function test_inline_link_type_attributes_dont_add_extra_spacing_at_end() + { + $view = View::make('uses-link')->render(); + + $this->assertSame('This is a sentence with a link.', trim($view)); + } + public function test_appendable_attributes() { $view = View::make('uses-appendable-panel', ['name' => 'Taylor', 'withInjectedValue' => true])->render(); diff --git a/tests/Integration/View/templates/components/link.blade.php b/tests/Integration/View/templates/components/link.blade.php new file mode 100644 index 000000000000..74b8835393b6 --- /dev/null +++ b/tests/Integration/View/templates/components/link.blade.php @@ -0,0 +1,3 @@ +@props(['href']) + +{{ $slot }} \ No newline at end of file diff --git a/tests/Integration/View/templates/uses-link.blade.php b/tests/Integration/View/templates/uses-link.blade.php new file mode 100644 index 000000000000..53a67cf64e30 --- /dev/null +++ b/tests/Integration/View/templates/uses-link.blade.php @@ -0,0 +1 @@ +This is a sentence with a link. \ No newline at end of file diff --git a/tests/View/Blade/BladeComponentTagCompilerTest.php b/tests/View/Blade/BladeComponentTagCompilerTest.php index b84030c13d2b..c9b89df6096e 100644 --- a/tests/View/Blade/BladeComponentTagCompilerTest.php +++ b/tests/View/Blade/BladeComponentTagCompilerTest.php @@ -40,69 +40,69 @@ public function testBasicComponentParsing() $result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('
'); - $this->assertSame("
@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', []) + $this->assertSame("
##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', []) withAttributes(['type' => 'foo','limit' => '5','@click' => 'foo','wire:click' => 'changePlan(\''.e(\$plan).'\')','required' => true]); ?>\n". -"@endcomponentClass @component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', []) +"@endComponentClass##END-COMPONENT-CLASS####BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', []) withAttributes([]); ?>\n". -'@endcomponentClass
', trim($result)); +'@endComponentClass##END-COMPONENT-CLASS##
', trim($result)); } public function testBasicComponentWithEmptyAttributesParsing() { $result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('
'); - $this->assertSame("
@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', []) + $this->assertSame("
##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', []) withAttributes(['type' => '','limit' => '','@click' => '','required' => true]); ?>\n". -'@endcomponentClass
', trim($result)); +'@endComponentClass##END-COMPONENT-CLASS##
', trim($result)); } public function testDataCamelCasing() { $result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags(''); - $this->assertSame("@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', ['userId' => '1']) -withAttributes([]); ?> @endcomponentClass", trim($result)); + $this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', ['userId' => '1']) +withAttributes([]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result)); } public function testColonData() { $result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags(''); - $this->assertSame("@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', ['userId' => 1]) -withAttributes([]); ?> @endcomponentClass", trim($result)); + $this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', ['userId' => 1]) +withAttributes([]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result)); } public function testColonAttributesIsEscapedIfStrings() { $result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags(''); - $this->assertSame("@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', []) -withAttributes(['src' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute('foo')]); ?> @endcomponentClass", trim($result)); + $this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', []) +withAttributes(['src' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute('foo')]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result)); } public function testColonNestedComponentParsing() { $result = $this->compiler(['foo:alert' => TestAlertComponent::class])->compileTags(''); - $this->assertSame("@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'foo:alert', []) -withAttributes([]); ?> @endcomponentClass", trim($result)); + $this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'foo:alert', []) +withAttributes([]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result)); } public function testColonStartingNestedComponentParsing() { $result = $this->compiler(['foo:alert' => TestAlertComponent::class])->compileTags(''); - $this->assertSame("@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'foo:alert', []) -withAttributes([]); ?> @endcomponentClass", trim($result)); + $this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'foo:alert', []) +withAttributes([]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result)); } public function testSelfClosingComponentsCanBeCompiled() { $result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('
'); - $this->assertSame("
@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', []) + $this->assertSame("
##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', []) withAttributes([]); ?>\n". -'@endcomponentClass
', trim($result)); +'@endComponentClass##END-COMPONENT-CLASS##
', trim($result)); } public function testClassNamesCanBeGuessed() @@ -139,18 +139,18 @@ public function testComponentsCanBeCompiledWithHyphenAttributes() $result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags(''); - $this->assertSame("@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', []) + $this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', []) withAttributes(['class' => 'bar','wire:model' => 'foo','x-on:click' => 'bar','@click' => 'baz']); ?>\n". -'@endcomponentClass', trim($result)); +'@endComponentClass##END-COMPONENT-CLASS##', trim($result)); } public function testSelfClosingComponentsCanBeCompiledWithDataAndAttributes() { $result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags(''); - $this->assertSame("@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', ['title' => 'foo']) + $this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', ['title' => 'foo']) withAttributes(['class' => 'bar','wire:model' => 'foo']); ?>\n". -'@endcomponentClass', trim($result)); +'@endComponentClass##END-COMPONENT-CLASS##', trim($result)); } public function testComponentCanReceiveAttributeBag() @@ -158,8 +158,8 @@ public function testComponentCanReceiveAttributeBag() $this->mockViewFactory(); $result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags(''); - $this->assertSame("@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', []) -withAttributes(['class' => 'bar','attributes' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute(\$attributes),'wire:model' => 'foo']); ?> @endcomponentClass", trim($result)); + $this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', []) +withAttributes(['class' => 'bar','attributes' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute(\$attributes),'wire:model' => 'foo']); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result)); } public function testSelfClosingComponentCanReceiveAttributeBag() @@ -168,35 +168,35 @@ public function testSelfClosingComponentCanReceiveAttributeBag() $result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('
merge([\'class\' => \'test\']) }} wire:model="foo" />
'); - $this->assertSame("
@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', ['title' => 'foo']) + $this->assertSame("
##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', ['title' => 'foo']) withAttributes(['class' => 'bar','attributes' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute(\$attributes->merge(['class' => 'test'])),'wire:model' => 'foo']); ?>\n". - '@endcomponentClass
', trim($result)); + '@endComponentClass##END-COMPONENT-CLASS##
', trim($result)); } public function testComponentsCanHaveAttachedWord() { $result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags('Words'); - $this->assertSame("@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', []) -withAttributes([]); ?> @endcomponentClass Words", trim($result)); + $this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', []) +withAttributes([]); ?> @endComponentClass##END-COMPONENT-CLASS##Words", trim($result)); } public function testSelfClosingComponentsCanHaveAttachedWord() { $result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags('Words'); - $this->assertSame("@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', []) + $this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', []) withAttributes([]); ?>\n". -'@endcomponentClass Words', trim($result)); +'@endComponentClass##END-COMPONENT-CLASS##Words', trim($result)); } public function testSelfClosingComponentsCanBeCompiledWithBoundData() { $result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags(''); - $this->assertSame("@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', ['title' => \$title]) + $this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', ['title' => \$title]) withAttributes(['class' => 'bar']); ?>\n". -'@endcomponentClass', trim($result)); +'@endComponentClass##END-COMPONENT-CLASS##', trim($result)); } public function testPairedComponentTags() @@ -204,9 +204,9 @@ public function testPairedComponentTags() $result = $this->compiler(['alert' => TestAlertComponent::class])->compileTags(' '); - $this->assertSame("@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', []) + $this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestAlertComponent', 'alert', []) withAttributes([]); ?> - @endcomponentClass", trim($result)); + @endComponentClass##END-COMPONENT-CLASS##", trim($result)); } public function testClasslessComponents() @@ -220,9 +220,9 @@ public function testClasslessComponents() $result = $this->compiler()->compileTags(''); - $this->assertSame("@component('Illuminate\View\AnonymousComponent', 'anonymous-component', ['view' => 'components.anonymous-component','data' => ['name' => 'Taylor','age' => 31,'wire:model' => 'foo']]) + $this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\View\AnonymousComponent', 'anonymous-component', ['view' => 'components.anonymous-component','data' => ['name' => 'Taylor','age' => 31,'wire:model' => 'foo']]) withAttributes(['name' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute('Taylor'),'age' => 31,'wire:model' => 'foo']); ?>\n". -'@endcomponentClass', trim($result)); +'@endComponentClass##END-COMPONENT-CLASS##', trim($result)); } public function testPackagesClasslessComponents() @@ -236,9 +236,9 @@ public function testPackagesClasslessComponents() $result = $this->compiler()->compileTags(''); - $this->assertSame("@component('Illuminate\View\AnonymousComponent', 'package::anonymous-component', ['view' => 'package::components.anonymous-component','data' => ['name' => 'Taylor','age' => 31,'wire:model' => 'foo']]) + $this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\View\AnonymousComponent', 'package::anonymous-component', ['view' => 'package::components.anonymous-component','data' => ['name' => 'Taylor','age' => 31,'wire:model' => 'foo']]) withAttributes(['name' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute('Taylor'),'age' => 31,'wire:model' => 'foo']); ?>\n". -'@endcomponentClass', trim($result)); +'@endComponentClass##END-COMPONENT-CLASS##', trim($result)); } public function testAttributeSanitization() From 7d56eff3136a1d22e3ed3a0bea0dd5ea2867812e Mon Sep 17 00:00:00 2001 From: Sjors Ottjes Date: Thu, 14 Jan 2021 15:47:18 +0100 Subject: [PATCH 10/23] add default parameter to throw_if / throw_unless (#35890) --- src/Illuminate/Support/helpers.php | 16 ++++++-- tests/Support/SupportHelpersTest.php | 56 +++++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/src/Illuminate/Support/helpers.php b/src/Illuminate/Support/helpers.php index f44371bb469e..bf110f8918b4 100755 --- a/src/Illuminate/Support/helpers.php +++ b/src/Illuminate/Support/helpers.php @@ -277,10 +277,14 @@ function tap($value, $callback = null) * * @throws \Throwable */ - function throw_if($condition, $exception, ...$parameters) + function throw_if($condition, $exception = 'RuntimeException', ...$parameters) { if ($condition) { - throw (is_string($exception) ? new $exception(...$parameters) : $exception); + if (is_string($exception) && class_exists($exception)) { + $exception = new $exception(...$parameters); + } + + throw is_string($exception) ? new RuntimeException($exception) : $exception; } return $condition; @@ -298,10 +302,14 @@ function throw_if($condition, $exception, ...$parameters) * * @throws \Throwable */ - function throw_unless($condition, $exception, ...$parameters) + function throw_unless($condition, $exception = 'RuntimeException', ...$parameters) { if (! $condition) { - throw (is_string($exception) ? new $exception(...$parameters) : $exception); + if (is_string($exception) && class_exists($exception)) { + $exception = new $exception(...$parameters); + } + + throw is_string($exception) ? new RuntimeException($exception) : $exception; } return $condition; diff --git a/tests/Support/SupportHelpersTest.php b/tests/Support/SupportHelpersTest.php index bb3e5ead59ce..af7de6b40f56 100755 --- a/tests/Support/SupportHelpersTest.php +++ b/tests/Support/SupportHelpersTest.php @@ -6,6 +6,7 @@ use Illuminate\Contracts\Support\Htmlable; use Illuminate\Support\Env; use Illuminate\Support\Optional; +use LogicException; use Mockery as m; use PHPUnit\Framework\TestCase; use RuntimeException; @@ -362,10 +363,63 @@ public function testTap() } public function testThrow() + { + $this->expectException(LogicException::class); + + throw_if(true, new LogicException); + } + + public function testThrowDefaultException() + { + $this->expectException(RuntimeException::class); + + throw_if(true); + } + + public function testThrowExceptionWithMessage() { $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('test'); + + throw_if(true, 'test'); + } + + public function testThrowExceptionAsStringWithMessage() + { + $this->expectException(LogicException::class); + $this->expectExceptionMessage('test'); + + throw_if(true, LogicException::class, 'test'); + } + + public function testThrowUnless() + { + $this->expectException(LogicException::class); + + throw_unless(false, new LogicException); + } + + public function testThrowUnlessDefaultException() + { + $this->expectException(RuntimeException::class); + + throw_unless(false); + } + + public function testThrowUnlessExceptionWithMessage() + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('test'); + + throw_unless(false, 'test'); + } + + public function testThrowUnlessExceptionAsStringWithMessage() + { + $this->expectException(LogicException::class); + $this->expectExceptionMessage('test'); - throw_if(true, new RuntimeException); + throw_unless(false, LogicException::class, 'test'); } public function testThrowReturnIfNotThrown() From 29c7dae9b32af2abffa7489f4758fd67905683c3 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Thu, 14 Jan 2021 15:27:12 -0600 Subject: [PATCH 11/23] rename file --- src/Illuminate/Database/Concerns/BuildsQueries.php | 10 +++++----- ...FoundException.php => RecordsNotFoundException.php} | 2 +- tests/Integration/Database/QueryBuilderTest.php | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) rename src/Illuminate/Database/{NoRecordsFoundException.php => RecordsNotFoundException.php} (56%) diff --git a/src/Illuminate/Database/Concerns/BuildsQueries.php b/src/Illuminate/Database/Concerns/BuildsQueries.php index 9aa590654b83..38b04e8bcdcb 100644 --- a/src/Illuminate/Database/Concerns/BuildsQueries.php +++ b/src/Illuminate/Database/Concerns/BuildsQueries.php @@ -4,7 +4,7 @@ use Illuminate\Container\Container; use Illuminate\Database\MultipleRecordsFoundException; -use Illuminate\Database\NoRecordsFoundException; +use Illuminate\Database\RecordsNotFoundException; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Pagination\Paginator; @@ -150,12 +150,12 @@ public function first($columns = ['*']) } /** - * Execute the query and get the first result if it's the sole. + * Execute the query and get the first result if it's the sole matching record. * * @param array|string $columns * @return \Illuminate\Database\Eloquent\Model|object|static|null * - * @throws \Illuminate\Database\NoRecordsFoundException + * @throws \Illuminate\Database\RecordsNotFoundException * @throws \Illuminate\Database\MultipleRecordsFoundException */ public function sole($columns = ['*']) @@ -163,11 +163,11 @@ public function sole($columns = ['*']) $result = $this->take(2)->get($columns); if ($result->isEmpty()) { - throw new NoRecordsFoundException(); + throw new RecordsNotFoundException; } if ($result->count() > 1) { - throw new MultipleRecordsFoundException(); + throw new MultipleRecordsFoundException; } return $result->first(); diff --git a/src/Illuminate/Database/NoRecordsFoundException.php b/src/Illuminate/Database/RecordsNotFoundException.php similarity index 56% rename from src/Illuminate/Database/NoRecordsFoundException.php rename to src/Illuminate/Database/RecordsNotFoundException.php index b45266c8e9bf..3e0d9557581d 100755 --- a/src/Illuminate/Database/NoRecordsFoundException.php +++ b/src/Illuminate/Database/RecordsNotFoundException.php @@ -4,7 +4,7 @@ use RuntimeException; -class NoRecordsFoundException extends RuntimeException +class RecordsNotFoundException extends RuntimeException { // } diff --git a/tests/Integration/Database/QueryBuilderTest.php b/tests/Integration/Database/QueryBuilderTest.php index 0c7df7bbb124..675f30561fae 100644 --- a/tests/Integration/Database/QueryBuilderTest.php +++ b/tests/Integration/Database/QueryBuilderTest.php @@ -4,7 +4,7 @@ use Illuminate\Contracts\Pagination\LengthAwarePaginator; use Illuminate\Database\MultipleRecordsFoundException; -use Illuminate\Database\NoRecordsFoundException; +use Illuminate\Database\RecordsNotFoundException; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\DB; @@ -52,7 +52,7 @@ public function testSoleFailsForMultipleRecords() public function testSoleFailsIfNoRecords() { - $this->expectException(NoRecordsFoundException::class); + $this->expectException(RecordsNotFoundException::class); DB::table('posts')->where('title', 'Baz Post')->sole(); } From f3d4dcb21dc66824611fdde95c8075b694825bf5 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Fri, 15 Jan 2021 07:23:12 -0600 Subject: [PATCH 12/23] fix serialization of rate limited middleware --- .../Queue/Middleware/RateLimited.php | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/Illuminate/Queue/Middleware/RateLimited.php b/src/Illuminate/Queue/Middleware/RateLimited.php index efb0f60841f2..f7a8d6c08105 100644 --- a/src/Illuminate/Queue/Middleware/RateLimited.php +++ b/src/Illuminate/Queue/Middleware/RateLimited.php @@ -120,4 +120,31 @@ protected function getTimeUntilNextRetry($key) { return $this->limiter->availableIn($key) + 3; } + + /** + * Prepare the object for serialization. + * + * @return array + */ + public function __serialize() + { + return [ + 'limiterName' => $this->limiterName, + 'shouldRelease' => $this->shouldRelease, + ]; + } + + /** + * Prepare the object after unserialization. + * + * @param array $data + * @return void + */ + public function __unserialize(array $data) + { + $this->limiter = Container::getInstance()->make(RateLimiter::class); + + $this->limitedName = $data['limiterName']; + $this->shouldRelease = $data['shouldRelease']; + } } From ef7171e679497685131392cb1b200955092b053c Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Fri, 15 Jan 2021 21:31:43 +0800 Subject: [PATCH 13/23] Internally don't report exceptions from DB::where()->sole() (#35908) Signed-off-by: Mior Muhammad Zaki --- src/Illuminate/Foundation/Exceptions/Handler.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Illuminate/Foundation/Exceptions/Handler.php b/src/Illuminate/Foundation/Exceptions/Handler.php index 924046b8b340..c73130cb137e 100644 --- a/src/Illuminate/Foundation/Exceptions/Handler.php +++ b/src/Illuminate/Foundation/Exceptions/Handler.php @@ -11,6 +11,8 @@ use Illuminate\Contracts\Debug\ExceptionHandler as ExceptionHandlerContract; use Illuminate\Contracts\Support\Responsable; use Illuminate\Database\Eloquent\ModelNotFoundException; +use Illuminate\Database\MultipleRecordsFoundException; +use Illuminate\Database\RecordsNotFoundException; use Illuminate\Http\Exceptions\HttpResponseException; use Illuminate\Http\JsonResponse; use Illuminate\Http\RedirectResponse; @@ -89,6 +91,8 @@ class Handler implements ExceptionHandlerContract HttpException::class, HttpResponseException::class, ModelNotFoundException::class, + MultipleRecordsFoundException::class, + RecordsNotFoundException::class, SuspiciousOperationException::class, TokenMismatchException::class, ValidationException::class, From ab79d0cc600b44a2a6e89a7a0ca521732b749838 Mon Sep 17 00:00:00 2001 From: Rodrigo Pedra Brum Date: Fri, 15 Jan 2021 10:33:06 -0300 Subject: [PATCH 14/23] [8.x] Throw ModelNotFoundException for sole in Eloquent (#35902) * throw ModelNotFoundException for sole in Eloquent * extend from RecordsNotFoundException --- src/Illuminate/Database/Eloquent/Builder.php | 24 +++++++++++- .../Eloquent/ModelNotFoundException.php | 4 +- .../Database/EloquentWhereTest.php | 39 +++++++++++++++++++ 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Builder.php b/src/Illuminate/Database/Eloquent/Builder.php index d3f1f96a8c13..aa579259c1d5 100755 --- a/src/Illuminate/Database/Eloquent/Builder.php +++ b/src/Illuminate/Database/Eloquent/Builder.php @@ -11,6 +11,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Database\Query\Builder as QueryBuilder; +use Illuminate\Database\RecordsNotFoundException; use Illuminate\Pagination\Paginator; use Illuminate\Support\Arr; use Illuminate\Support\Str; @@ -25,7 +26,10 @@ */ class Builder { - use BuildsQueries, Concerns\QueriesRelationships, ExplainsQueries, ForwardsCalls; + use Concerns\QueriesRelationships, ExplainsQueries, ForwardsCalls; + use BuildsQueries { + sole as baseSole; + } /** * The base query builder instance. @@ -504,6 +508,24 @@ public function firstOr($columns = ['*'], Closure $callback = null) return $callback(); } + /** + * Execute the query and get the first result if it's the sole matching record. + * + * @param array|string $columns + * @return \Illuminate\Database\Eloquent\Model + * + * @throws \Illuminate\Database\Eloquent\ModelNotFoundException + * @throws \Illuminate\Database\MultipleRecordsFoundException + */ + public function sole($columns = ['*']) + { + try { + return $this->baseSole($columns); + } catch (RecordsNotFoundException $exception) { + throw new ModelNotFoundException($this->model); + } + } + /** * Get a single column's value from the first result of a query. * diff --git a/src/Illuminate/Database/Eloquent/ModelNotFoundException.php b/src/Illuminate/Database/Eloquent/ModelNotFoundException.php index 2795b934bb74..c35598bdbf46 100755 --- a/src/Illuminate/Database/Eloquent/ModelNotFoundException.php +++ b/src/Illuminate/Database/Eloquent/ModelNotFoundException.php @@ -2,10 +2,10 @@ namespace Illuminate\Database\Eloquent; +use Illuminate\Database\RecordsNotFoundException; use Illuminate\Support\Arr; -use RuntimeException; -class ModelNotFoundException extends RuntimeException +class ModelNotFoundException extends RecordsNotFoundException { /** * Name of the affected Eloquent model. diff --git a/tests/Integration/Database/EloquentWhereTest.php b/tests/Integration/Database/EloquentWhereTest.php index c7fcc470e6f4..a400d7f76305 100644 --- a/tests/Integration/Database/EloquentWhereTest.php +++ b/tests/Integration/Database/EloquentWhereTest.php @@ -3,6 +3,8 @@ namespace Illuminate\Tests\Integration\Database; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\ModelNotFoundException; +use Illuminate\Database\MultipleRecordsFoundException; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; @@ -91,6 +93,43 @@ public function testFirstWhere() UserWhereTest::firstWhere(['name' => 'wrong-name', 'email' => 'test-email1'], null, null, 'or')) ); } + + public function testSole() + { + $expected = UserWhereTest::create([ + 'name' => 'test-name', + 'email' => 'test-email', + 'address' => 'test-address', + ]); + + $this->assertTrue($expected->is(UserWhereTest::where('name', 'test-name')->sole())); + } + + public function testSoleFailsForMultipleRecords() + { + UserWhereTest::create([ + 'name' => 'test-name', + 'email' => 'test-email', + 'address' => 'test-address', + ]); + + UserWhereTest::create([ + 'name' => 'test-name', + 'email' => 'other-email', + 'address' => 'other-address', + ]); + + $this->expectException(MultipleRecordsFoundException::class); + + UserWhereTest::where('name', 'test-name')->sole(); + } + + public function testSoleFailsIfNoRecords() + { + $this->expectException(ModelNotFoundException::class); + + UserWhereTest::where('name', 'test-name')->sole(); + } } class UserWhereTest extends Model From e1d3158d162c35d4b8e7b65840f9ac347199be63 Mon Sep 17 00:00:00 2001 From: Mo Khosh Date: Fri, 15 Jan 2021 17:21:46 +0330 Subject: [PATCH 15/23] [8.x] Pass $key to closure in Collection and LazyCollection's reduce method as well (#35878) * add reduce with keys to collections * add reduce with keys to lazy collections * add test for reduce with keys * fix style * merge reduceWithKeys into the existing reduce method * remove reduce and reduceWithKeys from Collection * remove reduce and reduceWithKeys from LazyCollection * add reduce and reduceWithKeys to EnumeratesValues * add test for reduce with keys and reduceWithKeys --- src/Illuminate/Collections/Collection.php | 30 ---------------- src/Illuminate/Collections/LazyCollection.php | 36 ------------------- .../Collections/Traits/EnumeratesValues.php | 36 +++++++++++++++++++ tests/Support/SupportCollectionTest.php | 8 +++++ 4 files changed, 44 insertions(+), 66 deletions(-) diff --git a/src/Illuminate/Collections/Collection.php b/src/Illuminate/Collections/Collection.php index f708a3ee28bd..e4549d03ed11 100644 --- a/src/Illuminate/Collections/Collection.php +++ b/src/Illuminate/Collections/Collection.php @@ -872,36 +872,6 @@ public function random($number = null) return new static(Arr::random($this->items, $number)); } - /** - * Reduce the collection to a single value. - * - * @param callable $callback - * @param mixed $initial - * @return mixed - */ - public function reduce(callable $callback, $initial = null) - { - return array_reduce($this->items, $callback, $initial); - } - - /** - * Reduce an associative collection to a single value. - * - * @param callable $callback - * @param mixed $initial - * @return mixed - */ - public function reduceWithKeys(callable $callback, $initial = null) - { - $result = $initial; - - foreach ($this->items as $key => $value) { - $result = $callback($result, $value, $key); - } - - return $result; - } - /** * Replace the collection items with the given items. * diff --git a/src/Illuminate/Collections/LazyCollection.php b/src/Illuminate/Collections/LazyCollection.php index c7995fb27e1b..650213133ced 100644 --- a/src/Illuminate/Collections/LazyCollection.php +++ b/src/Illuminate/Collections/LazyCollection.php @@ -827,42 +827,6 @@ public function random($number = null) return is_null($number) ? $result : new static($result); } - /** - * Reduce the collection to a single value. - * - * @param callable $callback - * @param mixed $initial - * @return mixed - */ - public function reduce(callable $callback, $initial = null) - { - $result = $initial; - - foreach ($this as $value) { - $result = $callback($result, $value); - } - - return $result; - } - - /** - * Reduce an associative collection to a single value. - * - * @param callable $callback - * @param mixed $initial - * @return mixed - */ - public function reduceWithKeys(callable $callback, $initial = null) - { - $result = $initial; - - foreach ($this as $key => $value) { - $result = $callback($result, $value, $key); - } - - return $result; - } - /** * Replace the collection items with the given items. * diff --git a/src/Illuminate/Collections/Traits/EnumeratesValues.php b/src/Illuminate/Collections/Traits/EnumeratesValues.php index 3355a9b2da29..0c0c7ce3c3ab 100644 --- a/src/Illuminate/Collections/Traits/EnumeratesValues.php +++ b/src/Illuminate/Collections/Traits/EnumeratesValues.php @@ -716,6 +716,42 @@ public function tap(callable $callback) return $this; } + /** + * Reduce the collection to a single value. + * + * @param callable $callback + * @param mixed $initial + * @return mixed + */ + public function reduce(callable $callback, $initial = null) + { + $result = $initial; + + foreach ($this as $key => $value) { + $result = $callback($result, $value, $key); + } + + return $result; + } + + /** + * Reduce an associative collection to a single value. + * + * @param callable $callback + * @param mixed $initial + * @return mixed + */ + public function reduceWithKeys(callable $callback, $initial = null) + { + $result = $initial; + + foreach ($this as $key => $value) { + $result = $callback($result, $value, $key); + } + + return $result; + } + /** * Create a collection of all elements that do not pass a given truth test. * diff --git a/tests/Support/SupportCollectionTest.php b/tests/Support/SupportCollectionTest.php index b622884fe6c1..1902589e181e 100755 --- a/tests/Support/SupportCollectionTest.php +++ b/tests/Support/SupportCollectionTest.php @@ -3590,6 +3590,14 @@ public function testReduce($collection) $this->assertEquals(6, $data->reduce(function ($carry, $element) { return $carry += $element; })); + + $data = new $collection([ + 'foo' => 'bar', + 'baz' => 'qux', + ]); + $this->assertEquals('foobarbazqux', $data->reduce(function ($carry, $element, $key) { + return $carry .= $key.$element; + })); } /** From f646f8a8c594e83217079763b8ac20c260828da4 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Fri, 15 Jan 2021 07:52:20 -0600 Subject: [PATCH 16/23] Apply fixes from StyleCI (#35909) --- tests/Support/SupportCollectionTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Support/SupportCollectionTest.php b/tests/Support/SupportCollectionTest.php index 1902589e181e..2dfd503656ca 100755 --- a/tests/Support/SupportCollectionTest.php +++ b/tests/Support/SupportCollectionTest.php @@ -3590,7 +3590,7 @@ public function testReduce($collection) $this->assertEquals(6, $data->reduce(function ($carry, $element) { return $carry += $element; })); - + $data = new $collection([ 'foo' => 'bar', 'baz' => 'qux', From 7132ff5d0307828173296b31953d195b517eb789 Mon Sep 17 00:00:00 2001 From: Rodrigo Pedra Brum Date: Fri, 15 Jan 2021 18:55:55 -0300 Subject: [PATCH 17/23] [8.x] Handle `->sole()` exceptions (#35912) * handle sole exceptions * do not handle MultipleRecordsFoundException --- .../Foundation/Exceptions/Handler.php | 2 ++ .../FoundationExceptionsHandlerTest.php | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/Illuminate/Foundation/Exceptions/Handler.php b/src/Illuminate/Foundation/Exceptions/Handler.php index c73130cb137e..33fbccc5e7e1 100644 --- a/src/Illuminate/Foundation/Exceptions/Handler.php +++ b/src/Illuminate/Foundation/Exceptions/Handler.php @@ -373,6 +373,8 @@ protected function prepareException(Throwable $e) $e = new HttpException(419, $e->getMessage(), $e); } elseif ($e instanceof SuspiciousOperationException) { $e = new NotFoundHttpException('Bad hostname provided.', $e); + } elseif ($e instanceof RecordsNotFoundException) { + $e = new NotFoundHttpException('Not found.', $e); } return $e; diff --git a/tests/Foundation/FoundationExceptionsHandlerTest.php b/tests/Foundation/FoundationExceptionsHandlerTest.php index 887de48f7ddd..f7175dc58db5 100644 --- a/tests/Foundation/FoundationExceptionsHandlerTest.php +++ b/tests/Foundation/FoundationExceptionsHandlerTest.php @@ -8,6 +8,7 @@ use Illuminate\Contracts\Routing\ResponseFactory as ResponseFactoryContract; use Illuminate\Contracts\Support\Responsable; use Illuminate\Contracts\View\Factory; +use Illuminate\Database\RecordsNotFoundException; use Illuminate\Foundation\Exceptions\Handler; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; @@ -235,6 +236,23 @@ public function testSuspiciousOperationReturns404WithoutReporting() $this->handler->report(new SuspiciousOperationException('Invalid method override "__CONSTRUCT"')); } + + public function testRecordsNotFoundReturns404WithoutReporting() + { + $this->config->shouldReceive('get')->with('app.debug', null)->once()->andReturn(true); + $this->request->shouldReceive('expectsJson')->once()->andReturn(true); + + $response = $this->handler->render($this->request, new RecordsNotFoundException()); + + $this->assertEquals(404, $response->getStatusCode()); + $this->assertStringContainsString('"message": "Not found."', $response->getContent()); + + $logger = m::mock(LoggerInterface::class); + $this->container->instance(LoggerInterface::class, $logger); + $logger->shouldNotReceive('error'); + + $this->handler->report(new RecordsNotFoundException()); + } } class CustomException extends Exception From 0076fc98a4aea00997764552bee17a86531cf605 Mon Sep 17 00:00:00 2001 From: Lupacescu Eduard Date: Fri, 15 Jan 2021 23:56:08 +0200 Subject: [PATCH 18/23] Adding PHPDoc 'afterCommit' on DB Facade. (#35911) --- src/Illuminate/Support/Facades/DB.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Illuminate/Support/Facades/DB.php b/src/Illuminate/Support/Facades/DB.php index 7986e3cf863c..47c3ab543fa3 100755 --- a/src/Illuminate/Support/Facades/DB.php +++ b/src/Illuminate/Support/Facades/DB.php @@ -22,6 +22,7 @@ * @method static string getDefaultConnection() * @method static void beginTransaction() * @method static void commit() + * @method static void afterCommit(\Closure $callback) * @method static void listen(\Closure $callback) * @method static void rollBack(int $toLevel = null) * @method static void setDefaultConnection(string $name) From 8465ecfc69ff72e4eb25fc9ff6f7a13746c0c060 Mon Sep 17 00:00:00 2001 From: Chris Morrell Date: Sat, 16 Jan 2021 11:54:40 -0500 Subject: [PATCH 19/23] Use View contract rather than implementation (#35920) --- src/Illuminate/View/Concerns/ManagesComponents.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/View/Concerns/ManagesComponents.php b/src/Illuminate/View/Concerns/ManagesComponents.php index 574e91d6213b..81b2bdf6cbaf 100644 --- a/src/Illuminate/View/Concerns/ManagesComponents.php +++ b/src/Illuminate/View/Concerns/ManagesComponents.php @@ -4,9 +4,9 @@ use Closure; use Illuminate\Contracts\Support\Htmlable; +use Illuminate\Contracts\View\View; use Illuminate\Support\Arr; use Illuminate\Support\HtmlString; -use Illuminate\View\View; use InvalidArgumentException; trait ManagesComponents From c90605d610c57c3738b4aa49bf08da82c75eb7b9 Mon Sep 17 00:00:00 2001 From: Chuangbo Li Date: Sun, 17 Jan 2021 00:54:56 +0800 Subject: [PATCH 20/23] fix typo (#35916) --- src/Illuminate/Queue/Middleware/RateLimited.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Queue/Middleware/RateLimited.php b/src/Illuminate/Queue/Middleware/RateLimited.php index f7a8d6c08105..4d2d61c5e4e4 100644 --- a/src/Illuminate/Queue/Middleware/RateLimited.php +++ b/src/Illuminate/Queue/Middleware/RateLimited.php @@ -144,7 +144,7 @@ public function __unserialize(array $data) { $this->limiter = Container::getInstance()->make(RateLimiter::class); - $this->limitedName = $data['limiterName']; + $this->limiterName = $data['limiterName']; $this->shouldRelease = $data['shouldRelease']; } } From 5e40b0e87f08d40d7de2922374ea9dc2d96c0c56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20N=C3=BCrnberger?= Date: Sun, 17 Jan 2021 21:14:47 +0100 Subject: [PATCH 21/23] use expected (#35926) --- tests/Integration/Database/QueryBuilderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Integration/Database/QueryBuilderTest.php b/tests/Integration/Database/QueryBuilderTest.php index 675f30561fae..66a65cbdaa43 100644 --- a/tests/Integration/Database/QueryBuilderTest.php +++ b/tests/Integration/Database/QueryBuilderTest.php @@ -36,7 +36,7 @@ public function testSole() { $expected = ['id' => '1', 'title' => 'Foo Post']; - $this->assertEquals(1, DB::table('posts')->where('title', 'Foo Post')->sole()->id); + $this->assertSame($expected, (array) DB::table('posts')->where('title', 'Foo Post')->select('id', 'title')->sole()); } public function testSoleFailsForMultipleRecords() From 74159770942b7660488e8c213d9ad7ffd6bfba2c Mon Sep 17 00:00:00 2001 From: Mikey O'Toole Date: Mon, 18 Jan 2021 15:27:44 +0000 Subject: [PATCH 22/23] Add validation support for TeamSpeak3 URI scheme (#35933) This PR adds support for `ts3server` URI validation to the URL validator's list of protocols. https://gaming.stackexchange.com/questions/51926/how-can-i-directly-link-to-a-teamspeak-server-on-my-website --- src/Illuminate/Validation/Concerns/ValidatesAttributes.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php index c0c5411c1391..4efd422cd711 100644 --- a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php +++ b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php @@ -1776,7 +1776,7 @@ public function validateUrl($attribute, $value) * (c) Fabien Potencier http://symfony.com */ $pattern = '~^ - (aaa|aaas|about|acap|acct|acd|acr|adiumxtra|adt|afp|afs|aim|amss|android|appdata|apt|ark|attachment|aw|barion|beshare|bitcoin|bitcoincash|blob|bolo|browserext|calculator|callto|cap|cast|casts|chrome|chrome-extension|cid|coap|coap\+tcp|coap\+ws|coaps|coaps\+tcp|coaps\+ws|com-eventbrite-attendee|content|conti|crid|cvs|dab|data|dav|diaspora|dict|did|dis|dlna-playcontainer|dlna-playsingle|dns|dntp|dpp|drm|drop|dtn|dvb|ed2k|elsi|example|facetime|fax|feed|feedready|file|filesystem|finger|first-run-pen-experience|fish|fm|ftp|fuchsia-pkg|geo|gg|git|gizmoproject|go|gopher|graph|gtalk|h323|ham|hcap|hcp|http|https|hxxp|hxxps|hydrazone|iax|icap|icon|im|imap|info|iotdisco|ipn|ipp|ipps|irc|irc6|ircs|iris|iris\.beep|iris\.lwz|iris\.xpc|iris\.xpcs|isostore|itms|jabber|jar|jms|keyparc|lastfm|ldap|ldaps|leaptofrogans|lorawan|lvlt|magnet|mailserver|mailto|maps|market|message|mid|mms|modem|mongodb|moz|ms-access|ms-browser-extension|ms-calculator|ms-drive-to|ms-enrollment|ms-excel|ms-eyecontrolspeech|ms-gamebarservices|ms-gamingoverlay|ms-getoffice|ms-help|ms-infopath|ms-inputapp|ms-lockscreencomponent-config|ms-media-stream-id|ms-mixedrealitycapture|ms-mobileplans|ms-officeapp|ms-people|ms-project|ms-powerpoint|ms-publisher|ms-restoretabcompanion|ms-screenclip|ms-screensketch|ms-search|ms-search-repair|ms-secondary-screen-controller|ms-secondary-screen-setup|ms-settings|ms-settings-airplanemode|ms-settings-bluetooth|ms-settings-camera|ms-settings-cellular|ms-settings-cloudstorage|ms-settings-connectabledevices|ms-settings-displays-topology|ms-settings-emailandaccounts|ms-settings-language|ms-settings-location|ms-settings-lock|ms-settings-nfctransactions|ms-settings-notifications|ms-settings-power|ms-settings-privacy|ms-settings-proximity|ms-settings-screenrotation|ms-settings-wifi|ms-settings-workplace|ms-spd|ms-sttoverlay|ms-transit-to|ms-useractivityset|ms-virtualtouchpad|ms-visio|ms-walk-to|ms-whiteboard|ms-whiteboard-cmd|ms-word|msnim|msrp|msrps|mss|mtqp|mumble|mupdate|mvn|news|nfs|ni|nih|nntp|notes|ocf|oid|onenote|onenote-cmd|opaquelocktoken|openpgp4fpr|pack|palm|paparazzi|payto|pkcs11|platform|pop|pres|prospero|proxy|pwid|psyc|pttp|qb|query|redis|rediss|reload|res|resource|rmi|rsync|rtmfp|rtmp|rtsp|rtsps|rtspu|s3|secondlife|service|session|sftp|sgn|shttp|sieve|simpleledger|sip|sips|skype|smb|sms|smtp|snews|snmp|soap\.beep|soap\.beeps|soldat|spiffe|spotify|ssh|steam|stun|stuns|submit|svn|tag|teamspeak|tel|teliaeid|telnet|tftp|tg|things|thismessage|tip|tn3270|tool|turn|turns|tv|udp|unreal|urn|ut2004|v-event|vemmi|ventrilo|videotex|vnc|view-source|wais|webcal|wpid|ws|wss|wtai|wyciwyg|xcon|xcon-userid|xfire|xmlrpc\.beep|xmlrpc\.beeps|xmpp|xri|ymsgr|z39\.50|z39\.50r|z39\.50s):// # protocol + (aaa|aaas|about|acap|acct|acd|acr|adiumxtra|adt|afp|afs|aim|amss|android|appdata|apt|ark|attachment|aw|barion|beshare|bitcoin|bitcoincash|blob|bolo|browserext|calculator|callto|cap|cast|casts|chrome|chrome-extension|cid|coap|coap\+tcp|coap\+ws|coaps|coaps\+tcp|coaps\+ws|com-eventbrite-attendee|content|conti|crid|cvs|dab|data|dav|diaspora|dict|did|dis|dlna-playcontainer|dlna-playsingle|dns|dntp|dpp|drm|drop|dtn|dvb|ed2k|elsi|example|facetime|fax|feed|feedready|file|filesystem|finger|first-run-pen-experience|fish|fm|ftp|fuchsia-pkg|geo|gg|git|gizmoproject|go|gopher|graph|gtalk|h323|ham|hcap|hcp|http|https|hxxp|hxxps|hydrazone|iax|icap|icon|im|imap|info|iotdisco|ipn|ipp|ipps|irc|irc6|ircs|iris|iris\.beep|iris\.lwz|iris\.xpc|iris\.xpcs|isostore|itms|jabber|jar|jms|keyparc|lastfm|ldap|ldaps|leaptofrogans|lorawan|lvlt|magnet|mailserver|mailto|maps|market|message|mid|mms|modem|mongodb|moz|ms-access|ms-browser-extension|ms-calculator|ms-drive-to|ms-enrollment|ms-excel|ms-eyecontrolspeech|ms-gamebarservices|ms-gamingoverlay|ms-getoffice|ms-help|ms-infopath|ms-inputapp|ms-lockscreencomponent-config|ms-media-stream-id|ms-mixedrealitycapture|ms-mobileplans|ms-officeapp|ms-people|ms-project|ms-powerpoint|ms-publisher|ms-restoretabcompanion|ms-screenclip|ms-screensketch|ms-search|ms-search-repair|ms-secondary-screen-controller|ms-secondary-screen-setup|ms-settings|ms-settings-airplanemode|ms-settings-bluetooth|ms-settings-camera|ms-settings-cellular|ms-settings-cloudstorage|ms-settings-connectabledevices|ms-settings-displays-topology|ms-settings-emailandaccounts|ms-settings-language|ms-settings-location|ms-settings-lock|ms-settings-nfctransactions|ms-settings-notifications|ms-settings-power|ms-settings-privacy|ms-settings-proximity|ms-settings-screenrotation|ms-settings-wifi|ms-settings-workplace|ms-spd|ms-sttoverlay|ms-transit-to|ms-useractivityset|ms-virtualtouchpad|ms-visio|ms-walk-to|ms-whiteboard|ms-whiteboard-cmd|ms-word|msnim|msrp|msrps|mss|mtqp|mumble|mupdate|mvn|news|nfs|ni|nih|nntp|notes|ocf|oid|onenote|onenote-cmd|opaquelocktoken|openpgp4fpr|pack|palm|paparazzi|payto|pkcs11|platform|pop|pres|prospero|proxy|pwid|psyc|pttp|qb|query|redis|rediss|reload|res|resource|rmi|rsync|rtmfp|rtmp|rtsp|rtsps|rtspu|s3|secondlife|service|session|sftp|sgn|shttp|sieve|simpleledger|sip|sips|skype|smb|sms|smtp|snews|snmp|soap\.beep|soap\.beeps|soldat|spiffe|spotify|ssh|steam|stun|stuns|submit|svn|tag|teamspeak|tel|teliaeid|telnet|tftp|tg|things|thismessage|tip|tn3270|tool|ts3server|turn|turns|tv|udp|unreal|urn|ut2004|v-event|vemmi|ventrilo|videotex|vnc|view-source|wais|webcal|wpid|ws|wss|wtai|wyciwyg|xcon|xcon-userid|xfire|xmlrpc\.beep|xmlrpc\.beeps|xmpp|xri|ymsgr|z39\.50|z39\.50r|z39\.50s):// # protocol (((?:[\_\.\pL\pN-]|%[0-9A-Fa-f]{2})+:)?((?:[\_\.\pL\pN-]|%[0-9A-Fa-f]{2})+)@)? # basic auth ( ([\pL\pN\pS\-\_\.])+(\.?([\pL\pN]|xn\-\-[\pL\pN-]+)+\.?) # a domain name From eeaf5f61446a62e93dff13d2c098d39bba8e6086 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Tue, 19 Jan 2021 07:40:52 -0600 Subject: [PATCH 23/23] version --- src/Illuminate/Foundation/Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index ec1deae44b68..cb0724131fbc 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 = '8.22.1'; + const VERSION = '8.23.0'; /** * The base path for the Laravel installation. pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy