mirror of
https://github.com/barryvdh/laravel-ide-helper.git
synced 2026-08-18 10:07:12 +00:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c341fb72d1 | ||
|
|
b441594c80 | ||
|
|
04c1a8d444 |
@@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Add support for enum default arguments using enum cases. [#1464 / d8vjork](https://github.com/barryvdh/laravel-ide-helper/pull/1464)
|
- Add support for enum default arguments using enum cases. [#1464 / d8vjork](https://github.com/barryvdh/laravel-ide-helper/pull/1464)
|
||||||
|
- Add support for real-time facades in the helper file. [#1455 / filipac](https://github.com/barryvdh/laravel-ide-helper/pull/1455)
|
||||||
|
|
||||||
2024-02-05, 2.14.0
|
2024-02-05, 2.14.0
|
||||||
------------------
|
------------------
|
||||||
|
|||||||
@@ -113,6 +113,10 @@ The generator tries to identify the real class, but if it cannot be found, you c
|
|||||||
Some classes need a working database connection. If you do not have a default working connection, some facades will not be included.
|
Some classes need a working database connection. If you do not have a default working connection, some facades will not be included.
|
||||||
You can use an in-memory SQLite driver by adding the `-M` option.
|
You can use an in-memory SQLite driver by adding the `-M` option.
|
||||||
|
|
||||||
|
If you use [real-time facades](https://laravel.com/docs/master/facades#real-time-facades) in your app, those will also be included in the generated file using a `@mixin` annotation and extending the original class underneath the facade.
|
||||||
|
|
||||||
|
**Note**: this feature uses the generated real-time facades files in the `storage/framework/cache` folder. Those files are generated on-demand as you use the real-time facade, so if the framework has not generated that first, it will not be included in the helper file. Run the route/command/code first and then regenerate the helper file and this time the real-time facade will be included in it.
|
||||||
|
|
||||||
You can choose to include helper files. This is not enabled by default, but you can override it with the `--helpers (-H)` option.
|
You can choose to include helper files. This is not enabled by default, but you can override it with the `--helpers (-H)` option.
|
||||||
The `Illuminate/Support/helpers.php` is already set up, but you can add/remove your own files in the config file.
|
The `Illuminate/Support/helpers.php` is already set up, but you can add/remove your own files in the config file.
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,16 @@ namespace <?= $namespace == '__root' ? '' : trim($namespace, '\\') ?> {
|
|||||||
|
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
|
|
||||||
|
<?php foreach($real_time_facades as $name): ?>
|
||||||
|
<?php $nested = explode('\\', str_replace('\\' . class_basename($name), '', $name)); ?>
|
||||||
|
namespace <?php echo implode('\\', $nested); ?> {
|
||||||
|
/**
|
||||||
|
* @mixin <?= str_replace('Facades', '', $name) ?>
|
||||||
|
*/
|
||||||
|
class <?= class_basename($name) ?> extends <?= str_replace('Facades', '', $name) ?> {}
|
||||||
|
}
|
||||||
|
<?php endforeach; ?>
|
||||||
|
|
||||||
<?php if ($helpers) : ?>
|
<?php if ($helpers) : ?>
|
||||||
namespace {
|
namespace {
|
||||||
<?= $helpers ?>
|
<?= $helpers ?>
|
||||||
|
|||||||
+53
-3
@@ -16,6 +16,10 @@ use Illuminate\Support\Collection;
|
|||||||
use Illuminate\Support\Facades\Facade;
|
use Illuminate\Support\Facades\Facade;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Illuminate\Support\Traits\Macroable;
|
use Illuminate\Support\Traits\Macroable;
|
||||||
|
use PhpParser\Lexer\Emulative;
|
||||||
|
use PhpParser\Node\Stmt\Class_;
|
||||||
|
use PhpParser\Node\Stmt\Namespace_;
|
||||||
|
use PhpParser\Parser\Php7;
|
||||||
use ReflectionClass;
|
use ReflectionClass;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
@@ -76,6 +80,7 @@ class Generator
|
|||||||
return $this->view->make('helper')
|
return $this->view->make('helper')
|
||||||
->with('namespaces_by_extends_ns', $this->getAliasesByExtendsNamespace())
|
->with('namespaces_by_extends_ns', $this->getAliasesByExtendsNamespace())
|
||||||
->with('namespaces_by_alias_ns', $this->getAliasesByAliasNamespace())
|
->with('namespaces_by_alias_ns', $this->getAliasesByAliasNamespace())
|
||||||
|
->with('real_time_facades', $this->getRealTimeFacades())
|
||||||
->with('helpers', $this->helpers)
|
->with('helpers', $this->helpers)
|
||||||
->with('version', $app->version())
|
->with('version', $app->version())
|
||||||
->with('include_fluent', $this->config->get('ide-helper.include_fluent', true))
|
->with('include_fluent', $this->config->get('ide-helper.include_fluent', true))
|
||||||
@@ -153,9 +158,9 @@ class Generator
|
|||||||
if ($facade == 'Illuminate\Support\Facades\Redis' && $name == 'Redis' && !class_exists('Predis\Client')) {
|
if ($facade == 'Illuminate\Support\Facades\Redis' && $name == 'Redis' && !class_exists('Predis\Client')) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip the swoole
|
// Skip the swoole
|
||||||
if ($facade == 'SwooleTW\Http\Server\Facades\Server' && $name == 'Server' && !class_exists('Swoole\Http\Server')) {
|
if ($facade == 'SwooleTW\Http\Server\Facades\Server' && $name == 'Server' && !class_exists('Swoole\Http\Server')) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,6 +179,51 @@ class Generator
|
|||||||
return $aliases;
|
return $aliases;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getRealTimeFacades()
|
||||||
|
{
|
||||||
|
$facades = [];
|
||||||
|
$realTimeFacadeFiles = glob(storage_path('framework/cache/facade-*.php'));
|
||||||
|
foreach ($realTimeFacadeFiles as $file) {
|
||||||
|
try {
|
||||||
|
$name = $this->getFullyQualifiedClassNameInFile($file);
|
||||||
|
$facades[$name] = $name;
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $facades;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getFullyQualifiedClassNameInFile(string $path)
|
||||||
|
{
|
||||||
|
$contents = file_get_contents($path);
|
||||||
|
|
||||||
|
$parsers = new Php7(new Emulative());
|
||||||
|
|
||||||
|
$parsed = collect($parsers->parse($contents) ?: []);
|
||||||
|
|
||||||
|
$namespace = $parsed->first(function ($node) {
|
||||||
|
return $node instanceof Namespace_;
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($namespace) {
|
||||||
|
$name = $namespace->name->toString();
|
||||||
|
|
||||||
|
$class = collect($namespace->stmts)->first(function ($node) {
|
||||||
|
return $node instanceof Class_;
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($class) {
|
||||||
|
$name .= '\\' . $class->name->toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Regroup aliases by namespace of extended classes
|
* Regroup aliases by namespace of extended classes
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhpDocWithEnumDefaults\Models;
|
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhpDocWithEnumDefaults\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
|
||||||
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhpDocWithEnumDefaults\Enums\PostStatus;
|
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhpDocWithEnumDefaults\Enums\PostStatus;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
class Post extends Model
|
class Post extends Model
|
||||||
{
|
{
|
||||||
public function scopeHasStatus(Builder $query, ?PostStatus $status = PostStatus::Published)
|
public function scopeHasStatus(Builder $query, ?PostStatus $status = PostStatus::Published)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Barryvdh\LaravelIdeHelper\Tests;
|
||||||
|
|
||||||
|
use Barryvdh\LaravelIdeHelper\Generator;
|
||||||
|
use Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider;
|
||||||
|
use Illuminate\Foundation\AliasLoader;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\View;
|
||||||
|
use PhpParser\Lexer\Emulative;
|
||||||
|
use PhpParser\Node\Stmt\Class_;
|
||||||
|
use PhpParser\Node\Stmt\Namespace_;
|
||||||
|
use PhpParser\Parser\Php7;
|
||||||
|
|
||||||
|
class RealTimeFacadesTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testRealTimeFacades()
|
||||||
|
{
|
||||||
|
// Add the views path to the view finder so the generator actually generates the file
|
||||||
|
View::addLocation(__DIR__ . '/../resources/views');
|
||||||
|
|
||||||
|
// Clear cached real-time facades
|
||||||
|
$cachedFacades = glob(storage_path('framework/cache/facade-*.php'));
|
||||||
|
foreach ($cachedFacades as $cachedFacade) {
|
||||||
|
unlink($cachedFacade);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy stubs to storage path as if the real-time facades were cached by the framework
|
||||||
|
copy(
|
||||||
|
__DIR__ . '/stubs/facade-0e0385307adf5db34c7986ecbd11646061356ec8.php',
|
||||||
|
storage_path('framework/cache/facade-0e0385307adf5db34c7986ecbd11646061356ec8.php')
|
||||||
|
);
|
||||||
|
copy(
|
||||||
|
__DIR__ . '/stubs/facade-9431b04ec1494fc71a1bc848f020044aba2af7b1.php',
|
||||||
|
storage_path('framework/cache/facade-9431b04ec1494fc71a1bc848f020044aba2af7b1.php')
|
||||||
|
);
|
||||||
|
|
||||||
|
// new instance of the generator which we test
|
||||||
|
$generator = new Generator($this->app['config'], $this->app['view'], null, false);
|
||||||
|
|
||||||
|
// Clear aliases and macros to have a small output file
|
||||||
|
AliasLoader::getInstance()->setAliases([]);
|
||||||
|
Request::flushMacros();
|
||||||
|
|
||||||
|
// Generate the helper file and return the content
|
||||||
|
$content = $generator->generate();
|
||||||
|
|
||||||
|
$this->assertStringContainsString('namespace Facades\Illuminate\Foundation\Exceptions {', $content, 'Could not find Facades\Illuminate\Foundation\Exceptions namespace in the generated helper file.');
|
||||||
|
$this->assertStringContainsString('namespace Facades\App\Exceptions {', $content, 'Could not find Facades\App\Exceptions namespace in the generated helper file.');
|
||||||
|
|
||||||
|
$parsed = collect((new Php7(new Emulative()))->parse($content) ?: []);
|
||||||
|
|
||||||
|
// test the Facades\Illuminate\Foundation\Exceptions namespace in the generated helper file
|
||||||
|
$frameworkExceptionsNamespace = $parsed->first(function ($stmt) {
|
||||||
|
return ($stmt instanceof Namespace_) && $stmt->name->toString() === 'Facades\Illuminate\Foundation\Exceptions';
|
||||||
|
});
|
||||||
|
$this->assertNotNull($frameworkExceptionsNamespace, 'Could not find Facades\Illuminate\Foundation\Exceptions namespace');
|
||||||
|
$this->assertSame('Facades\Illuminate\Foundation\Exceptions', $frameworkExceptionsNamespace->name->toString());
|
||||||
|
$this->verifyNamespace($frameworkExceptionsNamespace, 'Illuminate\Foundation\Exceptions\Handler');
|
||||||
|
|
||||||
|
// test the Facades\App\Exceptions namespace in the generated helper file
|
||||||
|
$appExceptionsNamespace = $parsed->first(function ($stmt) {
|
||||||
|
return ($stmt instanceof Namespace_) && $stmt->name->toString() === 'Facades\App\Exceptions';
|
||||||
|
});
|
||||||
|
$this->assertNotNull($appExceptionsNamespace, 'Could not find Facades\App\Exceptions namespace');
|
||||||
|
$this->assertSame('Facades\App\Exceptions', $appExceptionsNamespace->name->toString());
|
||||||
|
$this->verifyNamespace($appExceptionsNamespace, 'App\Exceptions\Handler');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function verifyNamespace(Namespace_ $namespace, $target)
|
||||||
|
{
|
||||||
|
$stmts = collect($namespace->stmts);
|
||||||
|
|
||||||
|
$this->assertInstanceOf(Class_::class, $stmts[0], 'Expected instance of Class_');
|
||||||
|
|
||||||
|
$statement = $stmts[0];
|
||||||
|
$this->assertArrayHasKey('comments', $statement->getAttributes());
|
||||||
|
|
||||||
|
$this->assertStringContainsString('@mixin \\' . $target, $statement->getAttributes()['comments'][0]->getText(), 'Mixin comment not found');
|
||||||
|
$this->assertSame(class_basename($target), $statement->name->toString(), 'Class name not found');
|
||||||
|
$this->assertSame($target, $statement->extends->toString(), 'Class extends not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getPackageProviders($app)
|
||||||
|
{
|
||||||
|
return [IdeHelperServiceProvider::class];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Facades\Illuminate\Foundation\Exceptions;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Facade;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \Illuminate\Foundation\Exceptions\Handler
|
||||||
|
*/
|
||||||
|
class Handler extends Facade
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the registered name of the component.
|
||||||
|
*/
|
||||||
|
protected static function getFacadeAccessor(): string
|
||||||
|
{
|
||||||
|
return 'Illuminate\Foundation\Exceptions\Handler';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Facades\App\Exceptions;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Facade;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see \App\Exceptions\Handler
|
||||||
|
*/
|
||||||
|
class Handler extends Facade
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the registered name of the component.
|
||||||
|
*/
|
||||||
|
protected static function getFacadeAccessor(): string
|
||||||
|
{
|
||||||
|
return 'App\Exceptions\Handler';
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user