From 00cdf85281788d01e0bbfd66577a11b20ff98b79 Mon Sep 17 00:00:00 2001 From: Tetiana Blindaruk Date: Tue, 1 Feb 2022 20:15:15 +0200 Subject: [PATCH 01/15] [8.x] update changelog --- CHANGELOG-8.x.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-8.x.md b/CHANGELOG-8.x.md index 35dace73786c..70840bdadaee 100644 --- a/CHANGELOG-8.x.md +++ b/CHANGELOG-8.x.md @@ -1,6 +1,25 @@ # Release Notes for 8.x -## [Unreleased](https://github.com/laravel/framework/compare/v8.81.0...8.x) +## [Unreleased](https://github.com/laravel/framework/compare/v8.82.0...8.x) + + +## [v8.82.0 (2022-02-01)](https://github.com/laravel/framework/compare/v8.81.0...v8.82.0) + +### Added +- Added class and method to create cross joined sequences for factories ([#40542](https://github.com/laravel/framework/pull/40542)) +- Added Transliterate shortcut to the Str helper ([#40681](https://github.com/laravel/framework/pull/40681)) +- Added array_keys validation rule ([#40720](https://github.com/laravel/framework/pull/40720)) + +### Fixed +- Prevent job serialization error in Queue ([#40625](https://github.com/laravel/framework/pull/40625)) +- Fixed autoresolving model name from factory ([#40616](https://github.com/laravel/framework/pull/40616)) +- Fixed : strtotime Epoch doesn't fit in PHP int ([#40690](https://github.com/laravel/framework/pull/40690)) +- Fixed Stringable ucsplit ([#40694](https://github.com/laravel/framework/pull/40694), [#40699](https://github.com/laravel/framework/pull/40699)) + +### Changed +- Server command: Allow xdebug auto-connect to listener feature ([#40673](https://github.com/laravel/framework/pull/40673)) +- respect null driver in `QueueServiceProvider` ([9435827](https://github.com/laravel/framework/commit/9435827014ca289213f2bcf64847f5c5959bb652), [56d433a](https://github.com/laravel/framework/commit/56d433aaec40e8383f28e8f0e835cd977845fcde)) +- Allow to push and prepend config values on new keys ([#40723](https://github.com/laravel/framework/pull/40723)) ## [v8.81.0 (2022-01-25)](https://github.com/laravel/framework/compare/v8.80.0...v8.81.0) From 442b6d0e7e086a5775c97ccd61111c75cd2d2037 Mon Sep 17 00:00:00 2001 From: Phillip Fickl Date: Wed, 2 Feb 2022 18:53:25 +0100 Subject: [PATCH 02/15] Make PendingRequest conditionable (#40762) --- src/Illuminate/Http/Client/PendingRequest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Http/Client/PendingRequest.php b/src/Illuminate/Http/Client/PendingRequest.php index fbbc288bb121..95194911e0dc 100644 --- a/src/Illuminate/Http/Client/PendingRequest.php +++ b/src/Illuminate/Http/Client/PendingRequest.php @@ -13,13 +13,14 @@ use Illuminate\Http\Client\Events\ResponseReceived; use Illuminate\Support\Collection; use Illuminate\Support\Str; +use Illuminate\Support\Traits\Conditionable; use Illuminate\Support\Traits\Macroable; use Psr\Http\Message\MessageInterface; use Symfony\Component\VarDumper\VarDumper; class PendingRequest { - use Macroable; + use Conditionable, Macroable; /** * The factory instance. From bcaebbab64737b60327fbb1dad40c8dbe3ea7f94 Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Thu, 3 Feb 2022 06:43:21 +1100 Subject: [PATCH 03/15] [8.x] Add a BladeCompiler::renderComponent() method to render a component instance (#40745) * Add a BladeCompiler::renderComponent() method to render a component instance * Fix test * Update BladeCompiler.php Co-authored-by: Taylor Otwell --- src/Illuminate/Support/Facades/Blade.php | 1 + .../View/Compilers/BladeCompiler.php | 26 +++++++++++++++++++ tests/Integration/View/BladeTest.php | 23 ++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/src/Illuminate/Support/Facades/Blade.php b/src/Illuminate/Support/Facades/Blade.php index 4427458669c2..81019e288de6 100755 --- a/src/Illuminate/Support/Facades/Blade.php +++ b/src/Illuminate/Support/Facades/Blade.php @@ -9,6 +9,7 @@ * @method static bool check(string $name, array ...$parameters) * @method static string compileString(string $value) * @method static string render(string $string, array $data = [], bool $deleteCachedView = false) + * @method static string renderComponent(\Illuminate\View\Component $component) * @method static string getPath() * @method static string stripParentheses(string $expression) * @method static void aliasComponent(string $path, string|null $alias = null) diff --git a/src/Illuminate/View/Compilers/BladeCompiler.php b/src/Illuminate/View/Compilers/BladeCompiler.php index 85edbfbcc159..4b4e45fdd71d 100644 --- a/src/Illuminate/View/Compilers/BladeCompiler.php +++ b/src/Illuminate/View/Compilers/BladeCompiler.php @@ -3,7 +3,9 @@ namespace Illuminate\View\Compilers; use Illuminate\Container\Container; +use Illuminate\Contracts\Support\Htmlable; use Illuminate\Contracts\View\Factory as ViewFactory; +use Illuminate\Contracts\View\View; use Illuminate\Support\Arr; use Illuminate\Support\Str; use Illuminate\Support\Traits\ReflectsClosures; @@ -306,6 +308,30 @@ public function render() }); } + /** + * Render a component instance to HTML. + * + * @param \Illuminate\View\Component $component + * @return string + */ + public static function renderComponent(Component $component) + { + $data = $component->data(); + + $view = value($component->resolveView(), $data); + + if ($view instanceof View) { + return $view->with($data)->render(); + } elseif ($view instanceof Htmlable) { + return $view->toHtml(); + } else { + return Container::getInstance() + ->make(ViewFactory::class) + ->make($view, $data) + ->render(); + } + } + /** * Store the blocks that do not receive compilation. * diff --git a/tests/Integration/View/BladeTest.php b/tests/Integration/View/BladeTest.php index 62d6cfd0a239..9f3717c4d818 100644 --- a/tests/Integration/View/BladeTest.php +++ b/tests/Integration/View/BladeTest.php @@ -4,6 +4,7 @@ use Illuminate\Support\Facades\Blade; use Illuminate\Support\Facades\View; +use Illuminate\View\Component; use Orchestra\Testbench\TestCase; class BladeTest extends TestCase @@ -13,6 +14,13 @@ public function test_rendering_blade_string() $this->assertSame('Hello Taylor', Blade::render('Hello {{ $name }}', ['name' => 'Taylor'])); } + public function test_rendering_blade_component_instance() + { + $component = new HelloComponent('Taylor'); + + $this->assertSame('Hello Taylor', Blade::renderComponent($component)); + } + public function test_basic_blade_rendering() { $view = View::make('hello', ['name' => 'Taylor'])->render(); @@ -110,3 +118,18 @@ protected function getEnvironmentSetUp($app) $app['config']->set('view.paths', [__DIR__.'/templates']); } } + +class HelloComponent extends Component +{ + public $name; + + public function __construct(string $name) + { + $this->name = $name; + } + + public function render() + { + return 'Hello {{ $name }}'; + } +} From 980a94a28e45e8e15a6b34612c4be9c2990cee2a Mon Sep 17 00:00:00 2001 From: Mark Beech Date: Wed, 2 Feb 2022 21:02:36 +0000 Subject: [PATCH 04/15] [8.0] Doc block tweaks in `BladeCompiler.php` (#40772) --- src/Illuminate/View/Compilers/BladeCompiler.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/View/Compilers/BladeCompiler.php b/src/Illuminate/View/Compilers/BladeCompiler.php index 4b4e45fdd71d..fd3f91a271a3 100644 --- a/src/Illuminate/View/Compilers/BladeCompiler.php +++ b/src/Illuminate/View/Compilers/BladeCompiler.php @@ -116,7 +116,7 @@ class BladeCompiler extends Compiler implements CompilerInterface protected $footer = []; /** - * Array to temporary store the raw blocks found in the template. + * Array to temporarily store the raw blocks found in the template. * * @var array */ @@ -425,7 +425,7 @@ protected function restoreRawContent($result) } /** - * Get a placeholder to temporary mark the position of raw blocks. + * Get a placeholder to temporarily mark the position of raw blocks. * * @param int|string $replace * @return string From c275cdc018b70b87f81f9412ff4287f3d9f51760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A1ssio=20Almeida?= Date: Wed, 2 Feb 2022 18:03:35 -0300 Subject: [PATCH 05/15] Remove commented code (#40769) --- src/Illuminate/Container/Container.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Illuminate/Container/Container.php b/src/Illuminate/Container/Container.php index bf7bb8e559ac..e6cd346fede8 100755 --- a/src/Illuminate/Container/Container.php +++ b/src/Illuminate/Container/Container.php @@ -886,10 +886,6 @@ public function build($concrete) return $this->notInstantiable($concrete); } - // if (in_array($concrete, $this->buildStack)) { - // throw new CircularDependencyException("Circular dependency detected while resolving [{$concrete}]."); - // } - $this->buildStack[] = $concrete; $constructor = $reflector->getConstructor(); From c239161dd54d6108dd7ca3b292183f94c994ce23 Mon Sep 17 00:00:00 2001 From: Reza Amini Date: Thu, 3 Feb 2022 19:41:04 +0330 Subject: [PATCH 06/15] [8.x] Add isolation level configuration for Postgres connector (#40767) * [8.x] Add isolation level configuration for Postgres connector * formatting Co-authored-by: Taylor Otwell --- .../Database/Connectors/PostgresConnector.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Illuminate/Database/Connectors/PostgresConnector.php b/src/Illuminate/Database/Connectors/PostgresConnector.php index c21135b9e83d..a507d9ac3c41 100755 --- a/src/Illuminate/Database/Connectors/PostgresConnector.php +++ b/src/Illuminate/Database/Connectors/PostgresConnector.php @@ -33,6 +33,8 @@ public function connect(array $config) $this->getDsn($config), $config, $this->getOptions($config) ); + $this->configureIsolationLevel($connection, $config); + $this->configureEncoding($connection, $config); // Next, we will check to see if a timezone has been specified in this config @@ -52,6 +54,20 @@ public function connect(array $config) return $connection; } + /** + * Set the connection transaction isolation level. + * + * @param \PDO $connection + * @param array $config + * @return void + */ + protected function configureIsolationLevel($connection, array $config) + { + if (isset($config['isolation_level'])) { + $connection->prepare("set session characteristics as transaction isolation level {$config['isolation_level']}")->execute(); + } + } + /** * Set the connection character set and collation. * From bd9b5e5f01f4e43f6230ae381d34fd766f0eeeb0 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 3 Feb 2022 17:29:46 +0100 Subject: [PATCH 07/15] Revert Bit operators (#40791) --- src/Illuminate/Database/Query/Builder.php | 29 ----------- .../Database/Query/Grammars/Grammar.php | 50 ------------------- .../Query/Grammars/PostgresGrammar.php | 9 ---- tests/Database/DatabaseEloquentModelTest.php | 2 - tests/Database/DatabaseQueryBuilderTest.php | 19 ------- 5 files changed, 109 deletions(-) diff --git a/src/Illuminate/Database/Query/Builder.php b/src/Illuminate/Database/Query/Builder.php index 6a9b6db0dc6d..2d2d96ff76bc 100755 --- a/src/Illuminate/Database/Query/Builder.php +++ b/src/Illuminate/Database/Query/Builder.php @@ -203,15 +203,6 @@ class Builder 'not similar to', 'not ilike', '~~*', '!~~*', ]; - /** - * All of the available bit operators. - * - * @var string[] - */ - public $bitOperators = [ - '&', '|', '^', '<<', '>>', '&~', - ]; - /** * Whether to use write pdo for the select. * @@ -763,10 +754,6 @@ public function where($column, $operator = null, $value = null, $boolean = 'and' } } - if ($this->isBitOperator($operator)) { - $type = 'Bit'; - } - // Now that we are working with just a simple query we can put the elements // in our array and add the query binding to our array of bindings that // will be bound to each SQL statements when it is finally executed. @@ -850,18 +837,6 @@ protected function invalidOperator($operator) ! in_array(strtolower($operator), $this->grammar->getOperators(), true); } - /** - * Determine if the operator is a bit operator. - * - * @param string $operator - * @return bool - */ - protected function isBitOperator($operator) - { - return in_array(strtolower($operator), $this->bitOperators, true) || - in_array(strtolower($operator), $this->grammar->getBitOperators(), true); - } - /** * Add an "or where" clause to the query. * @@ -1940,10 +1915,6 @@ public function having($column, $operator = null, $value = null, $boolean = 'and [$value, $operator] = [$operator, '=']; } - if ($this->isBitOperator($operator)) { - $type = 'bit'; - } - $this->havings[] = compact('type', 'column', 'operator', 'value', 'boolean'); if (! $value instanceof Expression) { diff --git a/src/Illuminate/Database/Query/Grammars/Grammar.php b/src/Illuminate/Database/Query/Grammars/Grammar.php index 740769436adf..77472f088e02 100755 --- a/src/Illuminate/Database/Query/Grammars/Grammar.php +++ b/src/Illuminate/Database/Query/Grammars/Grammar.php @@ -18,13 +18,6 @@ class Grammar extends BaseGrammar */ protected $operators = []; - /** - * The grammar specific bit operators. - * - * @var array - */ - protected $bitOperators = []; - /** * The components that make up a select clause. * @@ -262,22 +255,6 @@ protected function whereBasic(Builder $query, $where) return $this->wrap($where['column']).' '.$operator.' '.$value; } - /** - * Compile a bit operator where clause. - * - * @param \Illuminate\Database\Query\Builder $query - * @param array $where - * @return string - */ - protected function whereBit(Builder $query, $where) - { - $value = $this->parameter($where['value']); - - $operator = str_replace('?', '??', $where['operator']); - - return '('.$this->wrap($where['column']).' '.$operator.' '.$value.') != 0'; - } - /** * Compile a "where in" clause. * @@ -708,8 +685,6 @@ protected function compileHaving(array $having) return $having['boolean'].' '.$having['sql']; } elseif ($having['type'] === 'between') { return $this->compileHavingBetween($having); - } elseif ($having['type'] === 'bit') { - return $this->compileHavingBit($having); } return $this->compileBasicHaving($having); @@ -749,21 +724,6 @@ protected function compileHavingBetween($having) return $having['boolean'].' '.$column.' '.$between.' '.$min.' and '.$max; } - /** - * Compile a having clause involving a bit operator. - * - * @param array $having - * @return string - */ - protected function compileHavingBit($having) - { - $column = $this->wrap($having['column']); - - $parameter = $this->parameter($having['value']); - - return $having['boolean'].' ('.$column.' '.$having['operator'].' '.$parameter.') != 0'; - } - /** * Compile the "order by" portions of the query. * @@ -1339,14 +1299,4 @@ public function getOperators() { return $this->operators; } - - /** - * Get the grammar specific bit operators. - * - * @return array - */ - public function getBitOperators() - { - return $this->bitOperators; - } } diff --git a/src/Illuminate/Database/Query/Grammars/PostgresGrammar.php b/src/Illuminate/Database/Query/Grammars/PostgresGrammar.php index 17a306edf638..47f498e54708 100755 --- a/src/Illuminate/Database/Query/Grammars/PostgresGrammar.php +++ b/src/Illuminate/Database/Query/Grammars/PostgresGrammar.php @@ -21,15 +21,6 @@ class PostgresGrammar extends Grammar 'is distinct from', 'is not distinct from', ]; - /** - * The grammar specific bit operators. - * - * @var array - */ - protected $bitOperators = [ - '~', '&', '|', '#', '<<', '>>', '<<=', '>>=', - ]; - /** * {@inheritdoc} * diff --git a/tests/Database/DatabaseEloquentModelTest.php b/tests/Database/DatabaseEloquentModelTest.php index 1ff87c9bf215..76fa651e855c 100755 --- a/tests/Database/DatabaseEloquentModelTest.php +++ b/tests/Database/DatabaseEloquentModelTest.php @@ -2153,7 +2153,6 @@ protected function addMockConnection($model) $model->setConnectionResolver($resolver = m::mock(ConnectionResolverInterface::class)); $resolver->shouldReceive('connection')->andReturn($connection = m::mock(Connection::class)); $connection->shouldReceive('getQueryGrammar')->andReturn($grammar = m::mock(Grammar::class)); - $grammar->shouldReceive('getBitOperators')->andReturn([]); $connection->shouldReceive('getPostProcessor')->andReturn($processor = m::mock(Processor::class)); $connection->shouldReceive('query')->andReturnUsing(function () use ($connection, $grammar, $processor) { return new BaseBuilder($connection, $grammar, $processor); @@ -2441,7 +2440,6 @@ public function getConnection() { $mock = m::mock(Connection::class); $mock->shouldReceive('getQueryGrammar')->andReturn($grammar = m::mock(Grammar::class)); - $grammar->shouldReceive('getBitOperators')->andReturn([]); $mock->shouldReceive('getPostProcessor')->andReturn($processor = m::mock(Processor::class)); $mock->shouldReceive('getName')->andReturn('name'); $mock->shouldReceive('query')->andReturnUsing(function () use ($mock, $grammar, $processor) { diff --git a/tests/Database/DatabaseQueryBuilderTest.php b/tests/Database/DatabaseQueryBuilderTest.php index b46fce4c6ade..d27a38a10276 100755 --- a/tests/Database/DatabaseQueryBuilderTest.php +++ b/tests/Database/DatabaseQueryBuilderTest.php @@ -3209,25 +3209,6 @@ public function testMySqlSoundsLikeOperator() $this->assertEquals(['John Doe'], $builder->getBindings()); } - public function testBitOperators() - { - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->where('bar', '&', 1); - $this->assertSame('select * from "users" where ("bar" & ?) != 0', $builder->toSql()); - - $builder = $this->getPostgresBuilder(); - $builder->select('*')->from('users')->where('bar', '#', 1); - $this->assertSame('select * from "users" where ("bar" # ?) != 0', $builder->toSql()); - - $builder = $this->getBuilder(); - $builder->select('*')->from('users')->having('bar', '&', 1); - $this->assertSame('select * from "users" having ("bar" & ?) != 0', $builder->toSql()); - - $builder = $this->getPostgresBuilder(); - $builder->select('*')->from('users')->having('bar', '#', 1); - $this->assertSame('select * from "users" having ("bar" # ?) != 0', $builder->toSql()); - } - public function testMergeWheresCanMergeWheresAndBindings() { $builder = $this->getBuilder(); From 09c1c0431c6cb616560f06e5740eb567364a96ab Mon Sep 17 00:00:00 2001 From: Iman Date: Fri, 4 Feb 2022 05:49:25 +0330 Subject: [PATCH 08/15] [8.x] Add test for FileStore (#40795) * Add test for FileStore * Add test for Increment in FileStore --- tests/Cache/CacheFileStoreTest.php | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/Cache/CacheFileStoreTest.php b/tests/Cache/CacheFileStoreTest.php index e1f50801d6b7..ac32d4642bc9 100755 --- a/tests/Cache/CacheFileStoreTest.php +++ b/tests/Cache/CacheFileStoreTest.php @@ -34,6 +34,21 @@ public function testNullIsReturnedIfFileDoesntExist() $this->assertNull($value); } + public function testUnserializableFileContentGetDeleted() + { + $files = $this->mockFilesystem(); + $hash = sha1('foo'); + $cachePath = __DIR__.'/'.substr($hash, 0, 2).'/'.substr($hash, 2, 2).'/'.$hash; + + $files->expects($this->once())->method('get')->willReturn('9999999999-I_am_unserializableee: \(~_~)/'); + $files->expects($this->once())->method('exists')->with($this->equalTo($cachePath))->willReturn(true); + $files->expects($this->once())->method('delete')->with($this->equalTo($cachePath)); + + $value = (new FileStore($files, __DIR__))->get('foo'); + + $this->assertNull($value); + } + public function testPutCreatesMissingDirectories() { $files = $this->mockFilesystem(); @@ -149,6 +164,19 @@ public function testForeversAreNotRemovedOnIncrement() $this->assertSame('Hello World', $store->get('foo')); } + public function testIncrementCanAtomicallyJump() + { + $files = $this->mockFilesystem(); + $initialValue = '9999999999'.serialize(1); + $valueAfterIncrement = '9999999999'.serialize(4); + $store = new FileStore($files, __DIR__); + $files->expects($this->once())->method('get')->willReturn($initialValue); + $hash = sha1('foo'); + $cache_dir = substr($hash, 0, 2).'/'.substr($hash, 2, 2); + $files->expects($this->once())->method('put')->with($this->equalTo(__DIR__.'/'.$cache_dir.'/'.$hash), $this->equalTo($valueAfterIncrement)); + $store->increment('foo', 3); + } + public function testIncrementDoesNotExtendCacheLife() { $files = $this->mockFilesystem(); From 3af82f6986a72343762fdbf2c2a08fe3cf55292c Mon Sep 17 00:00:00 2001 From: Reza Amini Date: Fri, 4 Feb 2022 19:08:00 +0330 Subject: [PATCH 09/15] [8.x] Add tests for new changes in postgres connector (#40800) --- tests/Database/DatabaseConnectorTest.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/Database/DatabaseConnectorTest.php b/tests/Database/DatabaseConnectorTest.php index 926c95b46c08..1bbd6a34d6e1 100755 --- a/tests/Database/DatabaseConnectorTest.php +++ b/tests/Database/DatabaseConnectorTest.php @@ -140,6 +140,23 @@ public function testPostgresApplicationNameIsSet() $this->assertSame($result, $connection); } + public function testPostgresConnectorReadsIsolationLevelFromConfig() + { + $dsn = 'pgsql:host=foo;dbname=\'bar\';port=111'; + $config = ['host' => 'foo', 'database' => 'bar', 'port' => 111, 'isolation_level' => 'SERIALIZABLE']; + $connector = $this->getMockBuilder(PostgresConnector::class)->onlyMethods(['createConnection', 'getOptions'])->getMock(); + $connection = m::mock(PDO::class); + $connector->expects($this->once())->method('getOptions')->with($this->equalTo($config))->willReturn(['options']); + $connector->expects($this->once())->method('createConnection')->with($this->equalTo($dsn), $this->equalTo($config), $this->equalTo(['options']))->willReturn($connection); + $statement = m::mock(PDOStatement::class); + $connection->shouldReceive('prepare')->once()->with('set session characteristics as transaction isolation level SERIALIZABLE')->andReturn($statement); + $statement->shouldReceive('execute')->zeroOrMoreTimes(); + $connection->shouldReceive('exec')->zeroOrMoreTimes(); + $result = $connector->connect($config); + + $this->assertSame($result, $connection); + } + public function testSQLiteMemoryDatabasesMayBeConnectedTo() { $dsn = 'sqlite::memory:'; From 1c15d0883bbe316f374c9f5e74a3a1e168184649 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Fri, 4 Feb 2022 17:29:45 +0100 Subject: [PATCH 10/15] Create pull-requests.yml (#40808) --- .github/workflows/pull-requests.yml | 64 +++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 .github/workflows/pull-requests.yml diff --git a/.github/workflows/pull-requests.yml b/.github/workflows/pull-requests.yml new file mode 100644 index 000000000000..87fa6b099bde --- /dev/null +++ b/.github/workflows/pull-requests.yml @@ -0,0 +1,64 @@ +name: Pull Requests + +# Credit: https://github.com/github/docs/blob/main/.github/workflows/notify-when-maintainers-cannot-edit.yaml + +on: + pull_request_target: + types: + - opened + +permissions: + pull-requests: write + +jobs: + uneditable: + if: github.repository == 'laravel/framework' + runs-on: ubuntu-latest + steps: + - uses: actions/github-script@2b34a689ec86a68d8ab9478298f91d5401337b7d + with: + script: | + const query = ` + query($number: Int!) { + repository(owner: "laravel", name: "framework") { + pullRequest(number: $number) { + headRepositoryOwner { + login + } + maintainerCanModify + } + } + } + `; + + const pullNumber = context.issue.number; + const variables = { number: pullNumber }; + + try { + console.log(`Check laravel/framework#${pullNumber} for maintainer edit access ...`); + + const result = await github.graphql(query, variables); + + console.log(JSON.stringify(result, null, 2)); + + const pullRequest = result.repository.pullRequest; + + if (pullRequest.headRepositoryOwner.login === 'laravel') { + console.log('PR owned by laravel'); + + return; + } + + if (!pullRequest.maintainerCanModify) { + console.log('PR not owned by Laravel and does not have maintainer edits enabled'); + + await github.issues.createComment({ + issue_number: pullNumber, + owner: 'laravel', + repo: 'framework', + body: "Thanks for submitting a PR!\n\nIn order to review and merge PRs most efficiently, we require that all PRs grant maintainer edit access before we review them. For information on how to do this, [see the relevant GitHub documentation](https://docs.github.com/en/github/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork)." + }); + } + } catch(e) { + console.log(e); + } From c7f4c23e17013b9c6f86a8fd1d37a590e2ad29b4 Mon Sep 17 00:00:00 2001 From: Iman Date: Fri, 4 Feb 2022 22:46:23 +0330 Subject: [PATCH 11/15] Add tests for put method of FileStore (#40811) --- tests/Cache/CacheFileStoreTest.php | 38 +++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/tests/Cache/CacheFileStoreTest.php b/tests/Cache/CacheFileStoreTest.php index ac32d4642bc9..8320237645b5 100755 --- a/tests/Cache/CacheFileStoreTest.php +++ b/tests/Cache/CacheFileStoreTest.php @@ -62,7 +62,43 @@ public function testPutCreatesMissingDirectories() $this->assertTrue($result); } - public function testExpiredItemsReturnNull() + public function testPutWillConsiderZeroAsEternalTime() + { + $files = $this->mockFilesystem(); + + $hash = sha1('O--L / key'); + $filePath = __DIR__.'/'.substr($hash, 0, 2).'/'.substr($hash, 2, 2).'/'.$hash; + $ten9s = '9999999999'; // The "forever" time value. + $fileContents = $ten9s.serialize('gold'); + $exclusiveLock = true; + + $files->expects($this->once())->method('put')->with( + $this->equalTo($filePath), + $this->equalTo($fileContents), + $this->equalTo($exclusiveLock) // Ensure we do lock the file while putting. + )->willReturn(strlen($fileContents)); + + (new FileStore($files, __DIR__))->put('O--L / key', 'gold', 0); + } + + public function testPutWillConsiderBigValuesAsEternalTime() + { + $files = $this->mockFilesystem(); + + $hash = sha1('O--L / key'); + $filePath = __DIR__.'/'.substr($hash, 0, 2).'/'.substr($hash, 2, 2).'/'.$hash; + $ten9s = '9999999999'; // The "forever" time value. + $fileContents = $ten9s.serialize('gold'); + + $files->expects($this->once())->method('put')->with( + $this->equalTo($filePath), + $this->equalTo($fileContents), + ); + + (new FileStore($files, __DIR__))->put('O--L / key', 'gold', (int) $ten9s + 1); + } + + public function testExpiredItemsReturnNullAndGetDeleted() { $files = $this->mockFilesystem(); $contents = '0000000000'; From d47153dc24bb8f0d2f75dde70d9f6dabf55403a3 Mon Sep 17 00:00:00 2001 From: Hassan Hedr <31159198+hassanhe@users.noreply.github.com> Date: Sat, 5 Feb 2022 17:07:38 +0200 Subject: [PATCH 12/15] [8.x] Improves `Support\Reflector` to support checking interfaces (#40822) * Update Reflector.php * Update SupportReflectorTest.php --- src/Illuminate/Support/Reflector.php | 3 ++- tests/Support/SupportReflectorTest.php | 26 ++++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/Illuminate/Support/Reflector.php b/src/Illuminate/Support/Reflector.php index 7a75f5f090fb..b2075757d71a 100644 --- a/src/Illuminate/Support/Reflector.php +++ b/src/Illuminate/Support/Reflector.php @@ -136,7 +136,8 @@ public static function isParameterSubclassOf($parameter, $className) $paramClassName = static::getParameterClassName($parameter); return $paramClassName - && class_exists($paramClassName) + && (class_exists($paramClassName) || + interface_exists($paramClassName)) && (new ReflectionClass($paramClassName))->isSubclassOf($className); } } diff --git a/tests/Support/SupportReflectorTest.php b/tests/Support/SupportReflectorTest.php index c7aaffe51cdc..9e4dfda39457 100644 --- a/tests/Support/SupportReflectorTest.php +++ b/tests/Support/SupportReflectorTest.php @@ -48,6 +48,13 @@ public function testParentClassName() $this->assertSame(A::class, Reflector::getParameterClassName($method->getParameters()[0])); } + public function testParameterSubclassOfInterface() + { + $method = (new ReflectionClass(TestClassWithInterfaceSubclassParameter::class))->getMethod('f'); + + $this->assertTrue(Reflector::isParameterSubclassOf($method->getParameters()[0], IA::class)); + } + /** * @requires PHP >= 8 */ @@ -95,8 +102,7 @@ public function f(A|Model $x) { // } -}' - ); +}'); } class TestClassWithCall @@ -114,3 +120,19 @@ public static function __callStatic($method, $parameters) // } } + +interface IA +{ +} + +interface IB extends IA +{ +} + +class TestClassWithInterfaceSubclassParameter +{ + public function f(IB $x) + { + // + } +} From 803a72550f1629bbca05f7748d424b9b57c24f33 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Sat, 5 Feb 2022 09:08:05 -0600 Subject: [PATCH 13/15] formatting --- src/Illuminate/Support/Reflector.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Illuminate/Support/Reflector.php b/src/Illuminate/Support/Reflector.php index b2075757d71a..841bad68629d 100644 --- a/src/Illuminate/Support/Reflector.php +++ b/src/Illuminate/Support/Reflector.php @@ -136,8 +136,7 @@ public static function isParameterSubclassOf($parameter, $className) $paramClassName = static::getParameterClassName($parameter); return $paramClassName - && (class_exists($paramClassName) || - interface_exists($paramClassName)) + && (class_exists($paramClassName) || interface_exists($paramClassName)) && (new ReflectionClass($paramClassName))->isSubclassOf($className); } } From 536f5a830c3d1bb3b5c82ca8537b08c21009632a Mon Sep 17 00:00:00 2001 From: William Date: Sat, 5 Feb 2022 23:09:51 +0800 Subject: [PATCH 14/15] [8.x] Do not set SYSTEMROOT to false (#40819) --- src/Illuminate/Foundation/Console/ServeCommand.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Illuminate/Foundation/Console/ServeCommand.php b/src/Illuminate/Foundation/Console/ServeCommand.php index 7bdbf10e730f..ddb07e824eca 100644 --- a/src/Illuminate/Foundation/Console/ServeCommand.php +++ b/src/Illuminate/Foundation/Console/ServeCommand.php @@ -105,6 +105,7 @@ protected function startProcess($hasEnvironment) 'LARAVEL_SAIL', 'PHP_CLI_SERVER_WORKERS', 'PHP_IDE_CONFIG', + 'SYSTEMROOT', 'XDEBUG_CONFIG', 'XDEBUG_MODE', 'XDEBUG_SESSION', From 2246744061de4bfd2d3a42d715e6b760015fa074 Mon Sep 17 00:00:00 2001 From: Iman Date: Sat, 5 Feb 2022 18:44:21 +0330 Subject: [PATCH 15/15] add test for cache Repository class (#40817) --- tests/Cache/CacheRepositoryTest.php | 32 +++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/Cache/CacheRepositoryTest.php b/tests/Cache/CacheRepositoryTest.php index 86064250e80c..9ec39d54daad 100755 --- a/tests/Cache/CacheRepositoryTest.php +++ b/tests/Cache/CacheRepositoryTest.php @@ -205,6 +205,36 @@ public function testCacheAddCallsRedisStoreAdd() $this->assertTrue($repository->add('k', 'v', 60)); } + public function testAddMethodCanAcceptDateIntervals() + { + $storeWithAdd = m::mock(RedisStore::class); + $storeWithAdd->shouldReceive('add')->once()->with('k', 'v', 61)->andReturn(true); + $repository = new Repository($storeWithAdd); + $this->assertTrue($repository->add('k', 'v', DateInterval::createFromDateString('61 seconds'))); + + $storeWithoutAdd = m::mock(ArrayStore::class); + $this->assertFalse(method_exists(ArrayStore::class, 'add'), 'This store should not have add method on it.'); + $storeWithoutAdd->shouldReceive('get')->once()->with('k')->andReturn(null); + $storeWithoutAdd->shouldReceive('put')->once()->with('k', 'v', 60)->andReturn(true); + $repository = new Repository($storeWithoutAdd); + $this->assertTrue($repository->add('k', 'v', DateInterval::createFromDateString('60 seconds'))); + } + + public function testAddMethodCanAcceptDateTimeInterface() + { + $withAddStore = m::mock(RedisStore::class); + $withAddStore->shouldReceive('add')->once()->with('k', 'v', 61)->andReturn(true); + $repository = new Repository($withAddStore); + $this->assertTrue($repository->add('k', 'v', Carbon::now()->addSeconds(61))); + + $noAddStore = m::mock(ArrayStore::class); + $this->assertFalse(method_exists(ArrayStore::class, 'add'), 'This store should not have add method on it.'); + $noAddStore->shouldReceive('get')->once()->with('k')->andReturn(null); + $noAddStore->shouldReceive('put')->once()->with('k', 'v', 62)->andReturn(true); + $repository = new Repository($noAddStore); + $this->assertTrue($repository->add('k', 'v', Carbon::now()->addSeconds(62))); + } + public function testAddWithNullTTLRemembersItemForever() { $repo = $this->getRepository(); @@ -221,6 +251,8 @@ public function testAddWithDatetimeInPastOrZeroSecondsReturnsImmediately() $this->assertFalse($result); $result = $repo->add('foo', 'bar', Carbon::now()); $this->assertFalse($result); + $result = $repo->add('foo', 'bar', -1); + $this->assertFalse($result); } public function dataProviderTestGetSeconds()