From 82ffe3cd4a72887ba3e6f8f4bf8fa28fda1f3691 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Mon, 19 Oct 2020 14:45:46 +0100 Subject: [PATCH] Provisional support for PHP 8.0 (#34884) Co-Authored-By: Dries Vints <594614+driesvints@users.noreply.github.com> Co-Authored-By: Taylor Otwell Co-authored-by: Dries Vints <594614+driesvints@users.noreply.github.com> Co-authored-by: Taylor Otwell --- composer.json | 16 ++++++------- src/Illuminate/Cache/RedisTaggedCache.php | 2 +- .../Console/Concerns/HasParameters.php | 4 ++-- src/Illuminate/Console/composer.json | 2 +- src/Illuminate/Container/BoundMethod.php | 6 ++--- src/Illuminate/Cookie/CookieJar.php | 2 +- src/Illuminate/Database/Eloquent/Builder.php | 18 +++++++++------ .../Database/Eloquent/Collection.php | 2 +- .../Concerns/InteractsWithPivotTable.php | 4 ++-- .../Database/MigrationServiceProvider.php | 2 +- .../Database/Schema/Grammars/RenameColumn.php | 15 +++++++++++- src/Illuminate/Events/CallQueuedListener.php | 12 ++++------ src/Illuminate/Events/Dispatcher.php | 6 ++--- .../Filesystem/FilesystemAdapter.php | 2 +- src/Illuminate/Filesystem/composer.json | 2 +- .../Foundation/Console/QueuedCommand.php | 2 +- .../Providers/ArtisanServiceProvider.php | 2 +- src/Illuminate/Http/ResponseTrait.php | 4 ++-- src/Illuminate/Queue/composer.json | 2 +- .../Redis/Connections/PredisConnection.php | 2 +- src/Illuminate/Routing/Controller.php | 2 +- src/Illuminate/Routing/Pipeline.php | 2 +- src/Illuminate/Routing/Route.php | 4 ++-- src/Illuminate/Routing/Router.php | 23 +++++++++++++++++++ src/Illuminate/Routing/SortedMiddleware.php | 2 +- src/Illuminate/Support/Collection.php | 2 +- src/Illuminate/Support/Str.php | 4 ++++ .../Support/Traits/EnumeratesValues.php | 2 +- src/Illuminate/Support/Traits/Macroable.php | 4 ++-- src/Illuminate/Support/composer.json | 2 +- .../Validation/Concerns/FormatsMessages.php | 4 ++-- src/Illuminate/Validation/Validator.php | 6 ++--- .../View/Concerns/ManagesEvents.php | 4 +--- tests/Container/ContainerCallTest.php | 6 ++--- tests/Database/DatabaseConnectionTest.php | 6 ++++- .../DatabaseEloquentBelongsToTest.php | 8 ++++++- .../Database/DatabaseEloquentBuilderTest.php | 4 +++- .../ApiAuthenticationWithEloquentTest.php | 3 +++ ...baseEmulatePreparesMySqlConnectionTest.php | 3 +++ .../Database/DatabaseMySqlConnectionTest.php | 3 +++ 40 files changed, 130 insertions(+), 71 deletions(-) diff --git a/composer.json b/composer.json index 095f73bb0ac7..6645429ddf98 100644 --- a/composer.json +++ b/composer.json @@ -20,13 +20,13 @@ "ext-mbstring": "*", "ext-openssl": "*", "doctrine/inflector": "^1.4|^2.0", - "dragonmantank/cron-expression": "^2.0", + "dragonmantank/cron-expression": "^2.3.1", "egulias/email-validator": "^2.1.10", "league/commonmark": "^1.3", - "league/flysystem": "^1.0.34", + "league/flysystem": "^1.1", "monolog/monolog": "^1.12|^2.0", - "nesbot/carbon": "^2.0", - "opis/closure": "^3.1", + "nesbot/carbon": "^2.31", + "opis/closure": "^3.6", "psr/container": "^1.0", "psr/simple-cache": "^1.0", "ramsey/uuid": "^3.7", @@ -79,14 +79,14 @@ "require-dev": { "aws/aws-sdk-php": "^3.0", "doctrine/dbal": "^2.6", - "filp/whoops": "^2.4", + "filp/whoops": "^2.8", "guzzlehttp/guzzle": "^6.3|^7.0", "league/flysystem-cached-adapter": "^1.0", - "mockery/mockery": "^1.3.1", + "mockery/mockery": "~1.3.3|^1.4.2", "moontoast/math": "^1.1", "orchestra/testbench-core": "^4.0", "pda/pheanstalk": "^4.0", - "phpunit/phpunit": "^7.5.15|^8.4|^9.0", + "phpunit/phpunit": "^7.5.15|^8.4|^9.3.3", "predis/predis": "^1.1.1", "symfony/cache": "^4.3.4" }, @@ -121,7 +121,7 @@ "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0).", "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.0).", "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.6).", - "filp/whoops": "Required for friendly error pages in development (^2.4).", + "filp/whoops": "Required for friendly error pages in development (^2.8).", "fzaninotto/faker": "Required to use the eloquent factory builder (^1.9.1).", "guzzlehttp/guzzle": "Required to use the Mailgun mail driver and the ping methods on schedules (^6.0|^7.0).", "laravel/tinker": "Required to use the tinker console command (^2.0).", diff --git a/src/Illuminate/Cache/RedisTaggedCache.php b/src/Illuminate/Cache/RedisTaggedCache.php index 208ae94661be..ad50ce9adb41 100644 --- a/src/Illuminate/Cache/RedisTaggedCache.php +++ b/src/Illuminate/Cache/RedisTaggedCache.php @@ -179,7 +179,7 @@ protected function deleteValues($referenceKey) if (count($values) > 0) { foreach (array_chunk($values, 1000) as $valuesChunk) { - call_user_func_array([$this->store->connection(), 'del'], $valuesChunk); + $this->store->connection()->del(...$valuesChunk); } } } diff --git a/src/Illuminate/Console/Concerns/HasParameters.php b/src/Illuminate/Console/Concerns/HasParameters.php index 3f6f9c7642cf..e860ec2a2ec5 100644 --- a/src/Illuminate/Console/Concerns/HasParameters.php +++ b/src/Illuminate/Console/Concerns/HasParameters.php @@ -21,7 +21,7 @@ protected function specifyParameters() if ($arguments instanceof InputArgument) { $this->getDefinition()->addArgument($arguments); } else { - call_user_func_array([$this, 'addArgument'], $arguments); + $this->addArgument(...array_values($arguments)); } } @@ -29,7 +29,7 @@ protected function specifyParameters() if ($options instanceof InputOption) { $this->getDefinition()->addOption($options); } else { - call_user_func_array([$this, 'addOption'], $options); + $this->addOption(...array_values($options)); } } } diff --git a/src/Illuminate/Console/composer.json b/src/Illuminate/Console/composer.json index 55f104571a7f..0643c70fbc17 100755 --- a/src/Illuminate/Console/composer.json +++ b/src/Illuminate/Console/composer.json @@ -31,7 +31,7 @@ } }, "suggest": { - "dragonmantank/cron-expression": "Required to use scheduler (^2.0).", + "dragonmantank/cron-expression": "Required to use scheduler (^2.3.1).", "guzzlehttp/guzzle": "Required to use the ping methods on schedules (^6.0|^7.0).", "illuminate/bus": "Required to use the scheduled job dispatcher (^6.0)", "illuminate/container": "Required to use the scheduler (^6.0)", diff --git a/src/Illuminate/Container/BoundMethod.php b/src/Illuminate/Container/BoundMethod.php index 8b53f71a331d..0afbd104c3c1 100644 --- a/src/Illuminate/Container/BoundMethod.php +++ b/src/Illuminate/Container/BoundMethod.php @@ -28,9 +28,7 @@ public static function call($container, $callback, array $parameters = [], $defa } return static::callBoundMethod($container, $callback, function () use ($container, $callback, $parameters) { - return call_user_func_array( - $callback, static::getMethodDependencies($container, $callback, $parameters) - ); + return $callback(...static::getMethodDependencies($container, $callback, $parameters)); }); } @@ -121,7 +119,7 @@ protected static function getMethodDependencies($container, $callback, array $pa static::addDependencyForCallParameter($container, $parameter, $parameters, $dependencies); } - return array_merge($dependencies, $parameters); + return array_merge($dependencies, array_values($parameters)); } /** diff --git a/src/Illuminate/Cookie/CookieJar.php b/src/Illuminate/Cookie/CookieJar.php index a880e898eb43..337435a74688 100755 --- a/src/Illuminate/Cookie/CookieJar.php +++ b/src/Illuminate/Cookie/CookieJar.php @@ -143,7 +143,7 @@ public function queue(...$parameters) if (head($parameters) instanceof Cookie) { $cookie = head($parameters); } else { - $cookie = call_user_func_array([$this, 'make'], $parameters); + $cookie = $this->make(...array_values($parameters)); } if (! isset($this->queued[$cookie->getName()])) { diff --git a/src/Illuminate/Database/Eloquent/Builder.php b/src/Illuminate/Database/Eloquent/Builder.php index aecbfa72d48c..ef7ac588dbd8 100755 --- a/src/Illuminate/Database/Eloquent/Builder.php +++ b/src/Illuminate/Database/Eloquent/Builder.php @@ -1359,14 +1359,16 @@ public function __call($method, $parameters) } if (static::hasGlobalMacro($method)) { - if (static::$macros[$method] instanceof Closure) { - return call_user_func_array(static::$macros[$method]->bindTo($this, static::class), $parameters); + $callable = static::$macros[$method]; + + if ($callable instanceof Closure) { + $callable = $callable->bindTo($this, static::class); } - return call_user_func_array(static::$macros[$method], $parameters); + return $callable(...$parameters); } - if (method_exists($this->model, $scope = 'scope'.ucfirst($method))) { + if ($this->model !== null && method_exists($this->model, $scope = 'scope'.ucfirst($method))) { return $this->callScope([$this->model, $scope], $parameters); } @@ -1404,11 +1406,13 @@ public static function __callStatic($method, $parameters) static::throwBadMethodCallException($method); } - if (static::$macros[$method] instanceof Closure) { - return call_user_func_array(Closure::bind(static::$macros[$method], null, static::class), $parameters); + $callable = static::$macros[$method]; + + if ($callable instanceof Closure) { + $callable = $callable->bindTo(null, static::class); } - return call_user_func_array(static::$macros[$method], $parameters); + return $callable(...$parameters); } /** diff --git a/src/Illuminate/Database/Eloquent/Collection.php b/src/Illuminate/Database/Eloquent/Collection.php index 7201603a9b33..2bb93f1e1def 100755 --- a/src/Illuminate/Database/Eloquent/Collection.php +++ b/src/Illuminate/Database/Eloquent/Collection.php @@ -451,7 +451,7 @@ public function keys() */ public function zip($items) { - return call_user_func_array([$this->toBase(), 'zip'], func_get_args()); + return $this->toBase()->zip(...func_get_args()); } /** diff --git a/src/Illuminate/Database/Eloquent/Relations/Concerns/InteractsWithPivotTable.php b/src/Illuminate/Database/Eloquent/Relations/Concerns/InteractsWithPivotTable.php index 4894103d202a..c6812b75a150 100644 --- a/src/Illuminate/Database/Eloquent/Relations/Concerns/InteractsWithPivotTable.php +++ b/src/Illuminate/Database/Eloquent/Relations/Concerns/InteractsWithPivotTable.php @@ -537,11 +537,11 @@ public function newPivotQuery() $query = $this->newPivotStatement(); foreach ($this->pivotWheres as $arguments) { - call_user_func_array([$query, 'where'], $arguments); + $query->where(...$arguments); } foreach ($this->pivotWhereIns as $arguments) { - call_user_func_array([$query, 'whereIn'], $arguments); + $query->whereIn(...$arguments); } return $query->where($this->foreignPivotKey, $this->parent->{$this->parentKey}); diff --git a/src/Illuminate/Database/MigrationServiceProvider.php b/src/Illuminate/Database/MigrationServiceProvider.php index f9bded758358..efd5f836c866 100755 --- a/src/Illuminate/Database/MigrationServiceProvider.php +++ b/src/Illuminate/Database/MigrationServiceProvider.php @@ -102,7 +102,7 @@ protected function registerCreator() protected function registerCommands(array $commands) { foreach (array_keys($commands) as $command) { - call_user_func_array([$this, "register{$command}Command"], []); + $this->{"register{$command}Command"}(); } $this->commands(array_values($commands)); diff --git a/src/Illuminate/Database/Schema/Grammars/RenameColumn.php b/src/Illuminate/Database/Schema/Grammars/RenameColumn.php index 3fe9fd8fbb10..fd54fb28df14 100644 --- a/src/Illuminate/Database/Schema/Grammars/RenameColumn.php +++ b/src/Illuminate/Database/Schema/Grammars/RenameColumn.php @@ -61,9 +61,22 @@ protected static function getRenamedDiff(Grammar $grammar, Blueprint $blueprint, protected static function setRenamedColumns(TableDiff $tableDiff, Fluent $command, Column $column) { $tableDiff->renamedColumns = [ - $command->from => new Column($command->to, $column->getType(), $column->toArray()), + $command->from => new Column($command->to, $column->getType(), self::getWritableColumnOptions($column)), ]; return $tableDiff; } + + /** + * Get the writable column options. + * + * @param \Doctrine\DBAL\Schema\Column $column + * @return array + */ + private static function getWritableColumnOptions(Column $column) + { + return array_filter($column->toArray(), function (string $name) use ($column) { + return method_exists($column, 'set'.$name); + }, ARRAY_FILTER_USE_KEY); + } } diff --git a/src/Illuminate/Events/CallQueuedListener.php b/src/Illuminate/Events/CallQueuedListener.php index 5a88df56f8b4..c7fc821de584 100644 --- a/src/Illuminate/Events/CallQueuedListener.php +++ b/src/Illuminate/Events/CallQueuedListener.php @@ -89,17 +89,15 @@ public function handle(Container $container) $this->job, $container->make($this->class) ); - call_user_func_array( - [$handler, $this->method], $this->data - ); + $handler->{$this->method}(...array_values($this->data)); } /** * Set the job instance of the given class if necessary. * * @param \Illuminate\Contracts\Queue\Job $job - * @param mixed $instance - * @return mixed + * @param object $instance + * @return object */ protected function setJobInstanceIfNecessary(Job $job, $instance) { @@ -124,10 +122,10 @@ public function failed($e) $handler = Container::getInstance()->make($this->class); - $parameters = array_merge($this->data, [$e]); + $parameters = array_merge(array_values($this->data), [$e]); if (method_exists($handler, 'failed')) { - call_user_func_array([$handler, 'failed'], $parameters); + $handler->failed(...$parameters); } } diff --git a/src/Illuminate/Events/Dispatcher.php b/src/Illuminate/Events/Dispatcher.php index 21dc14ab9e88..0d0173e3cbb9 100755 --- a/src/Illuminate/Events/Dispatcher.php +++ b/src/Illuminate/Events/Dispatcher.php @@ -384,9 +384,9 @@ public function createClassListener($listener, $wildcard = false) return call_user_func($this->createClassCallable($listener), $event, $payload); } - return call_user_func_array( - $this->createClassCallable($listener), $payload - ); + $callable = $this->createClassCallable($listener); + + return $callable(...array_values($payload)); }; } diff --git a/src/Illuminate/Filesystem/FilesystemAdapter.php b/src/Illuminate/Filesystem/FilesystemAdapter.php index d3d62194b251..e4b917c0d405 100644 --- a/src/Illuminate/Filesystem/FilesystemAdapter.php +++ b/src/Illuminate/Filesystem/FilesystemAdapter.php @@ -739,6 +739,6 @@ protected function parseVisibility($visibility) */ public function __call($method, array $parameters) { - return call_user_func_array([$this->driver, $method], $parameters); + return $this->driver->{$method}(...array_values($parameters)); } } diff --git a/src/Illuminate/Filesystem/composer.json b/src/Illuminate/Filesystem/composer.json index 010622d88b80..b21e461a946b 100644 --- a/src/Illuminate/Filesystem/composer.json +++ b/src/Illuminate/Filesystem/composer.json @@ -31,7 +31,7 @@ }, "suggest": { "ext-ftp": "Required to use the Flysystem FTP driver.", - "league/flysystem": "Required to use the Flysystem local and FTP drivers (^1.0.34).", + "league/flysystem": "Required to use the Flysystem local and FTP drivers (^1.1).", "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^1.0).", "league/flysystem-cached-adapter": "Required to use the Flysystem cache (^1.0).", "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (^1.0).", diff --git a/src/Illuminate/Foundation/Console/QueuedCommand.php b/src/Illuminate/Foundation/Console/QueuedCommand.php index 67749ee938dd..fb3d027b4b0a 100644 --- a/src/Illuminate/Foundation/Console/QueuedCommand.php +++ b/src/Illuminate/Foundation/Console/QueuedCommand.php @@ -37,6 +37,6 @@ public function __construct($data) */ public function handle(KernelContract $kernel) { - call_user_func_array([$kernel, 'call'], $this->data); + $kernel->call(...array_values($this->data)); } } diff --git a/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php b/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php index 66aeb5121141..7c33b8d5da91 100755 --- a/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php +++ b/src/Illuminate/Foundation/Providers/ArtisanServiceProvider.php @@ -168,7 +168,7 @@ public function register() protected function registerCommands(array $commands) { foreach (array_keys($commands) as $command) { - call_user_func_array([$this, "register{$command}Command"], []); + $this->{"register{$command}Command"}(); } $this->commands(array_values($commands)); diff --git a/src/Illuminate/Http/ResponseTrait.php b/src/Illuminate/Http/ResponseTrait.php index 76744b487fb8..0858b40e2494 100644 --- a/src/Illuminate/Http/ResponseTrait.php +++ b/src/Illuminate/Http/ResponseTrait.php @@ -96,7 +96,7 @@ public function withHeaders($headers) */ public function cookie($cookie) { - return call_user_func_array([$this, 'withCookie'], func_get_args()); + return $this->withCookie(...func_get_args()); } /** @@ -108,7 +108,7 @@ public function cookie($cookie) public function withCookie($cookie) { if (is_string($cookie) && function_exists('cookie')) { - $cookie = call_user_func_array('cookie', func_get_args()); + $cookie = cookie(...func_get_args()); } $this->headers->setCookie($cookie); diff --git a/src/Illuminate/Queue/composer.json b/src/Illuminate/Queue/composer.json index a2bc8c461d20..7ef8dd89070e 100644 --- a/src/Illuminate/Queue/composer.json +++ b/src/Illuminate/Queue/composer.json @@ -23,7 +23,7 @@ "illuminate/filesystem": "^6.0", "illuminate/pipeline": "^6.0", "illuminate/support": "^6.0", - "opis/closure": "^3.1", + "opis/closure": "^3.6", "symfony/debug": "^4.3.4", "symfony/process": "^4.3.4" }, diff --git a/src/Illuminate/Redis/Connections/PredisConnection.php b/src/Illuminate/Redis/Connections/PredisConnection.php index 665f328b0e9e..932982562ba5 100644 --- a/src/Illuminate/Redis/Connections/PredisConnection.php +++ b/src/Illuminate/Redis/Connections/PredisConnection.php @@ -42,7 +42,7 @@ public function createSubscription($channels, Closure $callback, $method = 'subs { $loop = $this->pubSubLoop(); - call_user_func_array([$loop, $method], (array) $channels); + $loop->{$method}(...array_values((array) $channels)); foreach ($loop as $message) { if ($message->kind === 'message' || $message->kind === 'pmessage') { diff --git a/src/Illuminate/Routing/Controller.php b/src/Illuminate/Routing/Controller.php index 50de9712294f..a26a5ee7effa 100644 --- a/src/Illuminate/Routing/Controller.php +++ b/src/Illuminate/Routing/Controller.php @@ -51,7 +51,7 @@ public function getMiddleware() */ public function callAction($method, $parameters) { - return call_user_func_array([$this, $method], $parameters); + return $this->{$method}(...array_values($parameters)); } /** diff --git a/src/Illuminate/Routing/Pipeline.php b/src/Illuminate/Routing/Pipeline.php index 63d59ad93a33..3d4a684cf39a 100644 --- a/src/Illuminate/Routing/Pipeline.php +++ b/src/Illuminate/Routing/Pipeline.php @@ -50,7 +50,7 @@ protected function handleException($passable, Exception $e) $response = $handler->render($passable, $e); - if (method_exists($response, 'withException')) { + if (is_object($response) && method_exists($response, 'withException')) { $response->withException($e); } diff --git a/src/Illuminate/Routing/Route.php b/src/Illuminate/Routing/Route.php index 2d854ef95964..9b31e619fea9 100755 --- a/src/Illuminate/Routing/Route.php +++ b/src/Illuminate/Routing/Route.php @@ -790,9 +790,9 @@ public function gatherMiddleware() $this->computedMiddleware = []; - return $this->computedMiddleware = array_unique(array_merge( + return $this->computedMiddleware = Router::uniqueMiddleware(array_merge( $this->middleware(), $this->controllerMiddleware() - ), SORT_REGULAR); + )); } /** diff --git a/src/Illuminate/Routing/Router.php b/src/Illuminate/Routing/Router.php index e7f0b58a4a43..8e762351ee8f 100644 --- a/src/Illuminate/Routing/Router.php +++ b/src/Illuminate/Routing/Router.php @@ -1273,6 +1273,29 @@ public function setRoutes(RouteCollection $routes) $this->container->instance('routes', $this->routes); } + /** + * Remove any duplicate middleware from the given array. + * + * @param array $middleware + * @return array + */ + public static function uniqueMiddleware(array $middleware) + { + $seen = []; + $result = []; + + foreach ($middleware as $value) { + $key = \is_object($value) ? \spl_object_id($value) : $value; + + if (! isset($seen[$key])) { + $seen[$key] = true; + $result[] = $value; + } + } + + return $result; + } + /** * Dynamically handle calls into the router instance. * diff --git a/src/Illuminate/Routing/SortedMiddleware.php b/src/Illuminate/Routing/SortedMiddleware.php index f384603387f8..57dbb0730a38 100644 --- a/src/Illuminate/Routing/SortedMiddleware.php +++ b/src/Illuminate/Routing/SortedMiddleware.php @@ -62,7 +62,7 @@ protected function sortMiddleware($priorityMap, $middlewares) } } - return array_values(array_unique($middlewares, SORT_REGULAR)); + return Router::uniqueMiddleware($middlewares); } /** diff --git a/src/Illuminate/Support/Collection.php b/src/Illuminate/Support/Collection.php index 91102f6862d2..b9d4ebb7d82b 100644 --- a/src/Illuminate/Support/Collection.php +++ b/src/Illuminate/Support/Collection.php @@ -1210,7 +1210,7 @@ public function zip($items) return new static(func_get_args()); }, $this->items], $arrayableItems); - return new static(call_user_func_array('array_map', $params)); + return new static(array_map(...$params)); } /** diff --git a/src/Illuminate/Support/Str.php b/src/Illuminate/Support/Str.php index 8ff6d4cacfdd..3497e851caf0 100644 --- a/src/Illuminate/Support/Str.php +++ b/src/Illuminate/Support/Str.php @@ -455,6 +455,10 @@ public static function replaceFirst($search, $replace, $subject) */ public static function replaceLast($search, $replace, $subject) { + if ($search === '') { + return $subject; + } + $position = strrpos($subject, $search); if ($position !== false) { diff --git a/src/Illuminate/Support/Traits/EnumeratesValues.php b/src/Illuminate/Support/Traits/EnumeratesValues.php index a32b51803bc3..f7e9bfc60a63 100644 --- a/src/Illuminate/Support/Traits/EnumeratesValues.php +++ b/src/Illuminate/Support/Traits/EnumeratesValues.php @@ -143,7 +143,7 @@ public function containsStrict($key, $value = null) */ public function dd(...$args) { - call_user_func_array([$this, 'dump'], $args); + $this->dump(...$args); exit(1); } diff --git a/src/Illuminate/Support/Traits/Macroable.php b/src/Illuminate/Support/Traits/Macroable.php index 0c2112c7fba5..406f65edc79b 100644 --- a/src/Illuminate/Support/Traits/Macroable.php +++ b/src/Illuminate/Support/Traits/Macroable.php @@ -82,7 +82,7 @@ public static function __callStatic($method, $parameters) $macro = static::$macros[$method]; if ($macro instanceof Closure) { - return call_user_func_array(Closure::bind($macro, null, static::class), $parameters); + $macro = $macro->bindTo(null, static::class); } return $macro(...$parameters); @@ -108,7 +108,7 @@ public function __call($method, $parameters) $macro = static::$macros[$method]; if ($macro instanceof Closure) { - return call_user_func_array($macro->bindTo($this, static::class), $parameters); + $macro = $macro->bindTo($this, static::class); } return $macro(...$parameters); diff --git a/src/Illuminate/Support/composer.json b/src/Illuminate/Support/composer.json index 828c6e7f95b3..1ac5b7447e7e 100644 --- a/src/Illuminate/Support/composer.json +++ b/src/Illuminate/Support/composer.json @@ -19,7 +19,7 @@ "ext-mbstring": "*", "doctrine/inflector": "^1.4|^2.0", "illuminate/contracts": "^6.0", - "nesbot/carbon": "^2.0" + "nesbot/carbon": "^2.31" }, "conflict": { "tightenco/collect": "<5.5.33" diff --git a/src/Illuminate/Validation/Concerns/FormatsMessages.php b/src/Illuminate/Validation/Concerns/FormatsMessages.php index 8ee3f0aee3bd..9d011892aaf7 100644 --- a/src/Illuminate/Validation/Concerns/FormatsMessages.php +++ b/src/Illuminate/Validation/Concerns/FormatsMessages.php @@ -374,7 +374,7 @@ protected function callReplacer($message, $attribute, $rule, $parameters, $valid $callback = $this->replacers[$rule]; if ($callback instanceof Closure) { - return call_user_func_array($callback, func_get_args()); + return $callback(...func_get_args()); } elseif (is_string($callback)) { return $this->callClassBasedReplacer($callback, $message, $attribute, $rule, $parameters, $validator); } @@ -395,6 +395,6 @@ protected function callClassBasedReplacer($callback, $message, $attribute, $rule { [$class, $method] = Str::parseCallback($callback, 'replace'); - return call_user_func_array([$this->container->make($class), $method], array_slice(func_get_args(), 1)); + return $this->container->make($class)->{$method}(...array_slice(func_get_args(), 1)); } } diff --git a/src/Illuminate/Validation/Validator.php b/src/Illuminate/Validation/Validator.php index df06c5077dbf..582075e7cba5 100755 --- a/src/Illuminate/Validation/Validator.php +++ b/src/Illuminate/Validation/Validator.php @@ -280,7 +280,7 @@ public function parseData(array $data) public function after($callback) { $this->after[] = function () use ($callback) { - return call_user_func_array($callback, [$this]); + return $callback($this); }; return $this; @@ -1268,7 +1268,7 @@ protected function callExtension($rule, $parameters) $callback = $this->extensions[$rule]; if (is_callable($callback)) { - return call_user_func_array($callback, $parameters); + return $callback(...array_values($parameters)); } elseif (is_string($callback)) { return $this->callClassBasedExtension($callback, $parameters); } @@ -1285,7 +1285,7 @@ protected function callClassBasedExtension($callback, $parameters) { [$class, $method] = Str::parseCallback($callback, 'validate'); - return call_user_func_array([$this->container->make($class), $method], $parameters); + return $this->container->make($class)->{$method}(...array_values($parameters)); } /** diff --git a/src/Illuminate/View/Concerns/ManagesEvents.php b/src/Illuminate/View/Concerns/ManagesEvents.php index 1889a6b6fdaa..39902905de09 100644 --- a/src/Illuminate/View/Concerns/ManagesEvents.php +++ b/src/Illuminate/View/Concerns/ManagesEvents.php @@ -121,9 +121,7 @@ protected function buildClassEventCallback($class, $prefix) // the instance out of the IoC container and call the method on it with the // given arguments that are passed to the Closure as the composer's data. return function () use ($class, $method) { - return call_user_func_array( - [$this->container->make($class), $method], func_get_args() - ); + return $this->container->make($class)->{$method}(...func_get_args()); }; } diff --git a/tests/Container/ContainerCallTest.php b/tests/Container/ContainerCallTest.php index fe8d6b96c1e8..bd5a4ca826dd 100644 --- a/tests/Container/ContainerCallTest.php +++ b/tests/Container/ContainerCallTest.php @@ -3,17 +3,17 @@ namespace Illuminate\Tests\Container; use Closure; +use Error; use Illuminate\Container\Container; use PHPUnit\Framework\TestCase; -use ReflectionException; use stdClass; class ContainerCallTest extends TestCase { public function testCallWithAtSignBasedClassReferencesWithoutMethodThrowsException() { - $this->expectException(ReflectionException::class); - $this->expectExceptionMessage('Function ContainerTestCallStub() does not exist'); + $this->expectException(Error::class); + $this->expectExceptionMessage('Call to undefined function ContainerTestCallStub()'); $container = new Container; $container->call('ContainerTestCallStub'); diff --git a/tests/Database/DatabaseConnectionTest.php b/tests/Database/DatabaseConnectionTest.php index ae9ab5007961..7baf935716dc 100755 --- a/tests/Database/DatabaseConnectionTest.php +++ b/tests/Database/DatabaseConnectionTest.php @@ -60,7 +60,10 @@ public function testSelectProperlyCallsPDO() $pdo = $this->getMockBuilder(DatabaseConnectionTestMockPDO::class)->setMethods(['prepare'])->getMock(); $writePdo = $this->getMockBuilder(DatabaseConnectionTestMockPDO::class)->setMethods(['prepare'])->getMock(); $writePdo->expects($this->never())->method('prepare'); - $statement = $this->getMockBuilder('PDOStatement')->setMethods(['execute', 'fetchAll', 'bindValue'])->getMock(); + $statement = $this->getMockBuilder('PDOStatement') + ->setMethods(['setFetchMode', 'execute', 'fetchAll', 'bindValue']) + ->getMock(); + $statement->expects($this->once())->method('setFetchMode'); $statement->expects($this->once())->method('bindValue')->with('foo', 'bar', 2); $statement->expects($this->once())->method('execute'); $statement->expects($this->once())->method('fetchAll')->willReturn(['boom']); @@ -178,6 +181,7 @@ public function testBeginTransactionMethodNeverRetriesIfWithinTransaction() $pdo->expects($this->once())->method('exec')->will($this->throwException(new Exception)); $connection = $this->getMockConnection(['reconnect'], $pdo); $queryGrammar = $this->createMock(Grammar::class); + $queryGrammar->expects($this->once())->method('compileSavepoint')->willReturn('trans1'); $queryGrammar->expects($this->once())->method('supportsSavepoints')->willReturn(true); $connection->setQueryGrammar($queryGrammar); $connection->expects($this->never())->method('reconnect'); diff --git a/tests/Database/DatabaseEloquentBelongsToTest.php b/tests/Database/DatabaseEloquentBelongsToTest.php index d362e4680307..06b2087ff395 100755 --- a/tests/Database/DatabaseEloquentBelongsToTest.php +++ b/tests/Database/DatabaseEloquentBelongsToTest.php @@ -77,10 +77,16 @@ public function testEagerConstraintsAreProperlyAdded() public function testIdsInEagerConstraintsCanBeZero() { + $keys = ['foreign.value', 0]; + + if (version_compare(PHP_VERSION, '8.0.0-dev', '>=')) { + sort($keys); + } + $relation = $this->getRelation(); $relation->getRelated()->shouldReceive('getKeyName')->andReturn('id'); $relation->getRelated()->shouldReceive('getKeyType')->andReturn('int'); - $relation->getQuery()->shouldReceive('whereIntegerInRaw')->once()->with('relation.id', ['foreign.value', 0]); + $relation->getQuery()->shouldReceive('whereIntegerInRaw')->once()->with('relation.id', $keys); $models = [new EloquentBelongsToModelStub, new EloquentBelongsToModelStubWithZeroId]; $relation->addEagerConstraints($models); } diff --git a/tests/Database/DatabaseEloquentBuilderTest.php b/tests/Database/DatabaseEloquentBuilderTest.php index 0b4530802a9d..2c40e2106a0e 100755 --- a/tests/Database/DatabaseEloquentBuilderTest.php +++ b/tests/Database/DatabaseEloquentBuilderTest.php @@ -449,7 +449,9 @@ public function testGlobalMacrosAreCalledOnBuilder() return $bar; }); - Builder::macro('bam', [Builder::class, 'getQuery']); + Builder::macro('bam', function () { + return $this->getQuery(); + }); $builder = $this->getBuilder(); diff --git a/tests/Integration/Auth/ApiAuthenticationWithEloquentTest.php b/tests/Integration/Auth/ApiAuthenticationWithEloquentTest.php index 9966fbea6d5d..cf6c6cc5246f 100644 --- a/tests/Integration/Auth/ApiAuthenticationWithEloquentTest.php +++ b/tests/Integration/Auth/ApiAuthenticationWithEloquentTest.php @@ -8,6 +8,9 @@ use Illuminate\Support\Str; use Orchestra\Testbench\TestCase; +/** + * @requires extension pdo_mysql + */ class ApiAuthenticationWithEloquentTest extends TestCase { protected function getEnvironmentSetUp($app) diff --git a/tests/Integration/Database/DatabaseEmulatePreparesMySqlConnectionTest.php b/tests/Integration/Database/DatabaseEmulatePreparesMySqlConnectionTest.php index 65e71ebdb908..bd71a5865c29 100755 --- a/tests/Integration/Database/DatabaseEmulatePreparesMySqlConnectionTest.php +++ b/tests/Integration/Database/DatabaseEmulatePreparesMySqlConnectionTest.php @@ -4,6 +4,9 @@ use PDO; +/** + * @requires extension pdo_mysql + */ class DatabaseEmulatePreparesMySqlConnectionTest extends DatabaseMySqlConnectionTest { protected function getEnvironmentSetUp($app) diff --git a/tests/Integration/Database/DatabaseMySqlConnectionTest.php b/tests/Integration/Database/DatabaseMySqlConnectionTest.php index d0ce732573e1..0ca3d3f69a0f 100644 --- a/tests/Integration/Database/DatabaseMySqlConnectionTest.php +++ b/tests/Integration/Database/DatabaseMySqlConnectionTest.php @@ -7,6 +7,9 @@ use Illuminate\Support\Facades\Schema; use Orchestra\Testbench\TestCase; +/** + * @requires extension pdo_mysql + */ class DatabaseMySqlConnectionTest extends TestCase { const TABLE = 'player';