diff --git a/README.md b/README.md index 22b8e0584..fc6efafe5 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,8 @@ Str::macro('concat', function(string $str1, string $str2) : string { }); ``` +You can add any custom Macroable traits to detect in the `macroable_traits` config option. + ### Automatic PHPDocs for models If you don't want to write your properties yourself, you can use the command `php artisan ide-helper:models` to generate diff --git a/config/ide-helper.php b/config/ide-helper.php index 5519dca8b..34c31449c 100644 --- a/config/ide-helper.php +++ b/config/ide-helper.php @@ -334,4 +334,18 @@ // 'ide-helper:models --nowrite', ], + /* + |-------------------------------------------------------------------------- + | Macroable Traits + |-------------------------------------------------------------------------- + | + | Define which traits should be considered capable of adding Macro. + | You can add any custom trait that behaves like the original Laravel one. + | + */ + 'macroable_traits' => [ + \Filament\Support\Concerns\Macroable::class, + \Spatie\Macroable\Macroable::class, + ], + ]; diff --git a/src/Alias.php b/src/Alias.php index 7ca59c583..50d74a914 100644 --- a/src/Alias.php +++ b/src/Alias.php @@ -46,6 +46,8 @@ class Alias protected $phpdoc = null; protected $classAliases = []; + protected $isMacroable = false; + /** @var ConfigRepository */ protected $config; @@ -60,12 +62,13 @@ class Alias * @param array $magicMethods * @param array $interfaces */ - public function __construct($config, $alias, $facade, $magicMethods = [], $interfaces = []) + public function __construct($config, $alias, $facade, $magicMethods = [], $interfaces = [], $isMacroable = false) { $this->alias = $alias; $this->magicMethods = $magicMethods; $this->interfaces = $interfaces; $this->config = $config; + $this->isMacroable = $isMacroable; // Make the class absolute $facade = '\\' . ltrim($facade, '\\'); @@ -395,8 +398,7 @@ protected function detectMethods() // Check if the class is macroable // (Eloquent\Builder is also macroable but doesn't use Macroable trait) - $traits = collect($reflection->getTraitNames()); - if ($traits->contains('Illuminate\Support\Traits\Macroable') || $class === EloquentBuilder::class) { + if ($this->isMacroable || $class === EloquentBuilder::class) { $properties = $reflection->getStaticProperties(); $macros = isset($properties['macros']) ? $properties['macros'] : []; foreach ($macros as $macro_name => $macro_func) { diff --git a/src/Generator.php b/src/Generator.php index 0c36850ca..78607b64b 100644 --- a/src/Generator.php +++ b/src/Generator.php @@ -35,6 +35,7 @@ class Generator protected $magic = []; protected $interfaces = []; protected $helpers; + protected array $macroableTraits = []; /** * @param \Illuminate\Config\Repository $config @@ -341,7 +342,7 @@ protected function addMacroableClasses(Collection $aliases) continue; } - $aliases[] = new Alias($this->config, $class, $class, [], $this->interfaces); + $aliases[] = new Alias($this->config, $class, $class, [], $this->interfaces, true); } } @@ -363,8 +364,18 @@ protected function getMacroableClasses(Collection $aliases) ->filter(function ($class) { $traits = class_uses_recursive($class); - // Filter only classes with the macroable trait - return isset($traits[Macroable::class]); + if (isset($traits[Macroable::class])) { + return true; + } + + // Filter only classes with a macroable trait + foreach ($this->config->get('ide-helper.macroable_traits', []) as $trait) { + if (isset($traits[$trait])) { + return true; + } + } + + return false; }) ->filter(function ($class) use ($aliases) { $class = Str::start($class, '\\'); diff --git a/tests/AliasTest.php b/tests/AliasTest.php index e0aa43373..5188eac5e 100644 --- a/tests/AliasTest.php +++ b/tests/AliasTest.php @@ -16,31 +16,6 @@ */ class AliasTest extends TestCase { - /** - * @covers ::detectMethods - */ - public function testDetectMethodsMacroableMacros(): void - { - // Mock - $macro = __FUNCTION__; - $alias = new AliasMock(); - - // Macros - Builder::macro( - $macro, - function () { - // empty - } - ); - - // Prepare - $alias->setClasses([Builder::class]); - $alias->detectMethods(); - - // Test - $this->assertNotNull($this->getAliasMacro($alias, Builder::class, $macro)); - } - /** * @covers ::detectMethods */ @@ -50,7 +25,7 @@ public function testDetectMethodsEloquentBuilderMacros(): void $macro = __FUNCTION__; $alias = new AliasMock(); - // Macros + // Macrosx EloquentBuilder::macro( $macro, function () {