Commit 507e7280 by 杨树贤

fix

parent d29646e4
<?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');
echo collect(app("Illuminate\Contracts\Http\Kernel")->getMiddlewareGroups())
->merge(app("Illuminate\Contracts\Http\Kernel")->getRouteMiddleware())
->map(function ($middleware, $key) {
$result = [
"class" => null,
"path" => null,
"line" => null,
"parameters" => null,
"groups" => [],
];
if (is_array($middleware)) {
$result["groups"] = collect($middleware)->map(function ($m) {
if (!class_exists($m)) {
return [
"class" => $m,
"path" => null,
"line" => null
];
}
$reflected = new ReflectionClass($m);
$reflectedMethod = $reflected->getMethod("handle");
return [
"class" => $m,
"path" => LaravelVsCode::relativePath($reflected->getFileName()),
"line" =>
$reflectedMethod->getFileName() === $reflected->getFileName()
? $reflectedMethod->getStartLine()
: null
];
})->all();
return $result;
}
$reflected = new ReflectionClass($middleware);
$reflectedMethod = $reflected->getMethod("handle");
$result = array_merge($result, [
"class" => $middleware,
"path" => LaravelVsCode::relativePath($reflected->getFileName()),
"line" => $reflectedMethod->getStartLine(),
]);
$parameters = collect($reflectedMethod->getParameters())
->filter(function ($rc) {
return $rc->getName() !== "request" && $rc->getName() !== "next";
})
->map(function ($rc) {
return $rc->getName() . ($rc->isVariadic() ? "..." : "");
});
if ($parameters->isEmpty()) {
return $result;
}
return array_merge($result, [
"parameters" => $parameters->implode(",")
]);
})
->toJson();
echo LaravelVsCode::outputMarker('END_OUTPUT');
exit(0);
<?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' => $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 ? $reflection->getFileName() : null,
'line' => $reflection ? $reflection->getStartLine() : 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);
<?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');
$translator = new class
{
public $paths = [];
public $values = [];
public $paramResults = [];
public $params = [];
public $emptyParams = [];
public $directoriesToWatch = [];
public function all()
{
$final = [];
foreach ($this->retrieve() as $value) {
if ($value instanceof \Illuminate\Support\LazyCollection) {
foreach ($value as $val) {
$dotKey = $val["k"];
$final[$dotKey] ??= [];
$final[$dotKey][$val["la"]] = $val["vs"];
}
} else {
foreach ($value["vs"] as $v) {
$dotKey = "{$value["k"]}.{$v['k']}";
$final[$dotKey] ??= [];
$final[$dotKey][$value["la"]] = $v['arr'];
}
}
}
return $final;
}
protected function retrieve()
{
$loader = app("translator")->getLoader();
$namespaces = $loader->namespaces();
$paths = $this->getPaths($loader);
$default = collect($paths)->flatMap(
fn($path) => $this->collectFromPath($path)
);
$namespaced = collect($namespaces)->flatMap(
fn($path, $namespace) => $this->collectFromPath($path, $namespace)
);
return $default->merge($namespaced);
}
protected function getPaths($loader)
{
$reflection = new ReflectionClass($loader);
$property = null;
if ($reflection->hasProperty("paths")) {
$property = $reflection->getProperty("paths");
} else if ($reflection->hasProperty("path")) {
$property = $reflection->getProperty("path");
}
if ($property !== null) {
$property->setAccessible(true);
return \Illuminate\Support\Arr::wrap($property->getValue($loader));
}
return [];
}
public function collectFromPath(string $path, ?string $namespace = null)
{
$realPath = realpath($path);
if (!is_dir($realPath)) {
return [];
}
if (!LaravelVsCode::isVendor($realPath)) {
$this->directoriesToWatch[] = LaravelVsCode::relativePath($realPath);
}
return array_map(
fn($file) => $this->fromFile($file, $path, $namespace),
\Illuminate\Support\Facades\File::allFiles($realPath),
);
}
protected function fromFile($file, $path, $namespace)
{
if (pathinfo($file, PATHINFO_EXTENSION) === 'json') {
return $this->fromJsonFile($file, $path, $namespace);
}
return $this->fromPhpFile($file, $path, $namespace);
}
protected function linesFromJsonFile($file)
{
$contents = file_get_contents($file);
try {
$json = json_decode($contents, true) ?? [];
} catch (\Throwable $e) {
return [[], []];
}
if (count($json) === 0) {
return [[], []];
}
$lines = explode(PHP_EOL, $contents);
$encoded = array_map(
fn($k) => [json_encode($k), $k],
array_keys($json),
);
$result = [];
$searchRange = 2;
foreach ($encoded as $index => $keys) {
// Pretty likely to be on the line that is the index, go happy path first
if (strpos($lines[$index + 1] ?? '', $keys[0]) !== false) {
$result[$keys[1]] = $index + 2;
continue;
}
// Search around the index, like to be within 2 lines
$start = max(0, $index - $searchRange);
$end = min($index + $searchRange, count($lines) - 1);
$current = $start;
while ($current <= $end) {
if (strpos($lines[$current], $keys[0]) !== false) {
$result[$keys[1]] = $current + 1;
break;
}
$current++;
}
}
return [$json, $result];
}
protected function linesFromPhpFile($file)
{
$tokens = token_get_all(file_get_contents($file));
$found = [];
$inArrayKey = true;
$arrayDepth = -1;
$depthKeys = [];
foreach ($tokens as $token) {
if (!is_array($token)) {
if ($token === '[') {
$inArrayKey = true;
$arrayDepth++;
}
if ($token === ']') {
$inArrayKey = true;
$arrayDepth--;
array_pop($depthKeys);
}
continue;
}
if ($token[0] === T_DOUBLE_ARROW) {
$inArrayKey = false;
}
if ($inArrayKey && $token[0] === T_CONSTANT_ENCAPSED_STRING) {
$depthKeys[$arrayDepth] = trim($token[1], '"\'');
\Illuminate\Support\Arr::set($found, implode('.', $depthKeys), $token[2]);
}
if (!$inArrayKey && $token[0] === T_CONSTANT_ENCAPSED_STRING) {
$inArrayKey = true;
}
}
return \Illuminate\Support\Arr::dot($found);
}
protected function getDotted($key, $lang)
{
try {
return \Illuminate\Support\Arr::dot(
\Illuminate\Support\Arr::wrap(
__($key, [], $lang),
),
);
} catch (\Throwable $e) {
// Most likely, in this case, the lang file doesn't return an array
return [];
}
}
protected function getPathIndex($file)
{
$path = LaravelVsCode::relativePath($file);
$index = $this->paths[$path] ?? null;
if ($index !== null) {
return $index;
}
$this->paths[$path] = count($this->paths);
return $this->paths[$path];
}
protected function getValueIndex($value)
{
$index = $this->values[$value] ?? null;
if ($index !== null) {
return $index;
}
$this->values[$value] = count($this->values);
return $this->values[$value];
}
protected function getParamIndex($key)
{
$processed = $this->params[$key] ?? null;
if ($processed) {
return $processed[0];
}
if (in_array($key, $this->emptyParams)) {
return null;
}
$params = preg_match_all("/\:([A-Za-z0-9_]+)/", $key, $matches)
? $matches[1]
: [];
if (count($params) === 0) {
$this->emptyParams[] = $key;
return null;
}
$paramKey = json_encode($params);
$paramIndex = $this->paramResults[$paramKey] ?? null;
if ($paramIndex !== null) {
$this->params[$key] = [$paramIndex, $params];
return $paramIndex;
}
$paramIndex = count($this->paramResults);
$this->paramResults[$paramKey] = $paramIndex;
$this->params[$key] = [$paramIndex, $params];
return $paramIndex;
}
protected function fromJsonFile($file, $path, $namespace)
{
$lang = pathinfo($file, PATHINFO_FILENAME);
$relativePath = $this->getPathIndex($file);
$lines = \Illuminate\Support\Facades\File::lines($file);
return \Illuminate\Support\LazyCollection::make(function () use ($file, $lang, $relativePath, $lines) {
[$json, $lines] = $this->linesFromJsonFile($file);
foreach ($json as $key => $value) {
yield [
"k" => $key,
"la" => $lang,
"vs" => [
$this->getValueIndex($value),
$relativePath,
$lines[$key] ?? null,
$this->getParamIndex($key),
],
];
}
});
}
protected function fromPhpFile($file, $path, $namespace)
{
$key = pathinfo($file, PATHINFO_FILENAME);
if ($namespace) {
$key = "{$namespace}::{$key}";
}
$lang = collect(explode(DIRECTORY_SEPARATOR, str_replace($path, "", $file)))
->filter()
->slice(-2, 1)
->first();
$relativePath = $this->getPathIndex($file);
$lines = $this->linesFromPhpFile($file);
return [
"k" => $key,
"la" => $lang,
"vs" => \Illuminate\Support\LazyCollection::make(function () use ($key, $lang, $relativePath, $lines) {
foreach ($this->getDotted($key, [], $lang) as $key => $value) {
if (!array_key_exists($key, $lines) || is_array($value)) {
continue;
}
yield [
'k' => $key,
'arr' => [
$this->getValueIndex($value),
$relativePath,
$lines[$key],
$this->getParamIndex($value),
],
];
}
}),
];
}
};
echo json_encode([
'default' => \Illuminate\Support\Facades\App::currentLocale(),
'translations' => $translator->all(),
'paths' => array_keys($translator->paths),
'values' => array_keys($translator->values),
'params' => array_map(fn($p) => json_decode($p, true), array_keys($translator->paramResults)),
'to_watch' => $translator->directoriesToWatch,
]);
echo LaravelVsCode::outputMarker('END_OUTPUT');
exit(0);
<?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');
echo collect(app()->getBindings())
->filter(fn ($binding) => ($binding['concrete'] ?? null) !== null)
->flatMap(function ($binding, $key) {
$boundTo = new ReflectionFunction($binding['concrete']);
$closureClass = $boundTo->getClosureScopeClass();
if ($closureClass === null) {
return [];
}
return [
$key => [
'path' => LaravelVsCode::relativePath($closureClass->getFileName()),
'class' => $closureClass->getName(),
'line' => $boundTo->getStartLine(),
],
];
})->toJson();
echo LaravelVsCode::outputMarker('END_OUTPUT');
exit(0);
<?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');
echo json_encode([
...config('inertia.testing', []),
'page_paths' => collect(config('inertia.testing.page_paths', []))->flatMap(function($path) {
$relativePath = LaravelVsCode::relativePath($path);
return [$relativePath, mb_strtolower($relativePath)];
})->unique()->values(),
]);
echo LaravelVsCode::outputMarker('END_OUTPUT');
exit(0);
<?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');
echo json_encode([
'php_version' => phpversion(),
'laravel_version' => app()->version(),
]);
echo LaravelVsCode::outputMarker('END_OUTPUT');
exit(0);
<?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');
echo json_encode([
[
'key' => 'base_path',
'path' => base_path(),
],
[
'key' => 'resource_path',
'path' => resource_path(),
],
[
'key' => 'config_path',
'path' => config_path(),
],
[
'key' => 'app_path',
'path' => app_path(),
],
[
'key' => 'database_path',
'path' => database_path(),
],
[
'key' => 'lang_path',
'path' => lang_path(),
],
[
'key' => 'public_path',
'path' => public_path(),
],
[
'key' => 'storage_path',
'path' => storage_path(),
],
]);
echo LaravelVsCode::outputMarker('END_OUTPUT');
exit(0);
<?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');
$blade = new class {
public function getAllViews()
{
$finder = app("view")->getFinder();
$paths = collect($finder->getPaths())->flatMap(fn($path) => $this->findViews($path));
$hints = collect($finder->getHints())->flatMap(
fn($paths, $key) => collect($paths)->flatMap(
fn($path) => collect($this->findViews($path))->map(
fn($value) => array_merge($value, ["key" => "{$key}::{$value["key"]}"])
)
)
);
[$local, $vendor] = $paths
->merge($hints)
->values()
->partition(fn($v) => !$v["isVendor"]);
return $local
->sortBy("key", SORT_NATURAL)
->merge($vendor->sortBy("key", SORT_NATURAL));
}
public function getAllComponents()
{
$namespaced = \Illuminate\Support\Facades\Blade::getClassComponentNamespaces();
$autoloaded = require base_path("vendor/composer/autoload_psr4.php");
$components = [];
foreach ($namespaced as $key => $ns) {
$path = null;
foreach ($autoloaded as $namespace => $paths) {
if (str_starts_with($ns, $namespace)) {
foreach ($paths as $p) {
$test = str($ns)->replace($namespace, '')->replace('\\', '/')->prepend($p . DIRECTORY_SEPARATOR)->toString();
if (is_dir($test)) {
$path = $test;
break;
}
}
break;
}
}
if (!$path) {
continue;
}
$files = \Symfony\Component\Finder\Finder::create()
->files()
->name("*.php")
->in($path);
foreach ($files as $file) {
$realPath = $file->getRealPath();
$components[] = [
"path" => str_replace(base_path(DIRECTORY_SEPARATOR), '', $realPath),
"isVendor" => str_contains($realPath, base_path("vendor")),
"key" => str($realPath)
->replace(realpath($path), "")
->replace(".php", "")
->ltrim(DIRECTORY_SEPARATOR)
->replace(DIRECTORY_SEPARATOR, ".")
->kebab()
->prepend($key . "::"),
];
}
}
return $components;
}
protected function findViews($path)
{
$paths = [];
if (!is_dir($path)) {
return $paths;
}
$files = \Symfony\Component\Finder\Finder::create()
->files()
->name("*.blade.php")
->in($path);
foreach ($files as $file) {
$paths[] = [
"path" => str_replace(base_path(DIRECTORY_SEPARATOR), '', $file->getRealPath()),
"isVendor" => str_contains($file->getRealPath(), base_path("vendor")),
"key" => str($file->getRealPath())
->replace(realpath($path), "")
->replace(".blade.php", "")
->ltrim(DIRECTORY_SEPARATOR)
->replace(DIRECTORY_SEPARATOR, ".")
];
}
return $paths;
}
};
echo json_encode($blade->getAllViews()->merge($blade->getAllComponents()));
echo LaravelVsCode::outputMarker('END_OUTPUT');
exit(0);
<?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');
$local = collect(glob(config_path("/*.php")))
->merge(glob(config_path("**/*.php")))
->map(fn ($path) => [
(string) str($path)
->replace([config_path('/'), ".php"], "")
->replace(DIRECTORY_SEPARATOR, "."),
$path
]);
$vendor = collect(glob(base_path("vendor/**/**/config/*.php")))->map(fn (
$path
) => [
(string) str($path)
->afterLast(DIRECTORY_SEPARATOR . "config" . DIRECTORY_SEPARATOR)
->replace(".php", "")
->replace(DIRECTORY_SEPARATOR, "."),
$path
]);
$configPaths = $local
->merge($vendor)
->groupBy(0)
->map(fn ($items)=>$items->pluck(1));
$cachedContents = [];
$cachedParsed = [];
function vsCodeGetConfigValue($value, $key, $configPaths) {
$parts = explode(".", $key);
$toFind = $key;
$found = null;
while (count($parts) > 0) {
$toFind = implode(".", $parts);
if ($configPaths->has($toFind)) {
$found = $toFind;
break;
}
array_pop($parts);
}
if ($found === null) {
return null;
}
$file = null;
$line = null;
if ($found === $key) {
$file = $configPaths->get($found)[0];
} else {
foreach ($configPaths->get($found) as $path) {
$cachedContents[$path] ??= file_get_contents($path);
$cachedParsed[$path] ??= token_get_all($cachedContents[$path]);
$keysToFind = str($key)
->replaceFirst($found, "")
->ltrim(".")
->explode(".");
if (is_numeric($keysToFind->last())) {
$index = $keysToFind->pop();
if ($index !== "0") {
return null;
}
$key = collect(explode(".", $key));
$key->pop();
$key = $key->implode(".");
$value = "array(...)";
}
$nextKey = $keysToFind->shift();
$expectedDepth = 1;
$depth = 0;
foreach ($cachedParsed[$path] as $token) {
if ($token === "[") {
$depth++;
}
if ($token === "]") {
$depth--;
}
if (!is_array($token)) {
continue;
}
$str = trim($token[1], '"\'');
if (
$str === $nextKey &&
$depth === $expectedDepth &&
$token[0] === T_CONSTANT_ENCAPSED_STRING
) {
$nextKey = $keysToFind->shift();
$expectedDepth++;
if ($nextKey === null) {
$file = $path;
$line = $token[2];
break;
}
}
}
if ($file) {
break;
}
}
}
return [
"name" => $key,
"value" => $value,
"file" => $file === null ? null : str_replace(base_path(DIRECTORY_SEPARATOR), '', $file),
"line" => $line
];
}
function vsCodeUnpackDottedKey($value, $key) {
$arr = [$key => $value];
$parts = explode('.', $key);
array_pop($parts);
while (count($parts)) {
$arr[implode('.', $parts)] = 'array(...)';
array_pop($parts);
}
return $arr;
}
echo collect(\Illuminate\Support\Arr::dot(config()->all()))
->mapWithKeys(fn($value, $key) => vsCodeUnpackDottedKey($value, $key))
->map(fn ($value, $key) => vsCodeGetConfigValue($value, $key, $configPaths))
->filter()
->values()
->toJson();
echo LaravelVsCode::outputMarker('END_OUTPUT');
exit(0);
<?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');
echo collect(app(\Illuminate\View\Compilers\BladeCompiler::class)->getCustomDirectives())
->map(function ($customDirective, $name) {
if ($customDirective instanceof \Closure) {
return [
'name' => $name,
'hasParams' => (new ReflectionFunction($customDirective))->getNumberOfParameters() >= 1,
];
}
if (is_array($customDirective)) {
return [
'name' => $name,
'hasParams' => (new ReflectionMethod($customDirective[0], $customDirective[1]))->getNumberOfParameters() >= 1,
];
}
return null;
})
->filter()
->values()
->toJson();
echo LaravelVsCode::outputMarker('END_OUTPUT');
exit(0);
<?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')->map(fn($items) => [
'isVendor' => $items->first()['isVendor'],
'paths' => $items->pluck('path')->values(),
'props' => $items->pluck('props')->values()->filter()->flatMap(fn($i) => $i),
]);
return [
'components' => $components,
'prefixes' => $this->prefixes,
];
}
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() ? $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' => $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',
fn($key) => $key
->kebab()
->prepend(($item['prefix'] ?? ':') . ':')
->ltrim(':'),
)
);
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) {
// First is always optional override in the resources/views folder
$path = $paths[0] . '/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 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;
}
};
echo json_encode($components->all());
echo LaravelVsCode::outputMarker('END_OUTPUT');
exit(0);
<?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()
{
collect(glob(base_path('**/Models/*.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($method) => $method->isPublic() && !$method->isStatic() && str_starts_with($method->name, 'scope'))
->map(fn($method) => str($method->name)->replace('scope', '')->lcfirst()->toString())
->values()
->toArray();
$data['uri'] = $reflection->getFileName();
return [
$className => $data,
];
}
};
$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))
->filter(fn(ReflectionMethod $method) => !str_starts_with($method->getName(), "__"))
->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);
<?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');
collect(glob(base_path('**/Models/*.php')))->each(fn($file) => include_once($file));
$modelPolicies = 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,
]))
->flatMap(fn($class) => [
$class => \Illuminate\Support\Facades\Gate::getPolicyFor($class),
])
->filter(fn($policy) => $policy !== null);
function vsCodeGetPolicyInfo($policy, $model)
{
$methods = (new ReflectionClass($policy))->getMethods();
return collect($methods)->map(fn(ReflectionMethod $method) => [
'key' => $method->getName(),
'uri' => $method->getFileName(),
'policy' => is_string($policy) ? $policy : get_class($policy),
'model' => $model,
'line' => $method->getStartLine(),
])->filter(fn($ability) => !in_array($ability['key'], ['allow', 'deny']));
}
echo collect(\Illuminate\Support\Facades\Gate::abilities())
->map(function ($policy, $key) {
$reflection = new \ReflectionFunction($policy);
$policyClass = null;
$closureThis = $reflection->getClosureThis();
if ($closureThis !== null) {
if (get_class($closureThis) === \Illuminate\Auth\Access\Gate::class) {
$vars = $reflection->getClosureUsedVariables();
if (isset($vars['callback'])) {
[$policyClass, $method] = explode('@', $vars['callback']);
$reflection = new \ReflectionMethod($policyClass, $method);
}
}
}
return [
'key' => $key,
'uri' => $reflection->getFileName(),
'policy' => $policyClass,
'line' => $reflection->getStartLine(),
];
})
->merge(
collect(\Illuminate\Support\Facades\Gate::policies())->flatMap(fn($policy, $model) => vsCodeGetPolicyInfo($policy, $model)),
)
->merge(
$modelPolicies->flatMap(fn($policy, $model) => vsCodeGetPolicyInfo($policy, $model)),
)
->values()
->groupBy('key')
->map(fn($item) => $item->map(fn($i) => \Illuminate\Support\Arr::except($i, 'key')))
->toJson();
echo LaravelVsCode::outputMarker('END_OUTPUT');
exit(0);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment