Skip to content

Commit 743afcd

Browse files
committed
Add Laravel 13 support
Builds on the Laravel 12 work (#207). Bumps to laravel/framework ^13, PHP ^8.3, tinker ^3, carbon ^3.8.4, symfony ^7.4|^8.0, testbench ^11 (PHPUnit kept at ^11.5.50 pending phpunit 12 support in test helpers). Code: defer ArraySource datasource setup out of the model boot cycle (L13 forbids instantiating a model while booting); restate Builder<Model> param on HasRelationships relation factories; fix Preferences::findRecord() scope typing; drop the unsupported 2nd arg to DownCommand option('status'); update schedule:list invokable-class test expectation; prune stale phpstan baseline entries; CI matrices to PHP 8.3/8.4.
1 parent 1994d5e commit 743afcd

11 files changed

Lines changed: 90 additions & 46 deletions

File tree

.github/workflows/code-analysis.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
- name: Install PHP
2727
uses: shivammathur/setup-php@v2
2828
with:
29-
php-version: '8.2'
29+
php-version: '8.3'
3030
extensions: ${{ env.extensions }}
3131
coverage: none
3232

.github/workflows/code-quality.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
- name: Install PHP and PHP Code Sniffer
2424
uses: shivammathur/setup-php@v2
2525
with:
26-
php-version: '8.2'
26+
php-version: '8.3'
2727
tools: phpcs
2828
coverage: none
2929

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
max-parallel: 4
1717
matrix:
1818
operatingSystem: [ubuntu-latest, windows-latest]
19-
phpVersion: ['8.2', '8.3', '8.4']
19+
phpVersion: ['8.3', '8.4']
2020
fail-fast: false
2121
runs-on: ${{ matrix.operatingSystem }}
2222
name: ${{ matrix.operatingSystem }} / PHP ${{ matrix.phpVersion }}

composer.json

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
}
2323
],
2424
"require": {
25-
"php": "^8.2",
25+
"php": "^8.3",
2626
"ext-ctype": "*",
2727
"ext-curl": "*",
2828
"ext-dom": "*",
@@ -38,33 +38,34 @@
3838
"assetic/framework": "^3.1",
3939
"doctrine/dbal": "^3.0",
4040
"enshrined/svg-sanitize": "~0.16",
41-
"laravel/framework": "^12.30.1",
42-
"laravel/tinker": "^2.8.1",
41+
"laravel/framework": "^13.0",
42+
"laravel/tinker": "^3.0",
4343
"league/csv": "~9.1",
44-
"nesbot/carbon": "^3.0",
44+
"nesbot/carbon": "^3.8.4",
4545
"scssphp/scssphp": "~1.0",
46-
"symfony/console": "^7.2",
47-
"symfony/process": "^7.1",
48-
"symfony/yaml": "^6.4|^7.0",
46+
"symfony/console": "^7.4|^8.0",
47+
"symfony/process": "^7.4|^8.0",
48+
"symfony/yaml": "^7.4|^8.0",
4949
"twig/twig": "^3.14",
5050
"wikimedia/less.php": "^5.0",
5151
"wikimedia/minify": "~2.2",
5252
"winter/laravel-config-writer": "^1.2.0"
5353
},
5454
"require-dev": {
55-
"phpunit/phpunit": "^11.0",
55+
"phpunit/phpunit": "^11.5.50",
5656
"squizlabs/php_codesniffer": "^3.2",
5757
"php-parallel-lint/php-parallel-lint": "^1.0",
5858
"meyfa/phpunit-assert-gd": "^4.2",
5959
"mockery/mockery": "^1.6|^2.0",
6060
"dms/phpunit-arraysubset-asserts": "dev-add-phpunit-11-support",
61-
"orchestra/testbench": "^10.0",
61+
"orchestra/testbench": "^11.0",
6262
"larastan/larastan": "^3.6.0"
6363
},
6464
"repositories": [
6565
{
6666
"type": "vcs",
67-
"url": "https://github.com/pieterocp/phpunit-arraysubset-asserts"
67+
"url": "https://github.com/pieterocp/phpunit-arraysubset-asserts",
68+
"no-api": true
6869
}
6970
],
7071
"suggest": {

phpstan-baseline.neon

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,6 @@ parameters:
3030
count: 1
3131
path: src/Auth/Models/User.php
3232

33-
-
34-
message: '#^Call to function method_exists\(\) with \$this\(Winter\\Storm\\Auth\\Models\\User\) and ''getHashableAttribut…'' will always evaluate to true\.$#'
35-
identifier: function.alreadyNarrowedType
36-
count: 1
37-
path: src/Auth/Models/User.php
38-
39-
-
40-
message: '#^Call to function property_exists\(\) with \$this\(Winter\\Storm\\Auth\\Models\\User\) and ''attributeNames'' will always evaluate to true\.$#'
41-
identifier: function.alreadyNarrowedType
42-
count: 1
43-
path: src/Auth/Models/User.php
44-
45-
-
46-
message: '#^Call to function property_exists\(\) with \$this\(Winter\\Storm\\Auth\\Models\\User\) and ''customMessages'' will always evaluate to true\.$#'
47-
identifier: function.alreadyNarrowedType
48-
count: 1
49-
path: src/Auth/Models/User.php
50-
5133
-
5234
message: '#^PHPDoc type array\<string\> of property Winter\\Storm\\Auth\\Models\\User\:\:\$hidden is not covariant with PHPDoc type list\<string\> of overridden property Illuminate\\Database\\Eloquent\\Model\:\:\$hidden\.$#'
5335
identifier: property.phpDocType
@@ -642,12 +624,6 @@ parameters:
642624
count: 1
643625
path: src/Database/Relations/HasOneThrough.php
644626

645-
-
646-
message: '#^Instanceof between \*NEVER\* and Winter\\Storm\\Database\\Relations\\HasManyThrough will always evaluate to false\.$#'
647-
identifier: instanceof.alwaysFalse
648-
count: 4
649-
path: src/Database/Relations/HasOneThrough.php
650-
651627
-
652628
message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\Relation\:\:withDefault\(\)\.$#'
653629
identifier: method.notFound

src/Auth/Models/Preferences.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
* @property string|null $item Represents the item name of the preference.
1414
* @property int|null $user_id Represents the user ID that this preference belongs to.
1515
*
16-
* @method static \Winter\Storm\Database\QueryBuilder applyKeyAndUser($key, $user = null) Scope to find a setting record
17-
* for the specified module (or plugin) name, setting name and user.
16+
* @method static \Illuminate\Database\Eloquent\Builder<static> applyKeyAndUser($key, $user = null) Scope to find a
17+
* setting record for the specified module (or plugin) name, setting name and user.
1818
*/
1919
class Preferences extends Model
2020
{
@@ -167,10 +167,10 @@ public static function findRecord($key, $user = null)
167167

168168
/**
169169
* Scope to find a setting record for the specified module (or plugin) name, setting name and user.
170-
* @param \Winter\Storm\Database\QueryBuilder $query
170+
* @param \Illuminate\Database\Eloquent\Builder<static> $query
171171
* @param string $key Specifies the setting key value, for example 'backend:items.perpage'
172172
* @param mixed $user An optional user object.
173-
* @return mixed Returns the found record or null.
173+
* @return \Illuminate\Database\Eloquent\Builder<static> Returns the scoped query builder.
174174
*/
175175
public function scopeApplyKeyAndUser($query, $key, $user = null)
176176
{

src/Database/Concerns/HasRelationships.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -913,6 +913,11 @@ protected function relationMethodDefinition(string $name, bool $ignoreResolved =
913913

914914
/**
915915
* {@inheritDoc}
916+
*
917+
* Storm's relation classes are non-generic and their constructors accept a
918+
* `Builder<Model>`, so we override the inherited `Builder<TRelatedModel>` param type here.
919+
*
920+
* @param \Illuminate\Database\Eloquent\Builder<\Illuminate\Database\Eloquent\Model> $query
916921
*/
917922
protected function newHasOne(Builder $query, Model $parent, $foreignKey, $localKey)
918923
{
@@ -926,6 +931,11 @@ protected function newHasOne(Builder $query, Model $parent, $foreignKey, $localK
926931

927932
/**
928933
* {@inheritDoc}
934+
*
935+
* Storm's relation classes are non-generic and their constructors accept a
936+
* `Builder<Model>`, so we override the inherited `Builder<TRelatedModel>` param type here.
937+
*
938+
* @param \Illuminate\Database\Eloquent\Builder<\Illuminate\Database\Eloquent\Model> $query
929939
*/
930940
protected function newHasOneThrough(Builder $query, Model $farParent, Model $throughParent, $firstKey, $secondKey, $localKey, $secondLocalKey)
931941
{
@@ -939,6 +949,11 @@ protected function newHasOneThrough(Builder $query, Model $farParent, Model $thr
939949

940950
/**
941951
* {@inheritDoc}
952+
*
953+
* Storm's relation classes are non-generic and their constructors accept a
954+
* `Builder<Model>`, so we override the inherited `Builder<TRelatedModel>` param type here.
955+
*
956+
* @param \Illuminate\Database\Eloquent\Builder<\Illuminate\Database\Eloquent\Model> $query
942957
*/
943958
protected function newMorphOne(Builder $query, Model $parent, $type, $id, $localKey)
944959
{
@@ -968,6 +983,11 @@ public function guessBelongsToManyRelation()
968983

969984
/**
970985
* {@inheritDoc}
986+
*
987+
* Storm's relation classes are non-generic and their constructors accept a
988+
* `Builder<Model>`, so we override the inherited `Builder<TRelatedModel>` param type here.
989+
*
990+
* @param \Illuminate\Database\Eloquent\Builder<\Illuminate\Database\Eloquent\Model> $query
971991
*/
972992
protected function newBelongsTo(Builder $query, Model $child, $foreignKey, $ownerKey, $relation)
973993
{
@@ -981,6 +1001,11 @@ protected function newBelongsTo(Builder $query, Model $child, $foreignKey, $owne
9811001

9821002
/**
9831003
* {@inheritDoc}
1004+
*
1005+
* Storm's relation classes are non-generic and their constructors accept a
1006+
* `Builder<Model>`, so we override the inherited `Builder<TRelatedModel>` param type here.
1007+
*
1008+
* @param \Illuminate\Database\Eloquent\Builder<\Illuminate\Database\Eloquent\Model> $query
9841009
*/
9851010
protected function newMorphTo(Builder $query, Model $parent, $foreignKey, $ownerKey, $type, $relation)
9861011
{
@@ -994,6 +1019,11 @@ protected function newMorphTo(Builder $query, Model $parent, $foreignKey, $owner
9941019

9951020
/**
9961021
* {@inheritDoc}
1022+
*
1023+
* Storm's relation classes are non-generic and their constructors accept a
1024+
* `Builder<Model>`, so we override the inherited `Builder<TRelatedModel>` param type here.
1025+
*
1026+
* @param \Illuminate\Database\Eloquent\Builder<\Illuminate\Database\Eloquent\Model> $query
9971027
*/
9981028
protected function newHasMany(Builder $query, Model $parent, $foreignKey, $localKey)
9991029
{
@@ -1007,6 +1037,11 @@ protected function newHasMany(Builder $query, Model $parent, $foreignKey, $local
10071037

10081038
/**
10091039
* {@inheritDoc}
1040+
*
1041+
* Storm's relation classes are non-generic and their constructors accept a
1042+
* `Builder<Model>`, so we override the inherited `Builder<TRelatedModel>` param type here.
1043+
*
1044+
* @param \Illuminate\Database\Eloquent\Builder<\Illuminate\Database\Eloquent\Model> $query
10101045
*/
10111046
protected function newHasManyThrough(Builder $query, Model $farParent, Model $throughParent, $firstKey, $secondKey, $localKey, $secondLocalKey)
10121047
{
@@ -1020,6 +1055,11 @@ protected function newHasManyThrough(Builder $query, Model $farParent, Model $th
10201055

10211056
/**
10221057
* {@inheritDoc}
1058+
*
1059+
* Storm's relation classes are non-generic and their constructors accept a
1060+
* `Builder<Model>`, so we override the inherited `Builder<TRelatedModel>` param type here.
1061+
*
1062+
* @param \Illuminate\Database\Eloquent\Builder<\Illuminate\Database\Eloquent\Model> $query
10231063
*/
10241064
protected function newMorphMany(Builder $query, Model $parent, $type, $id, $localKey)
10251065
{
@@ -1033,6 +1073,11 @@ protected function newMorphMany(Builder $query, Model $parent, $type, $id, $loca
10331073

10341074
/**
10351075
* {@inheritDoc}
1076+
*
1077+
* Storm's relation classes are non-generic and their constructors accept a
1078+
* `Builder<Model>`, so we override the inherited `Builder<TRelatedModel>` param type here.
1079+
*
1080+
* @param \Illuminate\Database\Eloquent\Builder<\Illuminate\Database\Eloquent\Model> $query
10361081
*/
10371082
protected function newBelongsToMany(
10381083
Builder $query,
@@ -1054,6 +1099,11 @@ protected function newBelongsToMany(
10541099

10551100
/**
10561101
* {@inheritDoc}
1102+
*
1103+
* Storm's relation classes are non-generic and their constructors accept a
1104+
* `Builder<Model>`, so we override the inherited `Builder<TRelatedModel>` param type here.
1105+
*
1106+
* @param \Illuminate\Database\Eloquent\Builder<\Illuminate\Database\Eloquent\Model> $query
10571107
*/
10581108
protected function newMorphToMany(
10591109
Builder $query,

src/Database/Traits/ArraySource.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,20 @@ public static function bootArraySource(): void
3939
if (!in_array('sqlite', \PDO::getAvailableDrivers())) {
4040
throw new ApplicationException('You must enable the SQLite PDO driver to use the ArraySource trait');
4141
}
42+
}
4243

44+
/**
45+
* Boots the temporary SQLite datasource for this model.
46+
*
47+
* This is deferred out of the trait's boot method (`bootArraySource`) because Laravel 13 no
48+
* longer permits a model to be instantiated while it is still booting -- doing so throws a
49+
* LogicException. Building the datasource requires an instance to read the model's (overridable)
50+
* array source configuration, as well as model inserts (which themselves instantiate the model),
51+
* so the work is performed lazily the first time the connection is resolved, by which point the
52+
* model has always finished booting.
53+
*/
54+
protected static function arraySourceBootConnection(): void
55+
{
4356
$instance = new static;
4457

4558
static::arraySourceSetDbConnection(
@@ -79,6 +92,10 @@ public function getRecords()
7992
*/
8093
public static function resolveConnection($connection = null)
8194
{
95+
if (!isset(static::$arraySourceConnection)) {
96+
static::arraySourceBootConnection();
97+
}
98+
8299
return static::$arraySourceConnection;
83100
}
84101

src/Foundation/Application.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ public function registerCoreContainerAliases()
468468
'filesystem.cloud' => [\Illuminate\Contracts\Filesystem\Cloud::class],
469469
'hash' => [\Illuminate\Contracts\Hashing\Hasher::class],
470470
'translator' => [\Illuminate\Translation\Translator::class, \Illuminate\Contracts\Translation\Translator::class],
471-
'log' => [\Illuminate\Log\Logger::class, \Psr\Log\LoggerInterface::class],
471+
'log' => [\Illuminate\Log\LogManager::class, \Psr\Log\LoggerInterface::class],
472472
'mail.manager' => [\Illuminate\Mail\MailManager::class, \Illuminate\Contracts\Mail\Factory::class],
473473
'mailer' => [\Illuminate\Mail\Mailer::class, \Illuminate\Contracts\Mail\Mailer::class, \Illuminate\Contracts\Mail\MailQueue::class],
474474
'queue' => [\Illuminate\Queue\QueueManager::class, \Illuminate\Contracts\Queue\Factory::class, \Illuminate\Contracts\Queue\Monitor::class],

src/Foundation/Console/DownCommand.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ protected function getDownFilePayload()
2020
'redirect' => $this->redirectPath(),
2121
'retry' => $this->getRetryTime(),
2222
'refresh' => $this->option('refresh'),
23-
'secret' => $this->option('secret'),
24-
'status' => (int) $this->option('status', 503),
23+
'secret' => $this->getSecret(),
24+
'status' => (int) $this->option('status'),
2525
'template' => $this->prerenderView(),
2626
];
2727
}

0 commit comments

Comments
 (0)