Added support for Laravel 7 custom casts (#913)

* added support for laravel 7 custom casts

* refactored tests; added test cases

* added test case

* resolved method dublication
This commit is contained in:
belamov
2020-04-22 06:32:40 +02:00
committed by GitHub
parent dcf76c1a81
commit cfa9a81d65
11 changed files with 340 additions and 1 deletions
+31 -1
View File
@@ -16,7 +16,7 @@ use Barryvdh\Reflection\DocBlock\Serializer as DocBlockSerializer;
use Barryvdh\Reflection\DocBlock\Tag;
use Composer\Autoload\ClassMapGenerator;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Str;
@@ -322,6 +322,8 @@ class ModelsCommand extends Command
if (!isset($this->properties[$name])) {
continue;
} else {
$realType = $this->checkForCustomLaravelCasts($realType);
$this->properties[$name]['type'] = $this->getTypeOverride($realType);
if (isset($this->nullableColumns[$name])) {
@@ -942,4 +944,32 @@ class ModelsCommand extends Command
return $keyword;
}
/**
* @param string $type
* @return string|null
* @throws \ReflectionException
*/
protected function checkForCustomLaravelCasts(string $type): ?string
{
if (!class_exists($type)) {
return $type;
}
$reflection = new \ReflectionClass($type);
if (!$reflection->implementsInterface(CastsAttributes::class)) {
return $type;
}
$methodReflection = new \ReflectionMethod($type, 'get');
$type = $this->getReturnTypeFromReflection($methodReflection);
if ($type === null) {
$type = $this->getReturnTypeFromDocBlock($methodReflection);
}
return $type;
}
}
@@ -0,0 +1,8 @@
<?php
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts;
class CastedProperty
{
}
@@ -0,0 +1,25 @@
<?php
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class CustomCasterWithDocblockReturn implements CastsAttributes
{
/**
* @inheritDoc
* @return CastedProperty
*/
public function get($model, string $key, $value, array $attributes)
{
return new CastedProperty();
}
/**
* @inheritDoc
*/
public function set($model, string $key, $value, array $attributes)
{
// TODO: Implement set() method.
}
}
@@ -0,0 +1,25 @@
<?php
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class CustomCasterWithNullablePrimitiveReturn implements CastsAttributes
{
/**
* @inheritDoc
* @return string
*/
public function get($model, string $key, $value, array $attributes): ?array
{
return new CastedProperty();
}
/**
* @inheritDoc
*/
public function set($model, string $key, $value, array $attributes)
{
// TODO: Implement set() method.
}
}
@@ -0,0 +1,25 @@
<?php
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class CustomCasterWithPrimitiveDocblockReturn implements CastsAttributes
{
/**
* @inheritDoc
* @return array|null
*/
public function get($model, string $key, $value, array $attributes)
{
return new CastedProperty();
}
/**
* @inheritDoc
*/
public function set($model, string $key, $value, array $attributes)
{
// TODO: Implement set() method.
}
}
@@ -0,0 +1,25 @@
<?php
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class CustomCasterWithPrimitiveReturn implements CastsAttributes
{
/**
* @inheritDoc
* @return string
*/
public function get($model, string $key, $value, array $attributes): array
{
return new CastedProperty();
}
/**
* @inheritDoc
*/
public function set($model, string $key, $value, array $attributes)
{
// TODO: Implement set() method.
}
}
@@ -0,0 +1,24 @@
<?php
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class CustomCasterWithReturnType implements CastsAttributes
{
/**
* @return array
*/
public function get($model, string $key, $value, array $attributes): CastedProperty
{
return new CastedProperty();
}
/**
* @inheritDoc
*/
public function set($model, string $key, $value, array $attributes)
{
// TODO: Implement set() method.
}
}
@@ -0,0 +1,21 @@
<?php
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class CustomCasterWithoutReturnType implements CastsAttributes
{
public function get($model, string $key, $value, array $attributes)
{
return new CastedProperty();
}
/**
* @inheritDoc
*/
public function set($model, string $key, $value, array $attributes)
{
// TODO: Implement set() method.
}
}
@@ -0,0 +1,23 @@
<?php declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Models;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CustomCasterWithDocblockReturn;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CustomCasterWithNullablePrimitiveReturn;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CustomCasterWithoutReturnType;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CustomCasterWithPrimitiveDocblockReturn;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CustomCasterWithPrimitiveReturn;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CustomCasterWithReturnType;
use Illuminate\Database\Eloquent\Model;
class CustomCast extends Model
{
protected $casts = [
'casted_property_with_return_type' => CustomCasterWithReturnType::class,
'casted_property_with_return_docblock' => CustomCasterWithDocblockReturn::class,
'casted_property_with_return_primitive' => CustomCasterWithPrimitiveReturn::class,
'casted_property_with_return_primitive_docblock' => CustomCasterWithPrimitiveDocblockReturn::class,
'casted_property_with_return_nullable_primitive' => CustomCasterWithNullablePrimitiveReturn::class,
'casted_property_without_return' => CustomCasterWithoutReturnType::class,
];
}
@@ -0,0 +1,113 @@
<?php declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts;
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AbstractModelsCommand;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Foundation\Application;
use Mockery;
class Test extends AbstractModelsCommand
{
protected function setUp(): void
{
parent::setUp();
if (version_compare(Application::VERSION, '7.0', '<')) {
$this->markTestSkipped('This test requires Laravel 7.0 or higher');
}
}
protected function getEnvironmentSetUp($app)
{
parent::getEnvironmentSetUp($app);
$app['config']->set('ide-helper', [
'model_locations' => [
// This is calculated from the base_path() which points to
// vendor/orchestra/testbench-core/laravel
'/../../../../tests/Console/ModelsCommand/LaravelCustomCasts/Models',
],
]);
}
public function test_it_parses_casted_properties_correctly(): void
{
$actualContent = null;
$mockFilesystem = Mockery::mock(Filesystem::class);
$mockFilesystem
->shouldReceive('get')
->andReturn(file_get_contents(__DIR__.'/Models/CustomCast.php'))
->once();
$mockFilesystem
->shouldReceive('put')
->with(
Mockery::any(),
Mockery::capture($actualContent)
)
->andReturn(1) // Simulate we wrote _something_ to the file
->once();
$this->instance(Filesystem::class, $mockFilesystem);
$command = $this->app->make(ModelsCommand::class);
$tester = $this->runCommand($command, [
'--write' => true,
]);
$this->assertSame(0, $tester->getStatusCode());
$this->assertEmpty($tester->getDisplay());
$expectedContent = <<<'PHP'
<?php declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Models;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CustomCasterWithDocblockReturn;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CustomCasterWithNullablePrimitiveReturn;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CustomCasterWithoutReturnType;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CustomCasterWithPrimitiveDocblockReturn;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CustomCasterWithPrimitiveReturn;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CustomCasterWithReturnType;
use Illuminate\Database\Eloquent\Model;
/**
* Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Models\CustomCast
*
* @property \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CastedProperty $casted_property_with_return_type
* @property \CastedProperty $casted_property_with_return_docblock
* @property array $casted_property_with_return_primitive
* @property array|null $casted_property_with_return_primitive_docblock
* @property array|null $casted_property_with_return_nullable_primitive
* @property $casted_property_without_return
* @method static \Illuminate\Database\Eloquent\Builder|\Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Models\CustomCast newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|\Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Models\CustomCast newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|\Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Models\CustomCast query()
* @method static \Illuminate\Database\Eloquent\Builder|\Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Models\CustomCast whereCastedPropertyWithReturnDocblock($value)
* @method static \Illuminate\Database\Eloquent\Builder|\Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Models\CustomCast whereCastedPropertyWithReturnNullablePrimitive($value)
* @method static \Illuminate\Database\Eloquent\Builder|\Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Models\CustomCast whereCastedPropertyWithReturnPrimitive($value)
* @method static \Illuminate\Database\Eloquent\Builder|\Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Models\CustomCast whereCastedPropertyWithReturnPrimitiveDocblock($value)
* @method static \Illuminate\Database\Eloquent\Builder|\Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Models\CustomCast whereCastedPropertyWithReturnType($value)
* @method static \Illuminate\Database\Eloquent\Builder|\Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Models\CustomCast whereCastedPropertyWithoutReturn($value)
* @mixin \Eloquent
*/
class CustomCast extends Model
{
protected $casts = [
'casted_property_with_return_type' => CustomCasterWithReturnType::class,
'casted_property_with_return_docblock' => CustomCasterWithDocblockReturn::class,
'casted_property_with_return_primitive' => CustomCasterWithPrimitiveReturn::class,
'casted_property_with_return_primitive_docblock' => CustomCasterWithPrimitiveDocblockReturn::class,
'casted_property_with_return_nullable_primitive' => CustomCasterWithNullablePrimitiveReturn::class,
'casted_property_without_return' => CustomCasterWithoutReturnType::class,
];
}
PHP;
$this->assertSame($expectedContent, $actualContent);
}
}
@@ -0,0 +1,20 @@
<?php declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CustomCastsTable extends Migration
{
public function up(): void
{
Schema::create('custom_casts', static function (Blueprint $table) {
$table->string('casted_property_with_return_type');
$table->string('casted_property_with_return_docblock');
$table->string('casted_property_with_return_primitive');
$table->string('casted_property_with_return_primitive_docblock');
$table->string('casted_property_with_return_nullable_primitive');
$table->string('casted_property_without_return');
});
}
}