feat(proxmox): add statistics redirect component and route
Introduced a new Livewire component for statistics redirection and added a corresponding route to enhance navigation within the Proxmox extension. This update lays the groundwork for future statistics-related features.
This commit is contained in:
11
vendor/_laravel_ide/_auth.php
vendored
Normal file
11
vendor/_laravel_ide/_auth.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Contracts\Auth;
|
||||
|
||||
interface Guard
|
||||
{
|
||||
/**
|
||||
* @return \App\Models\User|null
|
||||
*/
|
||||
public function user();
|
||||
}
|
||||
41
vendor/_laravel_ide/_facade.php
vendored
Normal file
41
vendor/_laravel_ide/_facade.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Support\Facades;
|
||||
|
||||
interface Auth
|
||||
{
|
||||
/**
|
||||
* @return \App\Models\User|false
|
||||
*/
|
||||
public static function loginUsingId(mixed $id, bool $remember = false);
|
||||
|
||||
/**
|
||||
* @return \App\Models\User|false
|
||||
*/
|
||||
public static function onceUsingId(mixed $id);
|
||||
|
||||
/**
|
||||
* @return \App\Models\User|null
|
||||
*/
|
||||
public static function getUser();
|
||||
|
||||
/**
|
||||
* @return \App\Models\User
|
||||
*/
|
||||
public static function authenticate();
|
||||
|
||||
/**
|
||||
* @return \App\Models\User|null
|
||||
*/
|
||||
public static function user();
|
||||
|
||||
/**
|
||||
* @return \App\Models\User|null
|
||||
*/
|
||||
public static function logoutOtherDevices(string $password);
|
||||
|
||||
/**
|
||||
* @return \App\Models\User
|
||||
*/
|
||||
public static function getLastAttempted();
|
||||
}
|
||||
1
vendor/_laravel_ide/_model_helpers.php
vendored
Normal file
1
vendor/_laravel_ide/_model_helpers.php
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<?php
|
||||
11
vendor/_laravel_ide/_request.php
vendored
Normal file
11
vendor/_laravel_ide/_request.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Http;
|
||||
|
||||
interface Request
|
||||
{
|
||||
/**
|
||||
* @return \App\Models\User|null
|
||||
*/
|
||||
public function user($guard = null);
|
||||
}
|
||||
361
vendor/_laravel_ide/discover-38647d8b44b32228b73734bb60d939db.php
vendored
Normal file
361
vendor/_laravel_ide/discover-38647d8b44b32228b73734bb60d939db.php
vendored
Normal file
@@ -0,0 +1,361 @@
|
||||
<?php
|
||||
|
||||
|
||||
error_reporting(E_ERROR | E_PARSE);
|
||||
|
||||
define('LARAVEL_START', microtime(true));
|
||||
|
||||
require_once __DIR__ . '/../autoload.php';
|
||||
|
||||
class LaravelVsCode
|
||||
{
|
||||
public static function relativePath($path)
|
||||
{
|
||||
if (!str_contains($path, base_path())) {
|
||||
return (string) $path;
|
||||
}
|
||||
|
||||
return ltrim(str_replace(base_path(), '', realpath($path) ?: $path), DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
public static function isVendor($path)
|
||||
{
|
||||
return str_contains($path, base_path("vendor"));
|
||||
}
|
||||
|
||||
public static function outputMarker($key)
|
||||
{
|
||||
return '__VSCODE_LARAVEL_' . $key . '__';
|
||||
}
|
||||
|
||||
public static function startupError(\Throwable $e)
|
||||
{
|
||||
throw new Error(self::outputMarker('STARTUP_ERROR') . ': ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$app = require_once __DIR__ . '/../../bootstrap/app.php';
|
||||
} catch (\Throwable $e) {
|
||||
LaravelVsCode::startupError($e);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$app->register(new class($app) extends \Illuminate\Support\ServiceProvider
|
||||
{
|
||||
public function boot()
|
||||
{
|
||||
config([
|
||||
'logging.channels.null' => [
|
||||
'driver' => 'monolog',
|
||||
'handler' => \Monolog\Handler\NullHandler::class,
|
||||
],
|
||||
'logging.default' => 'null',
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
|
||||
$kernel->bootstrap();
|
||||
} catch (\Throwable $e) {
|
||||
LaravelVsCode::startupError($e);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo LaravelVsCode::outputMarker('START_OUTPUT');
|
||||
|
||||
if (class_exists('\phpDocumentor\Reflection\DocBlockFactory')) {
|
||||
$factory = \phpDocumentor\Reflection\DocBlockFactory::createInstance();
|
||||
} else {
|
||||
$factory = null;
|
||||
}
|
||||
|
||||
$docblocks = new class($factory) {
|
||||
public function __construct(protected $factory) {}
|
||||
|
||||
public function forMethod($method)
|
||||
{
|
||||
if ($this->factory !== null) {
|
||||
$docblock = $this->factory->create($method->getDocComment());
|
||||
$params = collect($docblock->getTagsByName("param"))->map(fn($p) => (string) $p)->all();
|
||||
$return = (string) $docblock->getTagsByName("return")[0] ?? null;
|
||||
|
||||
return [$params, $return];
|
||||
}
|
||||
|
||||
|
||||
$params = collect($method->getParameters())
|
||||
->map(function (\ReflectionParameter $param) {
|
||||
$types = match ($param?->getType()) {
|
||||
null => [],
|
||||
default => method_exists($param->getType(), "getTypes")
|
||||
? $param->getType()->getTypes()
|
||||
: [$param->getType()]
|
||||
};
|
||||
|
||||
$types = collect($types)
|
||||
->filter()
|
||||
->values()
|
||||
->map(fn($t) => $t->getName());
|
||||
|
||||
return trim($types->join("|") . " $" . $param->getName());
|
||||
})
|
||||
->all();
|
||||
|
||||
$return = $method->getReturnType()?->getName();
|
||||
|
||||
return [$params, $return];
|
||||
}
|
||||
};
|
||||
|
||||
$models = new class($factory) {
|
||||
protected $output;
|
||||
|
||||
public function __construct(protected $factory)
|
||||
{
|
||||
$this->output = new \Symfony\Component\Console\Output\BufferedOutput();
|
||||
}
|
||||
|
||||
public function all()
|
||||
{
|
||||
if (\Illuminate\Support\Facades\File::isDirectory(base_path('app/Models'))) {
|
||||
collect(\Illuminate\Support\Facades\File::allFiles(base_path('app/Models')))
|
||||
->filter(fn(\Symfony\Component\Finder\SplFileInfo $file) => $file->getExtension() === 'php')
|
||||
->each(fn($file) => include_once($file));
|
||||
}
|
||||
|
||||
return collect(get_declared_classes())
|
||||
->filter(fn($class) => is_subclass_of($class, \Illuminate\Database\Eloquent\Model::class))
|
||||
->filter(fn($class) => !in_array($class, [\Illuminate\Database\Eloquent\Relations\Pivot::class, \Illuminate\Foundation\Auth\User::class]))
|
||||
->values()
|
||||
->flatMap(fn(string $className) => $this->getInfo($className))
|
||||
->filter();
|
||||
}
|
||||
|
||||
protected function getCastReturnType($className)
|
||||
{
|
||||
if ($className === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
$method = (new \ReflectionClass($className))->getMethod('get');
|
||||
|
||||
if ($method->hasReturnType()) {
|
||||
return $method->getReturnType()->getName();
|
||||
}
|
||||
|
||||
return $className;
|
||||
} catch (\Exception | \Throwable $e) {
|
||||
return $className;
|
||||
}
|
||||
}
|
||||
|
||||
protected function fromArtisan($className)
|
||||
{
|
||||
try {
|
||||
\Illuminate\Support\Facades\Artisan::call(
|
||||
"model:show",
|
||||
[
|
||||
"model" => $className,
|
||||
"--json" => true,
|
||||
],
|
||||
$this->output
|
||||
);
|
||||
} catch (\Exception | \Throwable $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return json_decode($this->output->fetch(), true);
|
||||
}
|
||||
|
||||
protected function collectExistingProperties($reflection)
|
||||
{
|
||||
if ($this->factory === null) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
if ($comment = $reflection->getDocComment()) {
|
||||
$docblock = $this->factory->create($comment);
|
||||
|
||||
$existingProperties = collect($docblock->getTagsByName("property"))->map(fn($p) => $p->getVariableName());
|
||||
$existingReadProperties = collect($docblock->getTagsByName("property-read"))->map(fn($p) => $p->getVariableName());
|
||||
|
||||
return $existingProperties->merge($existingReadProperties);
|
||||
}
|
||||
|
||||
return collect();
|
||||
}
|
||||
|
||||
protected function getParentClass(\ReflectionClass $reflection)
|
||||
{
|
||||
if (!$reflection->getParentClass()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$parent = $reflection->getParentClass()->getName();
|
||||
|
||||
if ($parent === \Illuminate\Database\Eloquent\Model::class) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return \Illuminate\Support\Str::start($parent, '\\');
|
||||
}
|
||||
|
||||
protected function getInfo($className)
|
||||
{
|
||||
if (($data = $this->fromArtisan($className)) === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$reflection = new \ReflectionClass($className);
|
||||
|
||||
$data["extends"] = $this->getParentClass($reflection);
|
||||
|
||||
$existingProperties = $this->collectExistingProperties($reflection);
|
||||
|
||||
$data['attributes'] = collect($data['attributes'])
|
||||
->map(fn($attrs) => array_merge($attrs, [
|
||||
'title_case' => str($attrs['name'])->title()->replace('_', '')->toString(),
|
||||
'documented' => $existingProperties->contains($attrs['name']),
|
||||
'cast' => $this->getCastReturnType($attrs['cast'])
|
||||
]))
|
||||
->toArray();
|
||||
|
||||
$data['scopes'] = collect($reflection->getMethods())
|
||||
->filter(fn(\ReflectionMethod $method) => !$method->isStatic() && ($method->getAttributes(\Illuminate\Database\Eloquent\Attributes\Scope::class) || ($method->isPublic() && str_starts_with($method->name, 'scope'))))
|
||||
->map(fn(\ReflectionMethod $method) => [
|
||||
"name" => str($method->name)->replace('scope', '')->lcfirst()->toString(),
|
||||
"method" => $method->name,
|
||||
"parameters" => collect($method->getParameters())->map($this->getScopeParameterInfo(...)),
|
||||
])
|
||||
->values()
|
||||
->toArray();
|
||||
|
||||
$data['relations'] = collect($data['relations'])
|
||||
->map(fn($relation) => array_merge($relation, [
|
||||
'snake_case' => \Illuminate\Support\Str::snake($relation['name']),
|
||||
]))
|
||||
->toArray();
|
||||
|
||||
$data['uri'] = $reflection->getFileName();
|
||||
|
||||
return [
|
||||
$className => $data,
|
||||
];
|
||||
}
|
||||
|
||||
protected function getScopeParameterInfo(\ReflectionParameter $parameter): array
|
||||
{
|
||||
$result = [
|
||||
"name" => $parameter->getName(),
|
||||
"type" => $this->typeToString($parameter->getType()),
|
||||
"hasDefault" => $parameter->isDefaultValueAvailable(),
|
||||
"isVariadic" => $parameter->isVariadic(),
|
||||
"isPassedByReference" => $parameter->isPassedByReference(),
|
||||
];
|
||||
|
||||
if ($parameter->isDefaultValueAvailable()) {
|
||||
$result['default'] = $this->defaultValueToString($parameter);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function typeToString(?\ReflectionType $type): string
|
||||
{
|
||||
return match (true) {
|
||||
$type instanceof \ReflectionNamedType => $this->namedTypeToString($type),
|
||||
$type instanceof \ReflectionUnionType => $this->unionTypeToString($type),
|
||||
$type instanceof \ReflectionIntersectionType => $this->intersectionTypeToString($type),
|
||||
default => 'mixed',
|
||||
};
|
||||
}
|
||||
|
||||
protected function namedTypeToString(\ReflectionNamedType $type): string
|
||||
{
|
||||
$name = $type->getName();
|
||||
|
||||
if (! $type->isBuiltin() && ! in_array($name, ['self', 'parent', 'static'])) {
|
||||
$name = '\\'.$name;
|
||||
}
|
||||
|
||||
if ($type->allowsNull() && ! in_array($name, ['null', 'mixed', 'void'])) {
|
||||
$name = '?'.$name;
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
protected function unionTypeToString(\ReflectionUnionType $type): string
|
||||
{
|
||||
return implode('|', array_map(function (\ReflectionType $type) {
|
||||
$result = $this->typeToString($type);
|
||||
|
||||
if ($type instanceof \ReflectionIntersectionType) {
|
||||
return "({$result})";
|
||||
}
|
||||
|
||||
return $result;
|
||||
}, $type->getTypes()));
|
||||
}
|
||||
|
||||
protected function intersectionTypeToString(\ReflectionIntersectionType $type): string
|
||||
{
|
||||
return implode('&', array_map($this->typeToString(...), $type->getTypes()));
|
||||
}
|
||||
|
||||
protected function defaultValueToString(\ReflectionParameter $param): string
|
||||
{
|
||||
if ($param->isDefaultValueConstant()) {
|
||||
return '\\'.$param->getDefaultValueConstantName();
|
||||
}
|
||||
|
||||
$value = $param->getDefaultValue();
|
||||
|
||||
return match (true) {
|
||||
is_null($value) => 'null',
|
||||
is_numeric($value) => $value,
|
||||
is_bool($value) => $value ? 'true' : 'false',
|
||||
is_array($value) => '[]',
|
||||
is_object($value) => 'new \\'.get_class($value),
|
||||
default => "'{$value}'",
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
$builder = new class($docblocks) {
|
||||
public function __construct(protected $docblocks) {}
|
||||
|
||||
public function methods()
|
||||
{
|
||||
$reflection = new \ReflectionClass(\Illuminate\Database\Query\Builder::class);
|
||||
|
||||
return collect($reflection->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED))
|
||||
->filter(fn(ReflectionMethod $method) => !str_starts_with($method->getName(), "__") || (!$method->isPublic() && empty($method->getAttributes(\Illuminate\Database\Eloquent\Attributes\Scope::class))))
|
||||
->map(fn(\ReflectionMethod $method) => $this->getMethodInfo($method))
|
||||
->filter()
|
||||
->values();
|
||||
}
|
||||
|
||||
protected function getMethodInfo($method)
|
||||
{
|
||||
[$params, $return] = $this->docblocks->forMethod($method);
|
||||
|
||||
return [
|
||||
"name" => $method->getName(),
|
||||
"parameters" => $params,
|
||||
"return" => $return,
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
echo json_encode([
|
||||
'builderMethods' => $builder->methods(),
|
||||
'models' => $models->all(),
|
||||
]);
|
||||
|
||||
echo LaravelVsCode::outputMarker('END_OUTPUT');
|
||||
|
||||
exit(0);
|
||||
175
vendor/_laravel_ide/discover-5c3cbe5e47b16e6c5fd1967f09c399da.php
vendored
Normal file
175
vendor/_laravel_ide/discover-5c3cbe5e47b16e6c5fd1967f09c399da.php
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
|
||||
|
||||
error_reporting(E_ERROR | E_PARSE);
|
||||
|
||||
define('LARAVEL_START', microtime(true));
|
||||
|
||||
require_once __DIR__ . '/../autoload.php';
|
||||
|
||||
class LaravelVsCode
|
||||
{
|
||||
public static function relativePath($path)
|
||||
{
|
||||
if (!str_contains($path, base_path())) {
|
||||
return (string) $path;
|
||||
}
|
||||
|
||||
return ltrim(str_replace(base_path(), '', realpath($path) ?: $path), DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
public static function isVendor($path)
|
||||
{
|
||||
return str_contains($path, base_path("vendor"));
|
||||
}
|
||||
|
||||
public static function outputMarker($key)
|
||||
{
|
||||
return '__VSCODE_LARAVEL_' . $key . '__';
|
||||
}
|
||||
|
||||
public static function startupError(\Throwable $e)
|
||||
{
|
||||
throw new Error(self::outputMarker('STARTUP_ERROR') . ': ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$app = require_once __DIR__ . '/../../bootstrap/app.php';
|
||||
} catch (\Throwable $e) {
|
||||
LaravelVsCode::startupError($e);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$app->register(new class($app) extends \Illuminate\Support\ServiceProvider
|
||||
{
|
||||
public function boot()
|
||||
{
|
||||
config([
|
||||
'logging.channels.null' => [
|
||||
'driver' => 'monolog',
|
||||
'handler' => \Monolog\Handler\NullHandler::class,
|
||||
],
|
||||
'logging.default' => 'null',
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
|
||||
$kernel->bootstrap();
|
||||
} catch (\Throwable $e) {
|
||||
LaravelVsCode::startupError($e);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo LaravelVsCode::outputMarker('START_OUTPUT');
|
||||
|
||||
$routes = new class {
|
||||
public function all()
|
||||
{
|
||||
return collect(app('router')->getRoutes()->getRoutes())
|
||||
->map(fn(\Illuminate\Routing\Route $route) => $this->getRoute($route))
|
||||
->merge($this->getFolioRoutes());
|
||||
}
|
||||
|
||||
protected function getFolioRoutes()
|
||||
{
|
||||
try {
|
||||
$output = new \Symfony\Component\Console\Output\BufferedOutput();
|
||||
|
||||
\Illuminate\Support\Facades\Artisan::call("folio:list", ["--json" => true], $output);
|
||||
|
||||
$mountPaths = collect(app(\Laravel\Folio\FolioManager::class)->mountPaths());
|
||||
|
||||
return collect(json_decode($output->fetch(), true))->map(fn($route) => $this->getFolioRoute($route, $mountPaths));
|
||||
} catch (\Exception | \Throwable $e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
protected function getFolioRoute($route, $mountPaths)
|
||||
{
|
||||
if ($mountPaths->count() === 1) {
|
||||
$mountPath = $mountPaths[0];
|
||||
} else {
|
||||
$mountPath = $mountPaths->first(fn($mp) => file_exists($mp->path . DIRECTORY_SEPARATOR . $route['view']));
|
||||
}
|
||||
|
||||
$path = $route['view'];
|
||||
|
||||
if ($mountPath) {
|
||||
$path = $mountPath->path . DIRECTORY_SEPARATOR . $path;
|
||||
}
|
||||
|
||||
return [
|
||||
'method' => $route['method'],
|
||||
'uri' => $route['uri'],
|
||||
'name' => $route['name'],
|
||||
'action' => null,
|
||||
'parameters' => [],
|
||||
'filename' => LaravelVsCode::relativePath($path),
|
||||
'line' => 0,
|
||||
];
|
||||
}
|
||||
|
||||
protected function getRoute(\Illuminate\Routing\Route $route)
|
||||
{
|
||||
try {
|
||||
$reflection = $this->getRouteReflection($route);
|
||||
} catch (\Throwable $e) {
|
||||
$reflection = null;
|
||||
}
|
||||
|
||||
return [
|
||||
'method' => collect($route->methods())
|
||||
->filter(fn($method) => $method !== 'HEAD')
|
||||
->implode('|'),
|
||||
'uri' => $route->uri(),
|
||||
'name' => $route->getName(),
|
||||
'action' => $route->getActionName(),
|
||||
'parameters' => $route->parameterNames(),
|
||||
'filename' => $reflection ? LaravelVsCode::relativePath($reflection->getFileName()) : null,
|
||||
'line' => $reflection ? $reflection->getStartLine() : null,
|
||||
'livewire' => $this->getLivewireView($route),
|
||||
];
|
||||
}
|
||||
|
||||
protected function getLivewireView(\Illuminate\Routing\Route $route): ?string
|
||||
{
|
||||
if ($route->getActionName() !== 'Livewire\Features\SupportRouting\LivewirePageController') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $route->defaults['_livewire_component'] ?? null;
|
||||
}
|
||||
|
||||
protected function getRouteReflection(\Illuminate\Routing\Route $route)
|
||||
{
|
||||
if ($route->getActionName() === 'Closure') {
|
||||
return new \ReflectionFunction($route->getAction()['uses']);
|
||||
}
|
||||
|
||||
if (!str_contains($route->getActionName(), '@')) {
|
||||
return new \ReflectionClass($route->getActionName());
|
||||
}
|
||||
|
||||
try {
|
||||
return new \ReflectionMethod($route->getControllerClass(), $route->getActionMethod());
|
||||
} catch (\Throwable $e) {
|
||||
$namespace = app(\Illuminate\Routing\UrlGenerator::class)->getRootControllerNamespace()
|
||||
?? (app()->getNamespace() . 'Http\Controllers');
|
||||
|
||||
return new \ReflectionMethod(
|
||||
$namespace . '\\' . ltrim($route->getControllerClass(), '\\'),
|
||||
$route->getActionMethod(),
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
echo $routes->all()->toJson();
|
||||
|
||||
echo LaravelVsCode::outputMarker('END_OUTPUT');
|
||||
|
||||
exit(0);
|
||||
451
vendor/_laravel_ide/discover-80bc781b69500326630e3fef7a4fdfeb.php
vendored
Normal file
451
vendor/_laravel_ide/discover-80bc781b69500326630e3fef7a4fdfeb.php
vendored
Normal file
@@ -0,0 +1,451 @@
|
||||
<?php
|
||||
|
||||
|
||||
error_reporting(E_ERROR | E_PARSE);
|
||||
|
||||
define('LARAVEL_START', microtime(true));
|
||||
|
||||
require_once __DIR__ . '/../autoload.php';
|
||||
|
||||
class LaravelVsCode
|
||||
{
|
||||
public static function relativePath($path)
|
||||
{
|
||||
if (!str_contains($path, base_path())) {
|
||||
return (string) $path;
|
||||
}
|
||||
|
||||
return ltrim(str_replace(base_path(), '', realpath($path) ?: $path), DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
public static function isVendor($path)
|
||||
{
|
||||
return str_contains($path, base_path("vendor"));
|
||||
}
|
||||
|
||||
public static function outputMarker($key)
|
||||
{
|
||||
return '__VSCODE_LARAVEL_' . $key . '__';
|
||||
}
|
||||
|
||||
public static function startupError(\Throwable $e)
|
||||
{
|
||||
throw new Error(self::outputMarker('STARTUP_ERROR') . ': ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$app = require_once __DIR__ . '/../../bootstrap/app.php';
|
||||
} catch (\Throwable $e) {
|
||||
LaravelVsCode::startupError($e);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$app->register(new class($app) extends \Illuminate\Support\ServiceProvider
|
||||
{
|
||||
public function boot()
|
||||
{
|
||||
config([
|
||||
'logging.channels.null' => [
|
||||
'driver' => 'monolog',
|
||||
'handler' => \Monolog\Handler\NullHandler::class,
|
||||
],
|
||||
'logging.default' => 'null',
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
|
||||
$kernel->bootstrap();
|
||||
} catch (\Throwable $e) {
|
||||
LaravelVsCode::startupError($e);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo LaravelVsCode::outputMarker('START_OUTPUT');
|
||||
|
||||
$components = new class {
|
||||
protected $autoloaded = [];
|
||||
|
||||
protected $prefixes = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->autoloaded = require base_path("vendor/composer/autoload_psr4.php");
|
||||
}
|
||||
|
||||
public function all()
|
||||
{
|
||||
$components = collect(array_merge(
|
||||
$this->getStandardClasses(),
|
||||
$this->getStandardViews(),
|
||||
$this->getNamespaced(),
|
||||
$this->getAnonymousNamespaced(),
|
||||
$this->getAnonymous(),
|
||||
$this->getAliases(),
|
||||
$this->getVendorComponents(),
|
||||
))->groupBy('key')->pipe($this->setProps(...))->map(fn($items) => [
|
||||
'isVendor' => $items->first()['isVendor'],
|
||||
'paths' => $items->pluck('path')->unique()->values(),
|
||||
'props' => $this->formatProps($items),
|
||||
]);
|
||||
|
||||
return [
|
||||
'components' => $components,
|
||||
'prefixes' => $this->prefixes,
|
||||
];
|
||||
}
|
||||
|
||||
protected function formatProps($items)
|
||||
{
|
||||
$props = $items->pluck('props');
|
||||
|
||||
if ($codeBlock = $props->firstWhere(fn ($prop) => is_string($prop))) {
|
||||
return $codeBlock;
|
||||
}
|
||||
|
||||
return $props->values()->filter()->flatMap(fn($i) => $i);
|
||||
}
|
||||
|
||||
protected function getStandardViews()
|
||||
{
|
||||
$path = resource_path('views/components');
|
||||
|
||||
return $this->findFiles($path, 'blade.php');
|
||||
}
|
||||
|
||||
protected function findFiles($path, $extension, $keyCallback = null)
|
||||
{
|
||||
if (!is_dir($path)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$files = \Symfony\Component\Finder\Finder::create()
|
||||
->files()
|
||||
->name("*." . $extension)
|
||||
->in($path);
|
||||
$components = [];
|
||||
$pathRealPath = realpath($path);
|
||||
|
||||
foreach ($files as $file) {
|
||||
$realPath = $file->getRealPath();
|
||||
|
||||
$key = str($realPath)
|
||||
->replace($pathRealPath, '')
|
||||
->ltrim('/\\')
|
||||
->replace('.' . $extension, '')
|
||||
->replace(['/', '\\'], '.')
|
||||
->pipe(fn($str) => $this->handleIndexComponents($str));
|
||||
|
||||
$components[] = [
|
||||
"path" => LaravelVsCode::relativePath($realPath),
|
||||
"isVendor" => LaravelVsCode::isVendor($realPath),
|
||||
"key" => $keyCallback ? $keyCallback($key) : $key,
|
||||
];
|
||||
}
|
||||
|
||||
return $components;
|
||||
}
|
||||
|
||||
protected function getStandardClasses()
|
||||
{
|
||||
$path = app_path('View/Components');
|
||||
|
||||
$appNamespace = collect($this->autoloaded)
|
||||
->filter(fn($paths) => in_array(app_path(), $paths))
|
||||
->keys()
|
||||
->first() ?? '';
|
||||
|
||||
return collect($this->findFiles(
|
||||
$path,
|
||||
'php',
|
||||
fn($key) => $key->explode('.')
|
||||
->map(fn($p) => \Illuminate\Support\Str::kebab($p))
|
||||
->implode('.'),
|
||||
))->map(function ($item) use ($appNamespace) {
|
||||
$class = str($item['path'])
|
||||
->after('View/Components/')
|
||||
->replace('.php', '')
|
||||
->replace('/', '\\')
|
||||
->prepend($appNamespace . 'View\\Components\\')
|
||||
->toString();
|
||||
|
||||
if (!class_exists($class)) {
|
||||
return $item;
|
||||
}
|
||||
|
||||
$reflection = new \ReflectionClass($class);
|
||||
$parameters = collect($reflection->getConstructor()?->getParameters() ?? [])
|
||||
->filter(fn($p) => $p->isPromoted())
|
||||
->flatMap(fn($p) => [$p->getName() => $p->isOptional() ? $this->normalizeDefault($p->getDefaultValue()) : null])
|
||||
->all();
|
||||
|
||||
$props = collect($reflection->getProperties())
|
||||
->filter(fn($p) => $p->isPublic() && $p->getDeclaringClass()->getName() === $class)
|
||||
->map(fn($p) => [
|
||||
'name' => \Illuminate\Support\Str::kebab($p->getName()),
|
||||
'type' => (string) ($p->getType() ?? 'mixed'),
|
||||
'default' => $this->normalizeDefault($p->getDefaultValue() ?? $parameters[$p->getName()] ?? null),
|
||||
]);
|
||||
|
||||
[$except, $props] = $props->partition(fn($p) => $p['name'] === 'except');
|
||||
|
||||
if ($except->isNotEmpty()) {
|
||||
$except = $except->first()['default'];
|
||||
$props = $props->reject(fn($p) => in_array($p['name'], $except));
|
||||
}
|
||||
|
||||
return [
|
||||
...$item,
|
||||
'props' => $props,
|
||||
];
|
||||
})->all();
|
||||
}
|
||||
|
||||
protected function getAliases()
|
||||
{
|
||||
$components = [];
|
||||
|
||||
foreach (\Illuminate\Support\Facades\Blade::getClassComponentAliases() as $key => $class) {
|
||||
if (class_exists($class)) {
|
||||
$reflection = new ReflectionClass($class);
|
||||
|
||||
$components[] = [
|
||||
"path" => LaravelVsCode::relativePath($reflection->getFileName()),
|
||||
"isVendor" => LaravelVsCode::isVendor($reflection->getFileName()),
|
||||
"key" => $key,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $components;
|
||||
}
|
||||
|
||||
protected function getAnonymousNamespaced()
|
||||
{
|
||||
$components = [];
|
||||
|
||||
foreach (\Illuminate\Support\Facades\Blade::getAnonymousComponentNamespaces() as $key => $dir) {
|
||||
$path = collect([$dir, resource_path('views/' . $dir)])->first(fn($p) => is_dir($p));
|
||||
|
||||
if (!$path) {
|
||||
continue;
|
||||
}
|
||||
|
||||
array_push(
|
||||
$components,
|
||||
...$this->findFiles(
|
||||
$path,
|
||||
'blade.php',
|
||||
fn($k) => $k->kebab()->prepend($key . "::"),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $components;
|
||||
}
|
||||
|
||||
protected function getAnonymous()
|
||||
{
|
||||
$components = [];
|
||||
|
||||
foreach (\Illuminate\Support\Facades\Blade::getAnonymousComponentPaths() as $item) {
|
||||
array_push(
|
||||
$components,
|
||||
...$this->findFiles(
|
||||
$item['path'],
|
||||
'blade.php',
|
||||
function (\Illuminate\Support\Stringable $key) use ($item) {
|
||||
$prefix = $item['prefix'] ? $item['prefix'] . '::' : '';
|
||||
$key = $key->kebab();
|
||||
$keys = [];
|
||||
|
||||
$keys[] = $key->prepend($prefix);
|
||||
|
||||
if ($item['prefix'] === 'flux') {
|
||||
$keys[] = $key->prepend('flux:');
|
||||
}
|
||||
|
||||
return $keys;
|
||||
},
|
||||
)
|
||||
);
|
||||
|
||||
if (!in_array($item['prefix'], $this->prefixes)) {
|
||||
$this->prefixes[] = $item['prefix'];
|
||||
}
|
||||
}
|
||||
|
||||
return $components;
|
||||
}
|
||||
|
||||
protected function getVendorComponents(): array
|
||||
{
|
||||
$components = [];
|
||||
|
||||
/** @var \Illuminate\View\Factory $view */
|
||||
$view = \Illuminate\Support\Facades\App::make('view');
|
||||
|
||||
/** @var \Illuminate\View\FileViewFinder $finder */
|
||||
$finder = $view->getFinder();
|
||||
|
||||
/** @var array<string, array<int, string>> $views */
|
||||
$views = $finder->getHints();
|
||||
|
||||
foreach ($views as $key => $paths) {
|
||||
foreach ($paths as $path) {
|
||||
$path .= '/components';
|
||||
|
||||
if (!is_dir($path)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
array_push(
|
||||
$components,
|
||||
...$this->findFiles(
|
||||
$path,
|
||||
'blade.php',
|
||||
fn (\Illuminate\Support\Stringable $k) => $k->kebab()->prepend($key.'::'),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $components;
|
||||
}
|
||||
|
||||
protected function handleIndexComponents($str)
|
||||
{
|
||||
if ($str->endsWith('.index')) {
|
||||
return $str->replaceLast('.index', '');
|
||||
}
|
||||
|
||||
if (!$str->contains('.')) {
|
||||
return $str;
|
||||
}
|
||||
|
||||
$parts = $str->explode('.');
|
||||
|
||||
if ($parts->slice(-2)->unique()->count() === 1) {
|
||||
$parts->pop();
|
||||
|
||||
return str($parts->implode('.'));
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
protected function getNamespaced()
|
||||
{
|
||||
$namespaced = \Illuminate\Support\Facades\Blade::getClassComponentNamespaces();
|
||||
$components = [];
|
||||
|
||||
foreach ($namespaced as $key => $classNamespace) {
|
||||
$path = $this->getNamespacePath($classNamespace);
|
||||
|
||||
if (!$path) {
|
||||
continue;
|
||||
}
|
||||
|
||||
array_push(
|
||||
$components,
|
||||
...$this->findFiles(
|
||||
$path,
|
||||
'php',
|
||||
fn($k) => $k->kebab()->prepend($key . "::"),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $components;
|
||||
}
|
||||
|
||||
protected function normalizeDefault($value)
|
||||
{
|
||||
if ($value instanceof \UnitEnum) {
|
||||
return $value instanceof \BackedEnum
|
||||
? $value->value
|
||||
: $value::class.'::'.$value->name;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
protected function getNamespacePath($classNamespace)
|
||||
{
|
||||
foreach ($this->autoloaded as $ns => $paths) {
|
||||
if (!str_starts_with($classNamespace, $ns)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($paths as $p) {
|
||||
$dir = str($classNamespace)
|
||||
->replace($ns, '')
|
||||
->replace('\\', '/')
|
||||
->prepend($p . DIRECTORY_SEPARATOR)
|
||||
->toString();
|
||||
|
||||
if (is_dir($dir)) {
|
||||
return $dir;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function setProps($groups)
|
||||
{
|
||||
try {
|
||||
$compiler = app('blade.compiler');
|
||||
} catch (\Throwable $e) {
|
||||
return $groups;
|
||||
}
|
||||
|
||||
return $groups->map(function ($group) use ($compiler) {
|
||||
return $group->transform(function ($component) use ($compiler) {
|
||||
if (isset($component['props'])) {
|
||||
return $component;
|
||||
}
|
||||
|
||||
if (!str($component['path'])->endsWith('.blade.php')) {
|
||||
return $component;
|
||||
}
|
||||
|
||||
if (! $props = $this->parseProps($compiler, $component)) {
|
||||
return $component;
|
||||
}
|
||||
|
||||
return array_merge($component, ['props' => $props]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
protected function parseProps($compiler, array $component): ?string
|
||||
{
|
||||
$content = file_get_contents(base_path($component['path']));
|
||||
|
||||
$result = '';
|
||||
|
||||
$compiler->directive('props', function ($expression) use (&$result) {
|
||||
return $result = $expression;
|
||||
});
|
||||
|
||||
$compiler->compileString($content);
|
||||
|
||||
if (empty($result)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return '@props('.$result.')';
|
||||
}
|
||||
};
|
||||
|
||||
echo json_encode($components->all());
|
||||
|
||||
echo LaravelVsCode::outputMarker('END_OUTPUT');
|
||||
|
||||
exit(0);
|
||||
89
vendor/_laravel_ide/discover-e4fb95a586b679e2bcd4cf4f0871799d.php
vendored
Normal file
89
vendor/_laravel_ide/discover-e4fb95a586b679e2bcd4cf4f0871799d.php
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
|
||||
error_reporting(E_ERROR | E_PARSE);
|
||||
|
||||
define('LARAVEL_START', microtime(true));
|
||||
|
||||
require_once __DIR__ . '/../autoload.php';
|
||||
|
||||
class LaravelVsCode
|
||||
{
|
||||
public static function relativePath($path)
|
||||
{
|
||||
if (!str_contains($path, base_path())) {
|
||||
return (string) $path;
|
||||
}
|
||||
|
||||
return ltrim(str_replace(base_path(), '', realpath($path) ?: $path), DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
public static function isVendor($path)
|
||||
{
|
||||
return str_contains($path, base_path("vendor"));
|
||||
}
|
||||
|
||||
public static function outputMarker($key)
|
||||
{
|
||||
return '__VSCODE_LARAVEL_' . $key . '__';
|
||||
}
|
||||
|
||||
public static function startupError(\Throwable $e)
|
||||
{
|
||||
throw new Error(self::outputMarker('STARTUP_ERROR') . ': ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$app = require_once __DIR__ . '/../../bootstrap/app.php';
|
||||
} catch (\Throwable $e) {
|
||||
LaravelVsCode::startupError($e);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$app->register(new class($app) extends \Illuminate\Support\ServiceProvider
|
||||
{
|
||||
public function boot()
|
||||
{
|
||||
config([
|
||||
'logging.channels.null' => [
|
||||
'driver' => 'monolog',
|
||||
'handler' => \Monolog\Handler\NullHandler::class,
|
||||
],
|
||||
'logging.default' => 'null',
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
|
||||
$kernel->bootstrap();
|
||||
} catch (\Throwable $e) {
|
||||
LaravelVsCode::startupError($e);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo LaravelVsCode::outputMarker('START_OUTPUT');
|
||||
|
||||
$pageExtensions = config(
|
||||
'inertia.pages.extensions',
|
||||
config('inertia.page_extensions', config('inertia.testing.page_extensions', [])),
|
||||
);
|
||||
|
||||
$pagePaths = config(
|
||||
'inertia.pages.paths',
|
||||
config('inertia.page_paths', config('inertia.testing.page_paths', [])),
|
||||
);
|
||||
|
||||
echo json_encode([
|
||||
'page_extensions' => $pageExtensions,
|
||||
'page_paths' => collect($pagePaths)->flatMap(function($path) {
|
||||
$relativePath = LaravelVsCode::relativePath($path);
|
||||
|
||||
return [$relativePath, mb_strtolower($relativePath)];
|
||||
})->unique()->values(),
|
||||
]);
|
||||
|
||||
echo LaravelVsCode::outputMarker('END_OUTPUT');
|
||||
|
||||
exit(0);
|
||||
Reference in New Issue
Block a user