Skip to content

Commit 3983fd4

Browse files
committed
model refactor
1 parent 4d8550d commit 3983fd4

File tree

2 files changed

+296
-226
lines changed

2 files changed

+296
-226
lines changed

php-templates/models.php

Lines changed: 148 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1,148 +1,183 @@
11
<?php
22

3-
collect(glob(base_path('**/Models/*.php')))->each(fn($file) => include_once($file));
4-
53
if (class_exists('\phpDocumentor\Reflection\DocBlockFactory')) {
64
$factory = \phpDocumentor\Reflection\DocBlockFactory::createInstance();
75
} else {
86
$factory = null;
97
}
108

11-
function getMethodDocblocks($method, $factory)
12-
{
13-
if ($factory !== null) {
14-
$docblock = $factory->create($method->getDocComment());
15-
$params = collect($docblock->getTagsByName("param"))->map(fn($p) => (string) $p)->all();
16-
$return = (string) $docblock->getTagsByName("return")[0] ?? null;
9+
$docblocks = new class($factory) {
10+
public function __construct(protected $factory) {}
11+
12+
public function forMethod($method)
13+
{
14+
if ($this->factory !== null) {
15+
$docblock = $this->factory->create($method->getDocComment());
16+
$params = collect($docblock->getTagsByName("param"))->map(fn($p) => (string) $p)->all();
17+
$return = (string) $docblock->getTagsByName("return")[0] ?? null;
18+
19+
return [$params, $return];
20+
}
21+
22+
23+
$params = collect($method->getParameters())
24+
->map(function (\ReflectionParameter $param) {
25+
$types = match ($param?->getType()) {
26+
null => [],
27+
default => method_exists($param->getType(), "getTypes")
28+
? $param->getType()->getTypes()
29+
: [$param->getType()]
30+
};
31+
32+
$types = collect($types)
33+
->filter()
34+
->values()
35+
->map(fn($t) => $t->getName());
36+
37+
return trim($types->join("|") . " $" . $param->getName());
38+
})
39+
->all();
40+
41+
$return = $method->getReturnType()?->getName();
1742

1843
return [$params, $return];
1944
}
45+
};
2046

47+
$models = new class($factory) {
48+
protected $output;
2149

22-
$params = collect($method->getParameters())
23-
->map(function (\ReflectionParameter $param) {
24-
$types = match ($param?->getType()) {
25-
null => [],
26-
default => method_exists($param->getType(), "getTypes")
27-
? $param->getType()->getTypes()
28-
: [$param->getType()]
29-
};
50+
public function __construct(protected $factory)
51+
{
52+
$this->output = new \Symfony\Component\Console\Output\BufferedOutput();
53+
}
3054

31-
$types = collect($types)
32-
->filter()
33-
->values()
34-
->map(fn($t) => $t->getName());
55+
public function all()
56+
{
57+
collect(glob(base_path('**/Models/*.php')))->each(fn($file) => include_once($file));
3558

36-
return trim($types->join("|") . " $" . $param->getName());
37-
})
38-
->all();
59+
return collect(get_declared_classes())
60+
->filter(fn($class) => is_subclass_of($class, \Illuminate\Database\Eloquent\Model::class))
61+
->filter(fn($class) => !in_array($class, [\Illuminate\Database\Eloquent\Relations\Pivot::class, \Illuminate\Foundation\Auth\User::class]))
62+
->values()
63+
->flatMap(fn(string $className) => $this->getInfo($className))
64+
->filter();
65+
}
3966

40-
$return = $method->getReturnType()?->getName();
67+
protected function getCastReturnType($className)
68+
{
69+
if ($className === null) {
70+
return null;
71+
}
4172

42-
return [$params, $return];
43-
}
73+
try {
74+
$method = (new \ReflectionClass($className))->getMethod('get');
4475

45-
function getBuilderMethod($method, $factory)
46-
{
47-
[$params, $return] = getMethodDocblocks($method, $factory);
76+
if ($method->hasReturnType()) {
77+
return $method->getReturnType()->getName();
78+
}
4879

49-
return [
50-
"name" => $method->getName(),
51-
"parameters" => $params,
52-
"return" => $return,
53-
];
54-
}
80+
return $className;
81+
} catch (\Exception | \Throwable $e) {
82+
return $className;
83+
}
84+
}
5585

56-
function getCastReturnType($className)
57-
{
58-
if ($className === null) {
59-
return null;
86+
protected function fromArtisan($className)
87+
{
88+
try {
89+
\Illuminate\Support\Facades\Artisan::call(
90+
"model:show",
91+
[
92+
"model" => $className,
93+
"--json" => true,
94+
],
95+
$this->output
96+
);
97+
} catch (\Exception | \Throwable $e) {
98+
return null;
99+
}
100+
101+
return json_decode($this->output->fetch(), true);
60102
}
61103

62-
try {
63-
$class = new \ReflectionClass($className);
64-
$method = $class->getMethod('get');
104+
protected function collectExistingProperties($reflection)
105+
{
106+
if ($this->factory === null) {
107+
return collect();
108+
}
109+
110+
if ($comment = $reflection->getDocComment()) {
111+
$docblock = $this->factory->create($comment);
65112

66-
if ($method->hasReturnType()) {
67-
return $method->getReturnType()->getName();
113+
$existingProperties = collect($docblock->getTagsByName("property"))->map(fn($p) => $p->getVariableName());
114+
$existingReadProperties = collect($docblock->getTagsByName("property-read"))->map(fn($p) => $p->getVariableName());
115+
116+
return $existingProperties->merge($existingReadProperties);
68117
}
69118

70-
return $className;
71-
} catch (\Exception | \Throwable $e) {
72-
return $className;
119+
return collect();
73120
}
74-
}
75121

76-
function getModelInfo($className, $factory)
77-
{
78-
$output = new \Symfony\Component\Console\Output\BufferedOutput();
79-
80-
try {
81-
\Illuminate\Support\Facades\Artisan::call(
82-
"model:show",
83-
[
84-
"model" => $className,
85-
"--json" => true,
86-
],
87-
$output
88-
);
89-
} catch (\Exception | \Throwable $e) {
90-
return null;
91-
}
122+
protected function getInfo($className)
123+
{
124+
if (($data = $this->fromArtisan($className)) === null) {
125+
return null;
126+
}
92127

93-
$data = json_decode($output->fetch(), true);
128+
$reflection = (new \ReflectionClass($className));
94129

95-
if ($data === null) {
96-
return null;
130+
$existingProperties = $this->collectExistingProperties($reflection);
131+
132+
$data['attributes'] = collect($data['attributes'])
133+
->map(fn($attrs) => array_merge($attrs, [
134+
'title_case' => \Illuminate\Support\Str::of($attrs['name'])->title()->replace('_', '')->toString(),
135+
'documented' => $existingProperties->contains($attrs['name']),
136+
'cast' => $this->getCastReturnType($attrs['cast'])
137+
]))
138+
->toArray();
139+
140+
$data['scopes'] = collect($reflection->getMethods())
141+
->filter(fn($method) => $method->isPublic() && !$method->isStatic() && str_starts_with($method->name, 'scope'))
142+
->map(fn($method) => \Illuminate\Support\Str::of($method->name)->replace('scope', '')->lcfirst()->toString())
143+
->values()
144+
->toArray();
145+
146+
$data['uri'] = $reflection->getFileName();
147+
148+
return [
149+
$className => $data,
150+
];
97151
}
152+
};
98153

99-
$reflection = (new \ReflectionClass($className));
154+
$builder = new class($docblocks) {
155+
public function __construct(protected $docblocks) {}
100156

101-
if ($factory !== null && ($comment = $reflection->getDocComment())) {
102-
$docblock = $factory->create($comment);
103-
$existingProperties = collect($docblock->getTagsByName("property"))->map(fn($p) => $p->getVariableName());
104-
$existingReadProperties = collect($docblock->getTagsByName("property-read"))->map(fn($p) => $p->getVariableName());
105-
$existingProperties = $existingProperties->merge($existingReadProperties);
106-
} else {
107-
$existingProperties = collect();
157+
public function methods()
158+
{
159+
$reflection = new \ReflectionClass(\Illuminate\Database\Query\Builder::class);
160+
161+
return collect($reflection->getMethods(\ReflectionMethod::IS_PUBLIC))
162+
->filter(fn(ReflectionMethod $method) => !str_starts_with($method->getName(), "__"))
163+
->map(fn(\ReflectionMethod $method) => $this->getMethodInfo($method))
164+
->filter()
165+
->values();
108166
}
109167

110-
$data['attributes'] = collect($data['attributes'])
111-
->map(fn($attrs) => array_merge($attrs, [
112-
'title_case' => str_replace('_', '', \Illuminate\Support\Str::title($attrs['name'])),
113-
'documented' => $existingProperties->contains($attrs['name']),
114-
'cast' => getCastReturnType($attrs['cast'])
115-
]))
116-
->toArray();
117-
118-
$data['scopes'] = collect($reflection->getMethods())
119-
->filter(fn($method) => $method->isPublic() && !$method->isStatic() && $method->name !== '__construct')
120-
->filter(fn($method) => str_starts_with($method->name, 'scope'))
121-
->map(fn($method) => str_replace('scope', '', $method->name))
122-
->map(fn($method) => strtolower(substr($method, 0, 1)) . substr($method, 1))
123-
->values()
124-
->toArray();
125-
126-
$data['uri'] = $reflection->getFileName();
127-
128-
return [
129-
$className => $data,
130-
];
131-
}
168+
protected function getMethodInfo($method)
169+
{
170+
[$params, $return] = $this->docblocks->forMethod($method);
171+
172+
return [
173+
"name" => $method->getName(),
174+
"parameters" => $params,
175+
"return" => $return,
176+
];
177+
}
178+
};
132179

133-
$reflection = new \ReflectionClass(\Illuminate\Database\Query\Builder::class);
134-
$builderMethods = collect($reflection->getMethods(\ReflectionMethod::IS_PUBLIC))
135-
->filter(fn(ReflectionMethod $method) => !str_starts_with($method->getName(), "__"))
136-
->map(fn(\ReflectionMethod $method) => getBuilderMethod($method, $factory))
137-
->filter()
138-
->values();
139-
140-
echo collect([
141-
'builderMethods' => $builderMethods,
142-
'models' => collect(get_declared_classes())
143-
->filter(fn($class) => is_subclass_of($class, \Illuminate\Database\Eloquent\Model::class))
144-
->filter(fn($class) => !in_array($class, [\Illuminate\Database\Eloquent\Relations\Pivot::class, \Illuminate\Foundation\Auth\User::class]))
145-
->values()
146-
->flatMap(fn(string $className) => getModelInfo($className, $factory))
147-
->filter(),
148-
])->toJson();
180+
echo json_encode([
181+
'builderMethods' => $builder->methods(),
182+
'models' => $models->all(),
183+
]);

0 commit comments

Comments
 (0)