Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: laravel/framework
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: c581caa
Choose a base ref
...
head repository: laravel/framework
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 91ec2d9
Choose a head ref
  • 20 commits
  • 37 files changed
  • 17 contributors

Commits on Nov 29, 2023

  1. Add trait to (#49172)

    khalilst authored Nov 29, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    d80af24 View commit details
  2. [10.x] Add --generate-secret option to Artisan down command. (#49171

    )
    
    * Add option to Artisan `down` command to generate a secret phrase.
    
    * Revise sentence.
    
    * Use `Str::random()` helper instead.
    
    * Rename `getSecretPhrase()` to `getSecret()`.
    
    * Fix spelling.
    
    * Move import statement.
    
    * formatting
    
    ---------
    
    Co-authored-by: Taylor Otwell <taylor@laravel.com>
    jj15asmr and taylorotwell authored Nov 29, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    3d2c03d View commit details
  3. Apply fixes from StyleCI

    StyleCIBot committed Nov 29, 2023

    Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    StyleCIBot StyleCI Bot
    Copy the full SHA
    0c574d4 View commit details

Commits on Nov 30, 2023

  1. [10.x] Add support for Number::summarize (#49197)

    * Add Number::summarize
    
    * Update comment
    
    * Make units configurable
    
    * Make end unit dynamic
    
    * Remove named arguments to be consistent with other method calls
    
    * CS fix
    
    * Fix tests
    
    * Fix tests
    
    * Fix tests
    
    * formatting
    
    * format
    
    ---------
    
    Co-authored-by: Taylor Otwell <taylor@laravel.com>
    jcsoriano and taylorotwell authored Nov 30, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    5172665 View commit details
  2. [10.x]: Add Blade @use directive (#49179)

    * Add Blade @use directive
    
    * Allow for `use` without `as`
    
    * Update CompilesUseStatements.php
    
    ---------
    
    Co-authored-by: Taylor Otwell <taylor@laravel.com>
    simonhamp and taylorotwell authored Nov 30, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e4ffa95 View commit details
  3. [10.x] Fixes retrying failed jobs causes PHP memory exhaustion errors…

    … when dealing with thousands of failed jobs (#49186)
    
    * [10.x] Fixes retrying failed jobs causes PHP memory exhaustion errors when dealing with thousands of failed jobs
    
    fixes #49185
    
    Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>
    
    * Apply fixes from StyleCI
    
    * formatting
    
    ---------
    
    Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>
    Co-authored-by: StyleCI Bot <bot@styleci.io>
    Co-authored-by: Taylor Otwell <taylor@laravel.com>
    3 people authored Nov 30, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    2b9d596 View commit details
  4. [10.x] Add "substituteImplicitBindingsUsing" method to router (#49200)

    * Add "substituteImplicitBindingsUsing" method to router
    
    * Remove un-used test method
    
    * formatting
    
    * simplify code
    
    ---------
    
    Co-authored-by: Taylor Otwell <taylor@laravel.com>
    calebporzio and taylorotwell authored Nov 30, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    ccf8beb View commit details
  5. Apply fixes from StyleCI

    StyleCIBot committed Nov 30, 2023

    Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    StyleCIBot StyleCI Bot
    Copy the full SHA
    378e4b3 View commit details
  6. [10.x] Cookies Having Independent Partitioned State (CHIPS) (#48745)

    * [10.x] Cookies Having Independent Partitioned State (CHIPS)
    
    * Clean up cookie duplication
    
    * Bump components symfony/http-foundation version
    fabricecw authored Nov 30, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    bd30b02 View commit details
  7. Update facade docblocks

    taylorotwell authored and github-actions[bot] committed Nov 30, 2023
    Copy the full SHA
    e574ffa View commit details

Commits on Dec 1, 2023

  1. Update InteractsWithDictionary.php to use base InvalidArgumentExcepti…

    …on (#49209)
    
    use base InvalidArgumentException instead of \Doctrine\Instantiator\Exception\InvalidArgumentException
    Grldk authored Dec 1, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    8b94c3e View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    a91c3f4 View commit details
  3. [10.x] Fix loss of attributes after calling child component (#49216)

    * Store and restore original attributes when rendering component
    
    * Move attribute assertion to mock
    
    This is needed because the original attributes are now restored after
    rendering a component.
    
    * Assert withAttribute params on child component prop
    
    * Fix assertion
    
    * Add assertion to ensure original attributes are restored
    rojtjo authored Dec 1, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    37cb345 View commit details

Commits on Dec 4, 2023

  1. [10.x] Fix typo in PHPDoc comment (#49234)

    Fixes a typo in a helper method comment (`exntension` => `extension`)
    caendesilva authored Dec 4, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    c59ef1f View commit details
  2. [10.x] league/flysystem 3.22.0 now prefer inclusive mime-type inste…

    …ad of `null`. (#49229)
    
    * [10.x] Test Improvements
    
    Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>
    
    * wip
    
    Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>
    
    * Apply fixes from StyleCI
    
    * wip
    
    Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>
    
    ---------
    
    Signed-off-by: Mior Muhammad Zaki <crynobone@gmail.com>
    Co-authored-by: StyleCI Bot <bot@styleci.io>
    crynobone and StyleCIBot authored Dec 4, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    0947618 View commit details
  3. Revert "[10.x] league/flysystem 3.22.0 now prefer inclusive mime-ty…

    …pe instead of `null`. (#49229)" (#49235)
    
    This reverts commit 0947618.
    driesvints authored Dec 4, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    be526ee View commit details
  4. [10.x] Determine if the given view exists. (#49231)

    * add `Schema::hasView()`
    
    * override `Schema::hasTable()` on SQL Server
    
    * add a test
    
    * formatting
    
    ---------
    
    Co-authored-by: Taylor Otwell <taylor@laravel.com>
    hafezdivandari and taylorotwell authored Dec 4, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    484e9c2 View commit details

Commits on Dec 5, 2023

  1. Update CHANGELOG

    driesvints authored and github-actions[bot] committed Dec 5, 2023

    Unverified

    This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
    Copy the full SHA
    8efb323 View commit details
  2. Update CHANGELOG

    driesvints authored and github-actions[bot] committed Dec 5, 2023

    Unverified

    This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
    Copy the full SHA
    5f00326 View commit details
  3. version

    taylorotwell committed Dec 5, 2023
    Copy the full SHA
    91ec2d9 View commit details
Showing with 439 additions and 43 deletions.
  1. +10 −1 CHANGELOG.md
  2. +1 −1 composer.json
  3. +1 −5 src/Illuminate/Cookie/Middleware/EncryptCookies.php
  4. +1 −1 src/Illuminate/Cookie/composer.json
  5. +1 −1 src/Illuminate/Database/Eloquent/Model.php
  6. +2 −2 src/Illuminate/Database/Eloquent/Relations/Concerns/InteractsWithDictionary.php
  7. +19 −0 src/Illuminate/Database/Schema/Builder.php
  8. +1 −1 src/Illuminate/Foundation/Application.php
  9. +24 −2 src/Illuminate/Foundation/Console/DownCommand.php
  10. +2 −1 src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php
  11. +1 −1 src/Illuminate/Http/composer.json
  12. +13 −5 src/Illuminate/Queue/Console/RetryCommand.php
  13. +15 −0 src/Illuminate/Queue/Failed/DatabaseFailedJobProvider.php
  14. +15 −0 src/Illuminate/Queue/Failed/DatabaseUuidFailedJobProvider.php
  15. +14 −0 src/Illuminate/Queue/Failed/DynamoDbFailedJobProvider.php
  16. +3 −0 src/Illuminate/Queue/Failed/FailedJobProviderInterface.php
  17. +14 −0 src/Illuminate/Queue/Failed/FileFailedJobProvider.php
  18. +11 −0 src/Illuminate/Queue/Failed/NullFailedJobProvider.php
  19. +25 −1 src/Illuminate/Routing/Router.php
  20. +1 −1 src/Illuminate/Routing/composer.json
  21. +10 −3 src/Illuminate/Session/Middleware/StartSession.php
  22. +1 −1 src/Illuminate/Session/composer.json
  23. +1 −0 src/Illuminate/Support/Facades/Route.php
  24. +1 −0 src/Illuminate/Support/Facades/Schema.php
  25. +53 −12 src/Illuminate/Support/Number.php
  26. +2 −0 src/Illuminate/Testing/Fluent/AssertableJson.php
  27. +2 −1 src/Illuminate/Testing/TestResponse.php
  28. +1 −1 src/Illuminate/Validation/composer.json
  29. +1 −0 src/Illuminate/View/Compilers/BladeCompiler.php
  30. +5 −0 src/Illuminate/View/Compilers/Concerns/CompilesComponents.php
  31. +22 −0 src/Illuminate/View/Compilers/Concerns/CompilesUseStatements.php
  32. +7 −0 tests/Integration/Database/SchemaBuilderTest.php
  33. +21 −0 tests/Routing/RoutingRouteTest.php
  34. +53 −0 tests/Support/SupportNumberTest.php
  35. +60 −2 tests/View/Blade/BladeComponentTagCompilerTest.php
  36. +5 −0 tests/View/Blade/BladeComponentsTest.php
  37. +20 −0 tests/View/Blade/BladeUseTest.php
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
# Release Notes for 10.x

## [Unreleased](https://github.com/laravel/framework/compare/v10.34.0...10.x)
## [Unreleased](https://github.com/laravel/framework/compare/v10.34.2...10.x)

## [v10.34.2](https://github.com/laravel/framework/compare/v10.34.1...v10.34.2) - 2023-11-28

* [v10.x] Add missing methods to newly extended fake `Vite` instance by [@stevebauman](https://github.com/stevebauman) in https://github.com/laravel/framework/pull/49165

## [v10.34.1](https://github.com/laravel/framework/compare/v10.34.0...v10.34.1) - 2023-11-28

* [10.x] Streamline `DatabaseMigrations` and `RefreshDatabase` events by [@crynobone](https://github.com/crynobone) in https://github.com/laravel/framework/pull/49153
* [10.x] Use HtmlString in Vite fake by [@jasonvarga](https://github.com/jasonvarga) in https://github.com/laravel/framework/pull/49163

## [v10.34.0](https://github.com/laravel/framework/compare/v10.33.0...v10.34.0) - 2023-11-28

2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -44,7 +44,7 @@
"symfony/console": "^6.2",
"symfony/error-handler": "^6.2",
"symfony/finder": "^6.2",
"symfony/http-foundation": "^6.3",
"symfony/http-foundation": "^6.4",
"symfony/http-kernel": "^6.2",
"symfony/mailer": "^6.2",
"symfony/mime": "^6.2",
6 changes: 1 addition & 5 deletions src/Illuminate/Cookie/Middleware/EncryptCookies.php
Original file line number Diff line number Diff line change
@@ -195,11 +195,7 @@ protected function encrypt(Response $response)
*/
protected function duplicate(Cookie $cookie, $value)
{
return new Cookie(
$cookie->getName(), $value, $cookie->getExpiresTime(),
$cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(),
$cookie->isHttpOnly(), $cookie->isRaw(), $cookie->getSameSite()
);
return $cookie->withValue($value);
}

/**
2 changes: 1 addition & 1 deletion src/Illuminate/Cookie/composer.json
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@
"illuminate/contracts": "^10.0",
"illuminate/macroable": "^10.0",
"illuminate/support": "^10.0",
"symfony/http-foundation": "^6.2",
"symfony/http-foundation": "^6.4",
"symfony/http-kernel": "^6.2"
},
"autoload": {
2 changes: 1 addition & 1 deletion src/Illuminate/Database/Eloquent/Model.php
Original file line number Diff line number Diff line change
@@ -106,7 +106,7 @@ abstract class Model implements Arrayable, ArrayAccess, CanBeEscapedWhenCastToSt
public $exists = false;

/**
* Indicates if the model was inserted during the current request lifecycle.
* Indicates if the model was inserted during the object's lifecycle.
*
* @var bool
*/
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
namespace Illuminate\Database\Eloquent\Relations\Concerns;

use BackedEnum;
use Doctrine\Instantiator\Exception\InvalidArgumentException;
use InvalidArgumentException;
use UnitEnum;

trait InteractsWithDictionary
@@ -14,7 +14,7 @@ trait InteractsWithDictionary
* @param mixed $attribute
* @return mixed
*
* @throws \Doctrine\Instantiator\Exception\InvalidArgumentException
* @throws \InvalidArgumentException
*/
protected function getDictionaryKey($attribute)
{
19 changes: 19 additions & 0 deletions src/Illuminate/Database/Schema/Builder.php
Original file line number Diff line number Diff line change
@@ -168,6 +168,25 @@ public function hasTable($table)
return false;
}

/**
* Determine if the given view exists.
*
* @param string $view
* @return bool
*/
public function hasView($view)
{
$view = $this->connection->getTablePrefix().$view;

foreach ($this->getViews() as $value) {
if (strtolower($view) === strtolower($value['name'])) {
return true;
}
}

return false;
}

/**
* Get the tables that belong to the database.
*
2 changes: 1 addition & 1 deletion src/Illuminate/Foundation/Application.php
Original file line number Diff line number Diff line change
@@ -38,7 +38,7 @@ class Application extends Container implements ApplicationContract, CachesConfig
*
* @var string
*/
const VERSION = '10.34.2';
const VERSION = '10.35.0';

/**
* The base path for the Laravel installation.
26 changes: 24 additions & 2 deletions src/Illuminate/Foundation/Console/DownCommand.php
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@
use Illuminate\Console\Command;
use Illuminate\Foundation\Events\MaintenanceModeEnabled;
use Illuminate\Foundation\Exceptions\RegisterErrorViewPaths;
use Illuminate\Support\Str;
use Symfony\Component\Console\Attribute\AsCommand;
use Throwable;

@@ -23,6 +24,7 @@ class DownCommand extends Command
{--retry= : The number of seconds after which the request may be retried}
{--refresh= : The number of seconds after which the browser may refresh}
{--secret= : The secret phrase that may be used to bypass maintenance mode}
{--with-secret : Generate a random secret phrase that may be used to bypass maintenance mode}
{--status=503 : The status code that should be used when returning the maintenance mode response}';

/**
@@ -46,7 +48,9 @@ public function handle()
return 0;
}

$this->laravel->maintenanceMode()->activate($this->getDownFilePayload());
$downFilePayload = $this->getDownFilePayload();

$this->laravel->maintenanceMode()->activate($downFilePayload);

file_put_contents(
storage_path('framework/maintenance.php'),
@@ -56,6 +60,10 @@ public function handle()
$this->laravel->get('events')->dispatch(new MaintenanceModeEnabled());

$this->components->info('Application is now in maintenance mode.');

if ($downFilePayload['secret'] !== null) {
$this->components->info('You may bypass maintenance mode via ['.config('app.url')."/{$downFilePayload['secret']}].");
}
} catch (Exception $e) {
$this->components->error(sprintf(
'Failed to enter maintenance mode: %s.',
@@ -78,7 +86,7 @@ protected function getDownFilePayload()
'redirect' => $this->redirectPath(),
'retry' => $this->getRetryTime(),
'refresh' => $this->option('refresh'),
'secret' => $this->option('secret'),
'secret' => $this->getSecret(),
'status' => (int) $this->option('status', 503),
'template' => $this->option('render') ? $this->prerenderView() : null,
];
@@ -137,4 +145,18 @@ protected function getRetryTime()

return is_numeric($retry) && $retry > 0 ? (int) $retry : null;
}

/**
* Get the secret phrase that may be used to bypass maintenance mode.
*
* @return string|null
*/
protected function getSecret()
{
return match (true) {
! is_null($this->option('secret')) => $this->option('secret'),
$this->option('with-secret') => Str::random(),
default => null,
};
}
}
Original file line number Diff line number Diff line change
@@ -211,7 +211,8 @@ protected function newCookie($request, $config)
$config['secure'],
false,
false,
$config['same_site'] ?? null
$config['same_site'] ?? null,
$config['partitioned'] ?? false
);
}

2 changes: 1 addition & 1 deletion src/Illuminate/Http/composer.json
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@
"illuminate/macroable": "^10.0",
"illuminate/session": "^10.0",
"illuminate/support": "^10.0",
"symfony/http-foundation": "^6.2",
"symfony/http-foundation": "^6.4",
"symfony/http-kernel": "^6.2",
"symfony/mime": "^6.2"
},
18 changes: 13 additions & 5 deletions src/Illuminate/Queue/Console/RetryCommand.php
Original file line number Diff line number Diff line change
@@ -70,7 +70,11 @@ protected function getJobIds()
$ids = (array) $this->argument('id');

if (count($ids) === 1 && $ids[0] === 'all') {
return Arr::pluck($this->laravel['queue.failer']->all(), 'id');
$failer = $this->laravel['queue.failer'];

return method_exists($failer, 'ids')
? $failer->ids()
: Arr::pluck($failer->all(), 'id');
}

if ($queue = $this->option('queue')) {
@@ -92,10 +96,14 @@ protected function getJobIds()
*/
protected function getJobIdsByQueue($queue)
{
$ids = collect($this->laravel['queue.failer']->all())
->where('queue', $queue)
->pluck('id')
->toArray();
$failer = $this->laravel['queue.failer'];

$ids = method_exists($failer, 'ids')
? $failer->ids($queue)
: collect($failer->all())
->where('queue', $queue)
->pluck('id')
->toArray();

if (count($ids) === 0) {
$this->components->error("Unable to find failed jobs for queue [{$queue}].");
15 changes: 15 additions & 0 deletions src/Illuminate/Queue/Failed/DatabaseFailedJobProvider.php
Original file line number Diff line number Diff line change
@@ -64,6 +64,21 @@ public function log($connection, $queue, $payload, $exception)
));
}

/**
* Get the IDs of all of the failed jobs.
*
* @param string|null $queue
* @return array
*/
public function ids($queue = null)
{
return $this->getTable()
->when(! is_null($queue), fn ($query) => $query->where('queue', $queue))
->orderBy('id', 'desc')
->pluck('id')
->all();
}

/**
* Get a list of all of the failed jobs.
*
15 changes: 15 additions & 0 deletions src/Illuminate/Queue/Failed/DatabaseUuidFailedJobProvider.php
Original file line number Diff line number Diff line change
@@ -67,6 +67,21 @@ public function log($connection, $queue, $payload, $exception)
return $uuid;
}

/**
* Get the IDs of all of the failed jobs.
*
* @param string|null $queue
* @return array
*/
public function ids($queue = null)
{
return $this->getTable()
->when(! is_null($queue), fn ($query) => $query->where('queue', $queue))
->orderBy('id', 'desc')
->pluck('uuid')
->all();
}

/**
* Get a list of all of the failed jobs.
*
14 changes: 14 additions & 0 deletions src/Illuminate/Queue/Failed/DynamoDbFailedJobProvider.php
Original file line number Diff line number Diff line change
@@ -78,6 +78,20 @@ public function log($connection, $queue, $payload, $exception)
return $id;
}

/**
* Get the IDs of all of the failed jobs.
*
* @param string|null $queue
* @return array
*/
public function ids($queue = null)
{
return collect($this->all())
->when(! is_null($queue), fn ($collect) => $collect->where('queue', $queue))
->pluck('id')
->all();
}

/**
* Get a list of all of the failed jobs.
*
3 changes: 3 additions & 0 deletions src/Illuminate/Queue/Failed/FailedJobProviderInterface.php
Original file line number Diff line number Diff line change
@@ -2,6 +2,9 @@

namespace Illuminate\Queue\Failed;

/**
* @method array ids(string $queue = null)
*/
interface FailedJobProviderInterface
{
/**
14 changes: 14 additions & 0 deletions src/Illuminate/Queue/Failed/FileFailedJobProvider.php
Original file line number Diff line number Diff line change
@@ -78,6 +78,20 @@ public function log($connection, $queue, $payload, $exception)
});
}

/**
* Get the IDs of all of the failed jobs.
*
* @param string|null $queue
* @return array
*/
public function ids($queue = null)
{
return collect($this->all())
->when(! is_null($queue), fn ($collect) => $collect->where('queue', $queue))
->pluck('id')
->all();
}

/**
* Get a list of all of the failed jobs.
*
11 changes: 11 additions & 0 deletions src/Illuminate/Queue/Failed/NullFailedJobProvider.php
Original file line number Diff line number Diff line change
@@ -18,6 +18,17 @@ public function log($connection, $queue, $payload, $exception)
//
}

/**
* Get the IDs of all of the failed jobs.
*
* @param string|null $queue
* @return array
*/
public function ids($queue = null)
{
return [];
}

/**
* Get a list of all of the failed jobs.
*
26 changes: 25 additions & 1 deletion src/Illuminate/Routing/Router.php
Original file line number Diff line number Diff line change
@@ -119,6 +119,13 @@ class Router implements BindingRegistrar, RegistrarContract
*/
protected $groupStack = [];

/**
* The registered custom implicit binding callback.
*
* @var array
*/
protected $implicitBindingCallback;

/**
* All of the verbs supported by the router.
*
@@ -949,7 +956,24 @@ public function substituteBindings($route)
*/
public function substituteImplicitBindings($route)
{
ImplicitRouteBinding::resolveForRoute($this->container, $route);
$default = fn () => ImplicitRouteBinding::resolveForRoute($this->container, $route);

return call_user_func(
$this->implicitBindingCallback ?? $default, $this->container, $route, $default
);
}

/**
* Register a callback to to run after implicit bindings are substituted.
*
* @param callable $callback
* @return $this
*/
public function substituteImplicitBindingsUsing($callback)
{
$this->implicitBindingCallback = $callback;

return $this;
}

/**
2 changes: 1 addition & 1 deletion src/Illuminate/Routing/composer.json
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@
"illuminate/pipeline": "^10.0",
"illuminate/session": "^10.0",
"illuminate/support": "^10.0",
"symfony/http-foundation": "^6.2",
"symfony/http-foundation": "^6.4",
"symfony/http-kernel": "^6.2",
"symfony/routing": "^6.2"
},
13 changes: 10 additions & 3 deletions src/Illuminate/Session/Middleware/StartSession.php
Original file line number Diff line number Diff line change
@@ -219,9 +219,16 @@ protected function addCookieToResponse(Response $response, Session $session)
{
if ($this->sessionIsPersistent($config = $this->manager->getSessionConfig())) {
$response->headers->setCookie(new Cookie(
$session->getName(), $session->getId(), $this->getCookieExpirationDate(),
$config['path'], $config['domain'], $config['secure'] ?? false,
$config['http_only'] ?? true, false, $config['same_site'] ?? null
$session->getName(),
$session->getId(),
$this->getCookieExpirationDate(),
$config['path'],
$config['domain'],
$config['secure'] ?? false,
$config['http_only'] ?? true,
false,
$config['same_site'] ?? null,
$config['partitioned'] ?? false
));
}
}
2 changes: 1 addition & 1 deletion src/Illuminate/Session/composer.json
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@
"illuminate/filesystem": "^10.0",
"illuminate/support": "^10.0",
"symfony/finder": "^6.2",
"symfony/http-foundation": "^6.2"
"symfony/http-foundation": "^6.4"
},
"autoload": {
"psr-4": {
1 change: 1 addition & 0 deletions src/Illuminate/Support/Facades/Route.php
Original file line number Diff line number Diff line change
@@ -37,6 +37,7 @@
* @method static \Symfony\Component\HttpFoundation\Response toResponse(\Symfony\Component\HttpFoundation\Request $request, mixed $response)
* @method static \Illuminate\Routing\Route substituteBindings(\Illuminate\Routing\Route $route)
* @method static void substituteImplicitBindings(\Illuminate\Routing\Route $route)
* @method static \Illuminate\Routing\Router substituteImplicitBindingsUsing(callable $callback)
* @method static void matched(string|callable $callback)
* @method static array getMiddleware()
* @method static \Illuminate\Routing\Router aliasMiddleware(string $name, string $class)
1 change: 1 addition & 0 deletions src/Illuminate/Support/Facades/Schema.php
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@
* @method static bool createDatabase(string $name)
* @method static bool dropDatabaseIfExists(string $name)
* @method static bool hasTable(string $table)
* @method static bool hasView(string $view)
* @method static array getTables()
* @method static array getViews()
* @method static bool hasColumn(string $table, string $column)
65 changes: 53 additions & 12 deletions src/Illuminate/Support/Number.php
Original file line number Diff line number Diff line change
@@ -141,30 +141,71 @@ public static function fileSize(int|float $bytes, int $precision = 0, ?int $maxP
* @param int|null $maxPrecision
* @return string
*/
public static function forHumans(int|float $number, int $precision = 0, ?int $maxPrecision = null)
public static function abbreviate(int|float $number, int $precision = 0, ?int $maxPrecision = null)
{
$units = [
3 => 'thousand',
6 => 'million',
9 => 'billion',
12 => 'trillion',
15 => 'quadrillion',
];
return static::forHumans($number, $precision, $maxPrecision, abbreviate: true);
}

/**
* Convert the number to its human readable equivalent.
*
* @param int $number
* @param int $precision
* @param int|null $maxPrecision
* @return string
*/
public static function forHumans(int|float $number, int $precision = 0, ?int $maxPrecision = null, bool $abbreviate = false)
{
return static::summarize($number, $precision, $maxPrecision, $abbreviate ? [
3 => 'K',
6 => 'M',
9 => 'B',
12 => 'T',
15 => 'Q',
] : [
3 => ' thousand',
6 => ' million',
9 => ' billion',
12 => ' trillion',
15 => ' quadrillion',
]);
}

/**
* Convert the number to its human readable equivalent.
*
* @param int $number
* @param int $precision
* @param int|null $maxPrecision
* @param array $units
* @return string
*/
protected static function summarize(int|float $number, int $precision = 0, ?int $maxPrecision = null, array $units = [])
{
if (empty($units)) {
$units = [
3 => 'K',
6 => 'M',
9 => 'B',
12 => 'T',
15 => 'Q',
];
}

switch (true) {
case $number === 0:
return '0';
case $number < 0:
return sprintf('-%s', static::forHumans(abs($number), $precision, $maxPrecision));
return sprintf('-%s', static::summarize(abs($number), $precision, $maxPrecision, $units));
case $number >= 1e15:
return sprintf('%s quadrillion', static::forHumans($number / 1e15, $precision, $maxPrecision));
return sprintf('%s'.end($units), static::summarize($number / 1e15, $precision, $maxPrecision, $units));
}

$numberExponent = floor(log10($number));
$displayExponent = $numberExponent - ($numberExponent % 3);
$number /= pow(10, $displayExponent);

return trim(sprintf('%s %s', static::format($number, $precision, $maxPrecision), $units[$displayExponent] ?? ''));
return trim(sprintf('%s%s', static::format($number, $precision, $maxPrecision), $units[$displayExponent] ?? ''));
}

/**
@@ -195,7 +236,7 @@ public static function useLocale(string $locale)
}

/**
* Ensure the "intl" PHP exntension is installed.
* Ensure the "intl" PHP extension is installed.
*
* @return void
*/
2 changes: 2 additions & 0 deletions src/Illuminate/Testing/Fluent/AssertableJson.php
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
use Closure;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Support\Arr;
use Illuminate\Support\Traits\Conditionable;
use Illuminate\Support\Traits\Macroable;
use Illuminate\Support\Traits\Tappable;
use Illuminate\Testing\AssertableJsonString;
@@ -16,6 +17,7 @@ class AssertableJson implements Arrayable
Concerns\Matching,
Concerns\Debugging,
Concerns\Interaction,
Conditionable,
Macroable,
Tappable;

3 changes: 2 additions & 1 deletion src/Illuminate/Testing/TestResponse.php
Original file line number Diff line number Diff line change
@@ -498,7 +498,8 @@ public function getCookie($cookieName, $decrypt = true, $unserialize = false)
$cookie->isSecure(),
$cookie->isHttpOnly(),
$cookie->isRaw(),
$cookie->getSameSite()
$cookie->getSameSite(),
$cookie->isPartitioned()
);
}
}
2 changes: 1 addition & 1 deletion src/Illuminate/Validation/composer.json
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@
"illuminate/macroable": "^10.0",
"illuminate/support": "^10.0",
"illuminate/translation": "^10.0",
"symfony/http-foundation": "^6.2",
"symfony/http-foundation": "^6.4",
"symfony/mime": "^6.2"
},
"autoload": {
1 change: 1 addition & 0 deletions src/Illuminate/View/Compilers/BladeCompiler.php
Original file line number Diff line number Diff line change
@@ -33,6 +33,7 @@ class BladeCompiler extends Compiler implements CompilerInterface
Concerns\CompilesStacks,
Concerns\CompilesStyles,
Concerns\CompilesTranslations,
Concerns\CompilesUseStatements,
ReflectsClosures;

/**
5 changes: 5 additions & 0 deletions src/Illuminate/View/Compilers/Concerns/CompilesComponents.php
Original file line number Diff line number Diff line change
@@ -67,6 +67,7 @@ public static function compileClassComponentOpening(string $component, string $a
{
return implode("\n", [
'<?php if (isset($component)) { $__componentOriginal'.$hash.' = $component; } ?>',
'<?php if (isset($attributes)) { $__attributesOriginal'.$hash.' = $attributes; } ?>',
'<?php $component = '.$component.'::resolve('.($data ?: '[]').' + (isset($attributes) && $attributes instanceof Illuminate\View\ComponentAttributeBag ? (array) $attributes->getIterator() : [])); ?>',
'<?php $component->withName('.$alias.'); ?>',
'<?php if ($component->shouldRender()): ?>',
@@ -94,6 +95,10 @@ public function compileEndComponentClass()
$hash = array_pop(static::$componentHashStack);

return $this->compileEndComponent()."\n".implode("\n", [
'<?php endif; ?>',
'<?php if (isset($__attributesOriginal'.$hash.')): ?>',
'<?php $attributes = $__attributesOriginal'.$hash.'; ?>',
'<?php unset($__attributesOriginal'.$hash.'); ?>',
'<?php endif; ?>',
'<?php if (isset($__componentOriginal'.$hash.')): ?>',
'<?php $component = $__componentOriginal'.$hash.'; ?>',
22 changes: 22 additions & 0 deletions src/Illuminate/View/Compilers/Concerns/CompilesUseStatements.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Illuminate\View\Compilers\Concerns;

trait CompilesUseStatements
{
/**
* Compile the use statements into valid PHP.
*
* @param string $expression
* @return string
*/
protected function compileUse($expression)
{
$segments = explode(',', preg_replace("/[\(\)]/", '', $expression));

$use = trim($segments[0], " '\"");
$as = isset($segments[1]) ? ' as '.trim($segments[1], " '\"") : '';

return "<?php use \\{$use}{$as}; ?>";
}
}
7 changes: 7 additions & 0 deletions tests/Integration/Database/SchemaBuilderTest.php
Original file line number Diff line number Diff line change
@@ -164,6 +164,13 @@ public function testGetTables()
}
}

public function testHasView()
{
DB::statement('create view foo (id) as select 1');

$this->assertTrue(Schema::hasView('foo'));
}

public function testGetViews()
{
DB::statement('create view foo (id) as select 1');
21 changes: 21 additions & 0 deletions tests/Routing/RoutingRouteTest.php
Original file line number Diff line number Diff line change
@@ -1756,6 +1756,27 @@ public function testImplicitBindings()
$this->assertSame('taylor', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent());
}

public function testImplicitBindingsWithClosure()
{
$router = $this->getRouter();

$router->substituteImplicitBindingsUsing(function ($container, $route, $default) {
$default = $default();

$model = $route->parameter('bar');
$model->value = 'otwell';
});

$router->get('foo/{bar}', [
'middleware' => SubstituteBindings::class,
'uses' => function (RoutingTestUserModel $bar) {
return $bar->value;
},
]);

$this->assertSame('otwell', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent());
}

public function testImplicitBindingsWhereScopedBindingsArePrevented()
{
$router = $this->getRouter();
53 changes: 53 additions & 0 deletions tests/Support/SupportNumberTest.php
Original file line number Diff line number Diff line change
@@ -208,6 +208,59 @@ public function testToHuman()
$this->assertSame('-1 thousand quadrillion', Number::forHumans(-1000000000000000000));
}

public function testSummarize()
{
$this->assertSame('1', Number::abbreviate(1));
$this->assertSame('1.00', Number::abbreviate(1, precision: 2));
$this->assertSame('10', Number::abbreviate(10));
$this->assertSame('100', Number::abbreviate(100));
$this->assertSame('1K', Number::abbreviate(1000));
$this->assertSame('1.00K', Number::abbreviate(1000, precision: 2));
$this->assertSame('1K', Number::abbreviate(1000, maxPrecision: 2));
$this->assertSame('1K', Number::abbreviate(1230));
$this->assertSame('1.2K', Number::abbreviate(1230, maxPrecision: 1));
$this->assertSame('1M', Number::abbreviate(1000000));
$this->assertSame('1B', Number::abbreviate(1000000000));
$this->assertSame('1T', Number::abbreviate(1000000000000));
$this->assertSame('1Q', Number::abbreviate(1000000000000000));
$this->assertSame('1KQ', Number::abbreviate(1000000000000000000));

$this->assertSame('123', Number::abbreviate(123));
$this->assertSame('1K', Number::abbreviate(1234));
$this->assertSame('1.23K', Number::abbreviate(1234, precision: 2));
$this->assertSame('12K', Number::abbreviate(12345));
$this->assertSame('1M', Number::abbreviate(1234567));
$this->assertSame('1B', Number::abbreviate(1234567890));
$this->assertSame('1T', Number::abbreviate(1234567890123));
$this->assertSame('1.23T', Number::abbreviate(1234567890123, precision: 2));
$this->assertSame('1Q', Number::abbreviate(1234567890123456));
$this->assertSame('1.23KQ', Number::abbreviate(1234567890123456789, precision: 2));
$this->assertSame('490K', Number::abbreviate(489939));
$this->assertSame('489.9390K', Number::abbreviate(489939, precision: 4));
$this->assertSame('500.00000M', Number::abbreviate(500000000, precision: 5));

$this->assertSame('1MQ', Number::abbreviate(1000000000000000000000));
$this->assertSame('1BQ', Number::abbreviate(1000000000000000000000000));
$this->assertSame('1TQ', Number::abbreviate(1000000000000000000000000000));
$this->assertSame('1QQ', Number::abbreviate(1000000000000000000000000000000));
$this->assertSame('1KQQ', Number::abbreviate(1000000000000000000000000000000000));

$this->assertSame('0', Number::abbreviate(0));
$this->assertSame('-1', Number::abbreviate(-1));
$this->assertSame('-1.00', Number::abbreviate(-1, precision: 2));
$this->assertSame('-10', Number::abbreviate(-10));
$this->assertSame('-100', Number::abbreviate(-100));
$this->assertSame('-1K', Number::abbreviate(-1000));
$this->assertSame('-1.23K', Number::abbreviate(-1234, precision: 2));
$this->assertSame('-1.2K', Number::abbreviate(-1234, maxPrecision: 1));
$this->assertSame('-1M', Number::abbreviate(-1000000));
$this->assertSame('-1B', Number::abbreviate(-1000000000));
$this->assertSame('-1T', Number::abbreviate(-1000000000000));
$this->assertSame('-1.1T', Number::abbreviate(-1100000000000, maxPrecision: 1));
$this->assertSame('-1Q', Number::abbreviate(-1000000000000000));
$this->assertSame('-1KQ', Number::abbreviate(-1000000000000000000));
}

protected function needsIntlExtension()
{
if (! extension_loaded('intl')) {
62 changes: 60 additions & 2 deletions tests/View/Blade/BladeComponentTagCompilerTest.php
Original file line number Diff line number Diff line change
@@ -715,7 +715,7 @@ public function testAttributesTreatedAsPropsAreRemovedFromFinalAttributes()
$component->shouldReceive('shouldRender')->once()->andReturn(true);
$component->shouldReceive('resolveView')->once()->andReturn('');
$component->shouldReceive('data')->once()->andReturn([]);
$component->shouldReceive('withAttributes')->once();
$component->shouldReceive('withAttributes')->with(['attributes' => new ComponentAttributeBag(['other' => 'ok'])])->once();

Component::resolveComponentsUsing(fn () => $component);

@@ -730,7 +730,57 @@ public function testAttributesTreatedAsPropsAreRemovedFromFinalAttributes()
eval(" ?> $template <?php ");
ob_get_clean();

$this->assertNull($attributes->get('userId'));
$this->assertSame($attributes->get('userId'), 'bar');
$this->assertSame($attributes->get('other'), 'ok');
}

public function testOriginalAttributesAreRestoredAfterRenderingChildComponentWithProps()
{
$container = new Container;
$container->instance(Application::class, $app = m::mock(Application::class));
$container->instance(Factory::class, $factory = m::mock(Factory::class));
$container->alias(Factory::class, 'view');
$app->shouldReceive('getNamespace')->never()->andReturn('App\\');
$factory->shouldReceive('exists')->never();

Container::setInstance($container);

$attributes = new ComponentAttributeBag(['userId' => 'bar', 'other' => 'ok']);

$containerComponent = m::mock(Component::class);
$containerComponent->shouldReceive('withName')->with('container')->once();
$containerComponent->shouldReceive('shouldRender')->once()->andReturn(true);
$containerComponent->shouldReceive('resolveView')->once()->andReturn('');
$containerComponent->shouldReceive('data')->once()->andReturn([]);
$containerComponent->shouldReceive('withAttributes')->once();

$profileComponent = m::mock(Component::class);
$profileComponent->shouldReceive('withName')->with('profile')->once();
$profileComponent->shouldReceive('shouldRender')->once()->andReturn(true);
$profileComponent->shouldReceive('resolveView')->once()->andReturn('');
$profileComponent->shouldReceive('data')->once()->andReturn([]);
$profileComponent->shouldReceive('withAttributes')->with(['attributes' => new ComponentAttributeBag(['other' => 'ok'])])->once();

Component::resolveComponentsUsing(fn ($component) => match ($component) {
TestContainerComponent::class => $containerComponent,
TestProfileComponent::class => $profileComponent,
});

$__env = m::mock(\Illuminate\View\Factory::class);
$__env->shouldReceive('startComponent')->twice();
$__env->shouldReceive('renderComponent')->twice();

$template = $this->compiler([
'container' => TestContainerComponent::class,
'profile' => TestProfileComponent::class,
])->compileTags('<x-container><x-profile {{ $attributes }} /></x-container>');
$template = $this->compiler->compileString($template);

ob_start();
eval(" ?> $template <?php ");
ob_get_clean();

$this->assertSame($attributes->get('userId'), 'bar');
$this->assertSame($attributes->get('other'), 'ok');
}

@@ -797,3 +847,11 @@ public function render()
return 'input';
}
}

class TestContainerComponent extends Component
{
public function render()
{
return 'container';
}
}
5 changes: 5 additions & 0 deletions tests/View/Blade/BladeComponentsTest.php
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@ public function testComponentsAreCompiled()
public function testClassComponentsAreCompiled()
{
$this->assertSame('<?php if (isset($component)) { $__componentOriginal2dda3d2f2f9b76bd400bf03f0b84e87f = $component; } ?>
<?php if (isset($attributes)) { $__attributesOriginal2dda3d2f2f9b76bd400bf03f0b84e87f = $attributes; } ?>
<?php $component = Illuminate\Tests\View\Blade\ComponentStub::class::resolve(["foo" => "bar"] + (isset($attributes) && $attributes instanceof Illuminate\View\ComponentAttributeBag ? (array) $attributes->getIterator() : [])); ?>
<?php $component->withName(\'test\'); ?>
<?php if ($component->shouldRender()): ?>
@@ -36,6 +37,10 @@ public function testEndComponentClassesAreCompiled()

$this->assertSame('<?php echo $__env->renderComponent(); ?>
<?php endif; ?>
<?php if (isset($__attributesOriginal79aef92e83454121ab6e5f64077e7d8a)): ?>
<?php $attributes = $__attributesOriginal79aef92e83454121ab6e5f64077e7d8a; ?>
<?php unset($__attributesOriginal79aef92e83454121ab6e5f64077e7d8a); ?>
<?php endif; ?>
<?php if (isset($__componentOriginal79aef92e83454121ab6e5f64077e7d8a)): ?>
<?php $component = $__componentOriginal79aef92e83454121ab6e5f64077e7d8a; ?>
<?php unset($__componentOriginal79aef92e83454121ab6e5f64077e7d8a); ?>
20 changes: 20 additions & 0 deletions tests/View/Blade/BladeUseTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace Illuminate\Tests\View\Blade;

class BladeUseTest extends AbstractBladeTestCase
{
public function testUseStatementsAreCompiled()
{
$string = "Foo @use('SomeNamespace\SomeClass', 'Foo') bar";
$expected = "Foo <?php use \SomeNamespace\SomeClass as Foo; ?> bar";
$this->assertEquals($expected, $this->compiler->compileString($string));
}

public function testUseStatementsWithoutAsAreCompiled()
{
$string = "Foo @use('SomeNamespace\SomeClass') bar";
$expected = "Foo <?php use \SomeNamespace\SomeClass; ?> bar";
$this->assertEquals($expected, $this->compiler->compileString($string));
}
}