Skip to content

Commit 6b8519c

Browse files
committed
added GenerateMappableColumnsCommand
1 parent acf1474 commit 6b8519c

File tree

3 files changed

+122
-1
lines changed

3 files changed

+122
-1
lines changed

composer.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,20 @@
1111
],
1212
"require": {
1313
"php": "^8.1",
14-
"laravel/framework": "^10.0"
14+
"laravel/framework": "^10.0",
15+
"barryvdh/reflection-docblock": "^2.1",
16+
"composer/class-map-generator": "^1.1"
1517
},
1618
"autoload": {
1719
"psr-4": {
1820
"BoredProgrammers\\LaravelEloquentMappable\\": "src/"
1921
}
22+
},
23+
"extra": {
24+
"laravel": {
25+
"providers": [
26+
"BoredProgrammers\\LaravelEloquentMappable\\Providers\\LaravelEloquentMappableServiceProvider"
27+
]
28+
}
2029
}
2130
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace BoredProgrammers\LaravelEloquentMappable\Commands;
4+
5+
use Barryvdh\Reflection\DocBlock;
6+
use Barryvdh\Reflection\DocBlock\Tag;
7+
use Barryvdh\Reflection\DocBlock\Tag\MethodTag;
8+
use Barryvdh\Reflection\DocBlock\Tag\PropertyTag;
9+
use Composer\ClassMapGenerator\ClassMapGenerator;
10+
use Illuminate\Console\Command;
11+
use Illuminate\Database\Eloquent\Model;
12+
use Illuminate\Support\Str;
13+
use ReflectionClass;
14+
15+
class GenerateMappableColumnsCommand extends Command
16+
{
17+
18+
protected $signature = 'mappable-columns:generate';
19+
20+
protected $description = 'Generate php doc for mappable columns';
21+
22+
public function handle(): void
23+
{
24+
$classMap = ClassMapGenerator::createMap(app_path('Models'));
25+
26+
foreach ($classMap as $model => $path) {
27+
$reflection = new ReflectionClass($model);
28+
29+
if (!$reflection->isSubclassOf(Model::class)) {
30+
continue;
31+
}
32+
33+
if (!$reflection->isInstantiable()) {
34+
continue;
35+
}
36+
37+
if (!$reflection->hasProperty('columns')) {
38+
continue;
39+
}
40+
41+
echo 'Generating for ' . $model . "\n";
42+
43+
$mappedColumns = $reflection->newInstance()->columns;
44+
$docBlock = new DocBlock($reflection);
45+
46+
$existingProperties = [];
47+
$existingMethods = [];
48+
49+
foreach ($docBlock->getTags() as $tag) {
50+
if ($tag instanceof PropertyTag) {
51+
$existingProperties[] = $tag->getVariableName();
52+
} elseif ($tag instanceof MethodTag) {
53+
$existingMethods[] = $tag->getMethodName();
54+
}
55+
}
56+
57+
foreach ($mappedColumns as $mappedColumn => $dbColumn) {
58+
if (in_array('$' . $mappedColumn, $existingProperties)) {
59+
continue;
60+
}
61+
62+
$methodName = 'where' . Str::studly($mappedColumn);
63+
64+
if (in_array($methodName, $existingMethods)) {
65+
continue;
66+
}
67+
68+
$tagLine = "@property mixed \$$mappedColumn mapped for db column '$dbColumn'";
69+
$docBlock->appendTag(Tag::createInstance($tagLine, $docBlock));
70+
71+
$tagLine = "@method static \\Illuminate\\Database\\Eloquent\\Builder $methodName(\$value)";
72+
$docBlock->appendTag(Tag::createInstance($tagLine, $docBlock));
73+
}
74+
75+
$doc = (new DocBlock\Serializer())->getDocComment($docBlock);
76+
$contents = file_get_contents($path);
77+
78+
if ($originalDoc = $reflection->getDocComment()) {
79+
$contents = str_replace($originalDoc, $doc, $contents);
80+
} else {
81+
$classname = $reflection->getShortName();
82+
$pos = strpos($contents, "final class {$classname}") ?: strpos($contents, "class {$classname}");
83+
if ($pos !== false) {
84+
$contents = substr_replace($contents, $doc . "\n", $pos, 0);
85+
}
86+
}
87+
88+
file_put_contents($path, $contents);
89+
}
90+
}
91+
92+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace BoredProgrammers\LaravelEloquentMappable\Providers;
4+
5+
use BoredProgrammers\LaravelEloquentMappable\Commands\GenerateMappableColumnsCommand;
6+
use Illuminate\Support\ServiceProvider;
7+
8+
class LaravelEloquentMappableServiceProvider extends ServiceProvider
9+
{
10+
11+
public function boot(): void
12+
{
13+
if ($this->app->runningInConsole()) {
14+
$this->commands([
15+
GenerateMappableColumnsCommand::class,
16+
]);
17+
}
18+
}
19+
20+
}

0 commit comments

Comments
 (0)