Skip to content

Commit 9f97f7c

Browse files
wimskilaravel-ide-helper
andauthored
Refactor resolving of null information for custom casted attribute types (#1330)
* Refactor resolving of null information for custom casted attribute types * composer fix-style --------- Co-authored-by: laravel-ide-helper <laravel-ide-helper@users.noreply.github.com>
1 parent 97fd0e0 commit 9f97f7c

File tree

4 files changed

+43
-6
lines changed

4 files changed

+43
-6
lines changed

src/Console/ModelsCommand.php

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -437,12 +437,44 @@ public function castPropertiesType($model)
437437
$realType = $this->checkForCastableCasts($realType, $params);
438438
$realType = $this->checkForCustomLaravelCasts($realType);
439439
$realType = $this->getTypeOverride($realType);
440-
$this->properties[$name]['type'] = $this->getTypeInModel($model, $realType);
440+
$realType = $this->getTypeInModel($model, $realType);
441+
$realType = $this->applyNullability($realType, isset($this->nullableColumns[$name]));
441442

442-
if (isset($this->nullableColumns[$name])) {
443-
$this->properties[$name]['type'] .= '|null';
444-
}
443+
$this->properties[$name]['type'] = $realType;
444+
}
445+
}
446+
447+
protected function applyNullability(?string $type, bool $isNullable): ?string
448+
{
449+
if (!$type) {
450+
return null;
451+
}
452+
453+
$nullString = null;
454+
455+
// Find instance of:
456+
// A) start of string or non-word character (like space or pipe) followed by 'null|'
457+
// B) '|null' followed by end of string or non-word character (like space or pipe)
458+
// This will find 'or null' instances at the beginning, middle or end of a type string,
459+
// but will exclude solo/pure null instances and null being part of a type's name (e.g. class 'Benull').
460+
if (preg_match('/(?:(?:^|\W)(null\|))|(\|null(?:$|\W))/', $type, $matches) === 1) {
461+
$nullString = array_pop($matches);
445462
}
463+
464+
// Return the current type string if:
465+
// A) the type can be null and the type contains a null instance
466+
// B) the type can not be null and the type does not contain a null instance
467+
if (!($isNullable xor $nullString)) {
468+
return $type;
469+
}
470+
471+
if ($isNullable) {
472+
$type .= '|null';
473+
} else {
474+
$type = str_replace($nullString, '', $type);
475+
}
476+
477+
return $type;
446478
}
447479

448480
/**

tests/Console/ModelsCommand/LaravelCustomCasts/Models/CustomCast.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class CustomCast extends Model
3131
'casted_property_with_return_primitive' => CustomCasterWithPrimitiveReturn::class,
3232
'casted_property_with_return_primitive_docblock' => CustomCasterWithPrimitiveDocblockReturn::class,
3333
'casted_property_with_return_nullable_primitive' => CustomCasterWithNullablePrimitiveReturn::class,
34+
'casted_property_with_return_nullable_primitive_and_nullable_column' => CustomCasterWithNullablePrimitiveReturn::class,
3435
'casted_property_without_return' => CustomCasterWithoutReturnType::class,
3536
'casted_property_with_param' => CustomCasterWithParam::class . ':param',
3637
'casted_property_with_static_return_docblock' => SelfCastingCasterWithStaticDocblockReturn::class,

tests/Console/ModelsCommand/LaravelCustomCasts/__snapshots__/Test__test__1.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@
2929
* @property \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CastedProperty $casted_property_with_return_docblock
3030
* @property \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CastedProperty $casted_property_with_return_docblock_fqn
3131
* @property array $casted_property_with_return_primitive
32-
* @property array|null $casted_property_with_return_primitive_docblock
33-
* @property array|null $casted_property_with_return_nullable_primitive
32+
* @property array $casted_property_with_return_primitive_docblock
33+
* @property array $casted_property_with_return_nullable_primitive
34+
* @property array|null $casted_property_with_return_nullable_primitive_and_nullable_column
3435
* @property $casted_property_without_return
3536
* @property \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CastedProperty $casted_property_with_param
3637
* @property SelfCastingCasterWithStaticDocblockReturn $casted_property_with_static_return_docblock
@@ -50,6 +51,7 @@
5051
* @method static \Illuminate\Database\Eloquent\Builder|CustomCast whereCastedPropertyWithReturnDocblock($value)
5152
* @method static \Illuminate\Database\Eloquent\Builder|CustomCast whereCastedPropertyWithReturnDocblockFqn($value)
5253
* @method static \Illuminate\Database\Eloquent\Builder|CustomCast whereCastedPropertyWithReturnNullablePrimitive($value)
54+
* @method static \Illuminate\Database\Eloquent\Builder|CustomCast whereCastedPropertyWithReturnNullablePrimitiveAndNullableColumn($value)
5355
* @method static \Illuminate\Database\Eloquent\Builder|CustomCast whereCastedPropertyWithReturnPrimitive($value)
5456
* @method static \Illuminate\Database\Eloquent\Builder|CustomCast whereCastedPropertyWithReturnPrimitiveDocblock($value)
5557
* @method static \Illuminate\Database\Eloquent\Builder|CustomCast whereCastedPropertyWithReturnType($value)
@@ -70,6 +72,7 @@ class CustomCast extends Model
7072
'casted_property_with_return_primitive' => CustomCasterWithPrimitiveReturn::class,
7173
'casted_property_with_return_primitive_docblock' => CustomCasterWithPrimitiveDocblockReturn::class,
7274
'casted_property_with_return_nullable_primitive' => CustomCasterWithNullablePrimitiveReturn::class,
75+
'casted_property_with_return_nullable_primitive_and_nullable_column' => CustomCasterWithNullablePrimitiveReturn::class,
7376
'casted_property_without_return' => CustomCasterWithoutReturnType::class,
7477
'casted_property_with_param' => CustomCasterWithParam::class . ':param',
7578
'casted_property_with_static_return_docblock' => SelfCastingCasterWithStaticDocblockReturn::class,

tests/Console/ModelsCommand/migrations/____custom_casts_table.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public function up(): void
1717
$table->string('casted_property_with_return_primitive');
1818
$table->string('casted_property_with_return_primitive_docblock');
1919
$table->string('casted_property_with_return_nullable_primitive');
20+
$table->string('casted_property_with_return_nullable_primitive_and_nullable_column')->nullable();
2021
$table->string('casted_property_without_return');
2122
$table->string('casted_property_with_param');
2223
$table->string('casted_property_with_static_return_docblock');

0 commit comments

Comments
 (0)