Compare commits

...
160 Commits
Author SHA1 Message Date
Barry vd. Heuvel 8740a9a158 Fix CS 2019-09-08 11:56:38 +02:00
liquid207 d344cdc842 Fix phpcs (#803) 2019-09-08 11:55:17 +02:00
Mandy Schoep 5e411ef104 Do not added instances of a anonymous class to the phpstorm_meta file (#806) 2019-09-08 11:46:25 +02:00
Barry vd. Heuvel 499a2113b3 Check if method exists 2019-09-08 11:45:23 +02:00
Barry vd. Heuvel f8a8cb18e0 Always require doctrine 2019-09-08 11:36:40 +02:00
Barry vd. Heuvel 16eb4f65ee Update readme.md 2019-09-03 19:51:13 +02:00
Kevin Bond 0edf8f750e remove monolog configuration (fixes #818) (#820) 2019-09-03 19:49:46 +02:00
Johan van Helden 1b15d2930b fix the identation in the config (#817) 2019-08-31 12:53:08 +02:00
Matthew Hailwood 3668e3821a Add support for custom cast classes (#816)
* Add support for custom cast classes

* Fix unrelated code style warning.
2019-08-30 07:32:01 +02:00
Barry vd. Heuvel 7b4cef1ea4 Update composer.json 2019-08-23 14:21:37 +02:00
Stanislas cd2a71d43c ModelsCommand: Remove question mark (#812)
Sorry this is a bit nitpicky 😅
2019-08-06 07:54:53 +02:00
edvordo c9132b28a6 Chages to x2Many relationships detection & adds relationship_count docBlock comment (#783)
* x to Many relationships are detected via a `Many` keyword in the relationship object class name
   * reason: example: `belongsTo` was incorrectly recognized as `belongsToMany`
 * adds `@property-read int|null $x2Many_relationship_method_name_count` model class docBlock comment
   * when model makes use of `withCount` or `loadCount` there is a property on the resource `$instance->relationship_method_count` that states the count of related models
   * can be `NULL` when `withCount` or `loadCount` aren't used
2019-06-18 16:38:42 +02:00
Guilherme Pressutto 8ab6e0536b Fixed meta not working with app()->makeWith() (#791) 2019-05-29 17:09:57 +02:00
Theodore R. Smith 87ebe458e9 Removed confusing README installation instructions (#786)
While installing this for my project, I didn't see the `--dev` instructions until I was literally editing this README for a pull request.

Since laravel-ide-helper is only designed for development purposes, let's just remove the superfluous entry altogether. Smart devs who for some crazy reason need it on prod will know to remove the `--dev`, while less knowledgeable devs won't shoot themselves in the foot accidentally.
2019-04-17 22:07:56 +02:00
leo108 9ef14f83be use Throwable instead of Exception (#779) 2019-03-27 05:56:31 +01:00
Brent Roose 39c148ad42 Support for custom builder classes (#782) 2019-03-26 11:38:22 +01:00
Francis Lavoie 2b3c9a2449 Fix BC introduced in #765 (#778)
See my comment https://github.com/barryvdh/laravel-ide-helper/pull/765#issuecomment-471014271:

The change in #765 made anonymous functions get reflected with `ReflectionMethod` instead of `ReflectionFunction`, which makes it lose the doc comment. This means that the generated helpers are missing their return types. This is because Closure is also an object and callable.

To fix it, Closure should be excluded from that new condition.
2019-03-12 11:38:49 +01:00
Matthew Brown 725711022b Make autoload exception more specific (#777)
This is a nice-to-have ([as I'm currently overriding it](https://github.com/psalm/laravel-psalm-plugin/commit/a700c89061d151d1c08851abd93d834f9183534d)), but might help other packages.
2019-03-05 10:24:51 +01:00
neoteknic 881f77156c Fix php 7.3 bug (#772) 2019-03-02 15:15:16 +01:00
neoteknic 0fad511954 Fix Bug PHP 7.3 & L5.8 (#774)
add cast (string) to disable bug ($type can be null)
2019-03-02 15:14:46 +01:00
Stan Daniëls 754bb4d075 Add support for invokable classes as macro function (#765)
Macros can be used with invokable classes, like so.

```
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Response;

class ResponseMacroServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Response::macro('foo', new Foo());
    }
}

class Foo
{
    public function __invoke()
    {
        return 'foobar';
    }
}
```

When running `ide-helper:generate` the following fatal error was thrown.

```  Symfony\Component\Debug\Exception\FatalThrowableError  : ReflectionFunction::__construct() expects parameter 1 to be string, object given```

This commit fixes this error.
2019-02-18 20:54:27 +01:00
edcoreweb bcb881b20d Nested relations detection. (#763) 2019-02-03 16:59:09 +01:00
Tim Philips d00600d769 Include DocBloc’s from classes to allow deeper code inspection (#745)
* Add support to include DocBloc’s from classes to allow further code inspection

* Adjust for PSR2

* Additional fix for PSR2
2019-01-28 21:38:57 +01:00
Ahmed Fathy 858dd40844 Install doctrine/dbal on development (#753) 2019-01-28 21:25:55 +01:00
Kyle 4cd11a4d33 Allow Laravel 5.8 (#754) 2019-01-28 21:24:50 +01:00
Barry vd. Heuvel 5439781e7c Update composer.json 2018-12-19 13:13:32 +01:00
+pikari 190bf07c05 fix: warning when call the instance method (#735) 2018-12-19 13:12:44 +01:00
Vladimir Yuldashev 3d7f124089 prevent loading views if view class not in container (#691) 2018-12-19 13:12:05 +01:00
hubertnnn 32df0a3bc6 Fix: Parametrized relationships prevent generation of metadata (#719) 2018-12-19 13:11:08 +01:00
Patrick 2f8283a746 Optionally write missing Laravel Model DocBlock (#700)
* Fix missing doc-block.

* Fixes a bug where a missing DocBlock caused errors.

* Change Option Shorthand to W
Because it is not allowed to have two char shorthands for options.

* Revert code refactoring.

* Fix copied config header.
2018-12-19 13:10:53 +01:00
Barry vd. Heuvel 2a63b31475 Merge pull request #730 from apollopy/master
if aliases not Redis, don't skip
2018-12-19 13:10:13 +01:00
Barry vd. Heuvel 494d1593c8 Merge pull request #732 from HikaruYasuda/fix/duplicateMacroMethods
fix: Macro methods are duplicated registration.
2018-12-19 13:08:48 +01:00
Barry vd. Heuvel e513fb34dc Merge pull request #743 from JeppeKnockaert/fix-travis-timeout
bugfix - Increase composer update timeout in Travis
2018-12-19 13:08:22 +01:00
Barry vd. Heuvel 5db82752ef Merge pull request #742 from JeppeKnockaert/update-reflection-docblock-to-v2-0-6
Update ReflectionDocBlock to v2.0.6
2018-12-19 13:08:07 +01:00
Jeppe Knockaert 1f555bc194 bugfix - Increase composer update timeout in Travis
The composer update takes about 12 minutes, which is just over the
10 minute timeout in Travis.
2018-12-18 08:55:50 +01:00
Jeppe Knockaert b0ce5325de Update ReflectionDocBlock to v2.0.6
This update improves the parsing of return types, allowing array return
types to be recognized.

This was needed to properly recognize the files and allFiles methods as
duplicates (the function filtering duplicate definitions -
`removeDuplicateMethodsFromPhpDoc` in `Alias.php` - didn't recognise
them as duplicates, because the return type was seen as part of the name).
2018-12-17 18:15:59 +01:00
Barry vd. Heuvel aeae59d0af Merge pull request #740 from JeppeKnockaert/fix-cannot-redeclare-method
bugfix - Prevent redeclaring methods inside Aliases
2018-12-17 17:40:51 +01:00
Jeppe Knockaert 001719245c bugfix - Prevent redeclaring methods inside Aliases
The getMethods function gets called both in the removeDuplicateMethodsFromPhpDoc
function and in helper.php, which causes the method detection to be performed twice.

Parts of the method detection includes a check for duplicate methods, but Macro
methods for example, aren't checked for duplicates.

Instead of checking everywhere if we're not adding duplicates, I've included a
check in the getMethods call to just use the already generated methods
if they have been generated already.
2018-12-12 14:46:18 +01:00
Barry vd. Heuvel 99226c92b7 Merge pull request #736 from JeppeKnockaert/fix-real-name-for-closures
bugfix - Do not use the real_name for closures
2018-12-11 12:35:36 +01:00
Jeppe Knockaert dda63bf8df bugfix - Do not use the real_name for closures
Closures do not have a method name that makes sense to use in the ide_helper
file.

e.g. Illuminate\Foundation\Providers\{closure} would be the real_name instead of
just validate. So for the closure methods, we should just use the provided
methodName instead.
2018-12-10 14:14:34 +01:00
HikaruYasuda 3d7f45479e fix: Macro methods are duplicated registration. 2018-12-04 10:33:00 +09:00
ApolloPY 7905dd3926 if aliases not Redis, don't skip 2018-11-30 20:30:51 +08:00
ApolloPY 8d135a1dea Merge pull request #1 from barryvdh/master
merge master
2018-11-30 20:26:36 +08:00
Barry vd. Heuvel 858e730c00 Merge pull request #720 from JeppeKnockaert/remove-duplicate-functions-from-phpdoc
Prevent duplicate function declarations in docblocks
2018-11-07 21:27:14 +01:00
Jeppe Knockaert 2ab961e734 Prevent duplicate function declarations in docblocks
When a method is declared both in the phpdoc and in the class itself,
PhpStorm (2018.3) complains about duplicate function declarations, preventing
correct code hinting.

To solve this, I remove the already declared functions from the generated dockblocks.
2018-11-07 20:59:15 +01:00
Barry vd. Heuvel 981ff45b43 Merge pull request #707 from crhg/fix_getAliases
Fix alias class existence determination #698
2018-10-06 11:35:51 +02:00
Barry vd. Heuvel 8174730714 Merge pull request #714 from pahan35/fix-missed-autocomplete-in-header-view
Fix missed autocomplete in helper view
2018-10-06 11:34:14 +02:00
Barry vd. Heuvel ae5b623cf2 Merge pull request #713 from pahan35/fix-missed-methods-with-same-name
Fix missed methods with same name
2018-10-06 11:33:25 +02:00
Pavlo Zhukov eff51d41b3 Add missed getRealName() call for $namespaces_by_alias group 2018-10-01 03:25:34 +03:00
Pavlo Zhukov b14d983f74 Change comments style to allow folding and make its clear 2018-10-01 00:50:28 +03:00
Pavlo Zhukov 1fdc866fb0 Fix missed autocomplete in helper view 2018-10-01 00:39:40 +03:00
Pavlo Zhukov d7359b86d4 Avoid code duplication in constructors 2018-10-01 00:20:54 +03:00
Pavlo Zhukov 5d8d93273f Fix missed helpers for abstract methods the same name but different classes 2018-10-01 00:02:03 +03:00
Manabu Matsui 30e5300e49 Fix alias class existence determination 2018-09-14 10:16:13 +09:00
Barry vd. Heuvel 593e0d4aa7 Merge pull request #701 from brendt/master
Add ::query support
2018-09-07 12:07:33 +02:00
Brent Roose e7d4cb322f Update ModelsCommand.php 2018-09-07 10:29:59 +02:00
Brent Roose 5318f485e2 Add ::query support 2018-09-07 10:27:20 +02:00
Barry vd. Heuvel 7db1843473 Remove Eloquent mixin thing 2018-09-06 20:41:09 +02:00
Barry vd. Heuvel 1989d0e794 Update .travis.yml 2018-09-04 16:19:48 +02:00
Barry vd. Heuvel 09db8c9a76 Update composer.json 2018-08-31 15:28:09 +02:00
Barry vd. Heuvel 4aa43fa613 Merge pull request #690 from kevinpijning/laravel-5.7-support
Laravel 5.7 support
2018-08-21 11:29:23 +02:00
kevin d55b48476e Laravel 5.7 support
Added Laravel 5.7 support
2018-08-15 09:57:53 +02:00
Barry vd. Heuvel 45e84b9070 Merge pull request #678 from BinotaLIU/add-fluent-change
add change modifier
2018-07-16 09:12:17 +02:00
BinotaLIU f472c26601 add change modifier 2018-07-05 19:31:23 +08:00
Barry vd. Heuvel 1deadced46 Merge pull request #675 from glamorous/bugfix/phpstan-error-formatter
bugfix - Space/Enter between starting php tag and comment for PHPStan
2018-06-21 14:14:18 +02:00
Jonas De Smet e1d1352ac5 bugfix - Space/Enter between starting php tag and comment for PHPStan 2018-06-19 14:59:59 +02:00
Barry vd. Heuvel 65e3278c86 Merge pull request #668 from falnyr/final-abstract-class
Added support for abstract/final models.
2018-06-13 10:16:26 +02:00
Barry vd. Heuvel efd7e51566 Merge pull request #671 from eidng8/patch-2
suppress formatter in meta file
2018-06-13 10:16:01 +02:00
Barry vd. Heuvel 2a5dda6a27 Merge pull request #672 from eidng8/patch-3
suppress formatter in helper file
2018-06-13 10:15:47 +02:00
Jackey Cheung 6577af8464 suppress formatter in helper file 2018-06-13 10:24:58 +08:00
Jackey Cheung 6c7bc371f9 suppress formatter in meta file 2018-06-13 10:21:51 +08:00
Jan Alfred Richter 217b8989c2 Added support for abstract/final models. 2018-05-31 15:39:22 +12:00
Barry vd. Heuvel c003eb40d7 Merge pull request #667 from BinotaLIU/master
nullable is actually support an argument
2018-05-29 17:29:40 +02:00
BinotaLIU 1a3d32f0d1 nullable actually support an argument 2018-05-29 22:28:49 +08:00
Barry vd. Heuvel bd733b7b7c Merge pull request #665 from JeppeKnockaert/fix-model-comments
Only skip non-models when generating docs
2018-05-24 14:10:51 +02:00
Jeppe Knockaert 93630fdf62 Only skip non-models when generating docs
The fix made in PR https://github.com/barryvdh/laravel-ide-helper/pull/614 for issue https://github.com/barryvdh/laravel-ide-helper/issues/253 was incorrect as it resulted in comments
no longer being generated for Models that are not Pivot Rlations.

This PR allow comments to be generated for both Pivot Models (as they are
a subclass of Eloquent\Model) and normal Models.
2018-05-24 11:43:03 +02:00
Barry vd. Heuvel f64ed52205 Merge pull request #664 from huydang284/master
ide-helper:models error when model's method has parameters and also has relation
2018-05-24 10:32:51 +02:00
Huy Dang ba28841870 fix case relation method has parameter 2018-05-22 13:26:27 +07:00
Barry vd. Heuvel b02a0bc6c9 Update phpunit.xml.dist 2018-05-07 13:03:54 +02:00
Barry vd. Heuvel a665961fb9 Update .travis.yml 2018-05-07 12:56:29 +02:00
Barry vd. Heuvel 83852e9de0 Update .travis.yml 2018-05-07 12:41:54 +02:00
Barry vd. Heuvel d2f29d997b Update .travis.yml 2018-05-07 11:56:03 +02:00
Barry vd. Heuvel cbacb28f19 Update .travis.yml 2018-05-07 11:55:44 +02:00
Barry vd. Heuvel 930e5bd301 Update composer.json 2018-05-07 11:49:06 +02:00
Barry vd. Heuvel 930d258cd4 Update composer.json 2018-05-07 11:48:47 +02:00
Barry vd. Heuvel 94248adae8 Merge pull request #600 from mike-grinspan/patch-1
Use Illuminate\Support\Carbon instead of Carbon\Carbon
2018-05-07 11:44:40 +02:00
Barry vd. Heuvel 50ecd8b815 Update CS, typo 2018-05-07 11:38:57 +02:00
Barry vd. Heuvel 1b70277203 Typo 2018-05-07 11:25:19 +02:00
Barry vd. Heuvel 87a03fd9c4 Merge pull request #576 from yuklia/docs-enhancment
Add notice about "Package Auto-Discovery" to docs
2018-05-07 11:23:21 +02:00
Barry vd. Heuvel b8a73bcab9 Merge pull request #581 from soltmar/master
Changed overwriting confirmation message
2018-05-07 11:23:06 +02:00
Barry vd. Heuvel 0556991c69 Merge pull request #583 from inxilpro/support-fakes
Support for ::fake() calls
2018-05-07 11:22:33 +02:00
Barry vd. Heuvel be78ac62cd Merge pull request #589 from mfn/patch-1
Keep "null"-ness of column even with model casts
2018-05-07 11:21:47 +02:00
Barry vd. Heuvel 265f00c322 Update LICENSE.md 2018-05-07 11:20:53 +02:00
Barry vd. Heuvel bbd96d3616 Merge pull request #609 from lx1036/patch
Sort keys for generating stable .phpstorm.meta.php
2018-05-07 11:17:33 +02:00
Barry vd. Heuvel 8d913089db Merge pull request #614 from WickedSik/master
Allow command to find and use pivot models
2018-05-07 11:17:07 +02:00
Barry vd. Heuvel 9a2588cb3a Merge pull request #612 from westphalen/master
Added Validator and Gate facades for Lumen
2018-05-07 11:16:47 +02:00
Barry vd. Heuvel e7fa36bdc3 Merge pull request #629 from bedezign/smart-reset
"smart-reset": Reset properties/methods, but keep the text
2018-05-07 11:15:59 +02:00
Barry vd. Heuvel b1e868c5fc Merge pull request #621 from Zae/feature/fix-callable-macros
Support php's array callable format for macro's.
2018-05-07 11:15:49 +02:00
Barry vd. Heuvel 203d60dc8c Merge branch 'master' into feature/fix-callable-macros 2018-05-07 11:15:43 +02:00
Barry vd. Heuvel f5275b700a Merge pull request #632 from JeppeKnockaert/feature/add-morphedByMany-relation
Add morphedByMany relationship
2018-05-07 11:13:27 +02:00
Barry vd. Heuvel 046a9bcc77 Merge pull request #647 from eidng8/eidng8-suppress-formatter
suppress PHPStorm formatter
2018-05-07 11:10:25 +02:00
Barry vd. Heuvel c6191830ab Merge pull request #660 from TomzxForks/fixes/659-use-composer-classmapgenerator
Replace Symfony ClassMapGenerator with Composer ClassMapGenerator
2018-05-07 11:09:58 +02:00
Barry vd. Heuvel cfff7721bc Merge pull request #661 from tzurbaev/patch-1
Remove `mixed` typehint from `Fluent::default` method
2018-05-07 11:09:27 +02:00
Timur Zurbaev 4691bc5fbd Remove mixed typehint from Fluent::default method 2018-05-05 10:09:30 +08:00
Tom Rochette b1b05b694b Remove dependecy to Symfony\Component\ClassLoader\ClassMapGenerator and replace it with Composer\Autoload\ClassMapGenerator. 2018-05-03 16:02:16 -04:00
Barry vd. Heuvel 98d6087a1e Merge pull request #568 from fisharebest/artisan-optimize
The 'artisan optimize' command is now deprecated.
2018-03-26 12:18:59 +02:00
Jackey Cheung c7b7ebf1b5 suppress PHPStorm formatter 2018-03-21 11:36:02 +08:00
Jeppe Knockaert 17982029f0 Move long one-line array to multiple lines 2018-02-14 12:15:38 +01:00
Jeppe Knockaert bda5120e9a Add morphedByMany relationship 2018-02-14 12:06:45 +01:00
Steve Guns d961482d22 Fixed PHPCS PSR2 issues 2018-02-14 08:59:19 +01:00
Steve Guns 8852b1ca9d Added "smart-reset": Reset properties/methods, but keep the docBlock text, if any 2018-02-11 19:09:33 +01:00
Barry vd. Heuvel b644e48801 Merge pull request #618 from glamorous/feature/docblocks-on-classes
Add DocBlocks for classes too
2018-02-10 14:47:48 +01:00
Barry vd. Heuvel 09610da602 Merge pull request #626 from barryvdh/revert-624-Fix/623
Revert "Fixes a bug where a missing DocBlock caused errors"
2018-02-08 17:01:01 +01:00
Barry vd. Heuvel 2d56afce8e Revert "Fixes a bug where a missing DocBlock caused errors" 2018-02-08 17:00:48 +01:00
Barry vd. Heuvel 5c304db44f Merge pull request #624 from iPaat/Fix/623
Fixes a bug where a missing DocBlock caused errors
2018-02-08 08:56:07 +01:00
Patrick 1fc4284af6 Fixes for Travis. 2018-02-07 13:24:36 +01:00
Patrick ea113e8c0b Fixes a bug where a missing DocBlock caused errors 2018-02-07 13:17:03 +01:00
Barry vd. Heuvel 387efb9b42 Allow L5.6 2018-02-07 09:31:35 +01:00
Ezra Pool 8ab907f219 Support php's array callable format for macro's.
This allows you to define methods like this as well: Str::macro('name', [$this, 'method']);
2018-02-03 21:10:48 +01:00
Jonas De Smet e29e035135 Add DocBlocks for classes too 2018-02-01 15:53:32 +01:00
Jurrien Dokter 7b2786ac2b Fixing issue #253 2018-01-27 13:01:07 +01:00
Sune Westphalen 76bd86dbaf Added Validator and Gate facades for Lumen. 2018-01-23 13:56:22 +07:00
Xiang Liu 7b067198a6 Sort keys for generating stable .phpstorm.meta.php 2018-01-15 12:44:44 +08:00
Mike b6f525b320 Use Illuminate\Support\Carbon instead of Carbon\Carbon in config/ide-helper.php 2017-12-27 17:26:16 -05:00
Mike d65f1cedcd Use Illuminate\Support\Carbon instead of Carbon\Carbon in readme.md 2017-12-27 17:25:44 -05:00
Mike df6b1b6f82 Use Illuminate\Support\Carbon instead of Carbon\Carbon 2017-12-27 17:17:00 -05:00
Markus Fischer 76a1952c41 Keep "null"-ness of column even with model casts
A cast in Laravel should only affect the type, but not the database intrinsics whether a column accepts `null` or not.

As an example, consider this table (Postgres syntax):
```sql
CREATE TABLE foo (
  some_column jsonb
);
```
This will be generated as: `@property string|null $some_column`

When providing a the following casts on the model:
```php
protected $casts = [
  'some_column' => 'array',
];
```
then the generated property changes to: `@property array $some_column`

However the DB still accepts `null`, but this can't be expressed via the casts.

This change will make the null "sticky" and generate: `@property array|null $some_column`
2017-10-28 18:01:18 +02:00
Chris Morrell d45b02efb1 Support for ::fake() calls 2017-10-13 11:41:30 -04:00
Mariusz b0abafb8c7 Changed overwriting confirmation message
When running php artisan ide-helper:models below message was presented:
"Do you want to overwrite the existing model files? Choose no to write to _ide_helper_models.php instead? (Yes/No):  (yes/no) [no]:"
This commit changes message to:
"Do you want to overwrite the existing model files? Choose no to write to _ide_helper_models.php instead? (yes/no) [no]:"
2017-10-11 11:43:16 +01:00
Yulia Kostrikova 6b0e9ec48d Add notice about "Package Auto-Discovery" to docs 2017-09-21 00:40:49 +03:00
M. Vugteveen 28f0ac3781 also show time in generated files (#574) 2017-09-13 14:18:03 +02:00
Greg Roach 721a7cd3f7 The 'artisan optimize' command is deprecated 2017-09-02 21:25:00 +01:00
Carl Evison ea6d6d0105 update to the latest code intel (#567) 2017-09-02 17:44:59 +02:00
Subodh Dahal 01320a48e3 Bugfix: Undefined property: Barryvdh\LaravelIdeHelper\Console\MetaCommand::$config (#562) 2017-08-28 15:16:15 +02:00
Charles Peterson fedcb57295 Add an eloquent command (#544)
* Add an eloquent command for adding the `@mixin \Eloquent` to the Illuminate\Database\Eloquent\Model

* spacing updates...

* multi-line function call syntax

* Write helper mixin to Eloquent/Model after helper created

* Cleanup into helper - similar to Generator

* syntax cleanup
2017-08-28 15:12:54 +02:00
Barry vd. Heuvel ce72ff4663 Remove exit for static code analysers 2017-08-28 13:39:24 +02:00
Zakaria Acharki cb6f52f4d6 Minor typo fix (#548) 2017-08-28 13:38:22 +02:00
Chris Morrell 55c9bfc33b Allow for configurable meta filename (#553) 2017-08-28 13:37:22 +02:00
Chris Morrell a9ea231679 Support higher order tap() (#554) 2017-08-28 13:35:56 +02:00
Jan.Weskamp 2b1273c45e Fix for Laravel 5.5 (#540)
Command fire method is now handle
2017-07-16 02:24:12 +02:00
Stidges 08d39c125f Add back leading slash on meta class names (#532) 2017-07-06 21:25:44 +02:00
dannehl 87a02ff574 added L55-support (#525) 2017-06-16 16:08:59 +02:00
Michael Tsang 9e42ce11f4 return eloquent builder instead of plain database builder from model methods (#522) 2017-06-15 17:22:20 +02:00
Stidges dca7fa7b10 Use new PhpStorm advanced metadata format (#523) 2017-06-14 20:49:19 +02:00
Abdelrahman Omran 0e4b9b77c3 Support Auto-Discovery (#524) 2017-06-14 19:56:10 +02:00
leo 46901d2c80 set include_fluent default to true (#512) 2017-06-08 12:19:59 +02:00
Max Matiukhin 25b5576f57 generate methods for the SoftDeletes trait (#518) 2017-06-08 12:19:38 +02:00
Michael Tsang d6d99994c3 return eloquent builder instead of plain database builder from model methods (#521) 2017-06-08 12:19:27 +02:00
Barry vd. Heuvel 7e78d02d0a Update .travis.yml 2017-06-06 16:29:23 +02:00
Victor Isadov 35d954fc39 Note for \Eloquent (#515)
https://github.com/barryvdh/laravel-ide-helper/issues/514
2017-06-06 16:18:54 +02:00
Jez McKean 5eeda63958 replaced curly quotes and other minor tweaks (#510) 2017-05-29 19:44:30 +02:00
Matthew Erwin b76156b24c Adds support for macros (#500)
* Adds support for macros

* Fixes formatting
2017-05-05 11:22:12 +02:00
Emir Beganović 2a63d51496 Add PHP 7.1 to build script (#492) 2017-04-14 17:57:13 +02:00
Neil Farrington 3814fe86ca Resolve displaying @return types with descriptions (#491) 2017-04-14 08:56:19 +02:00
JC Lee 3ab73555d9 Add support for pgsql for boolean types. (#489) 2017-04-11 07:31:58 +02:00
Antoine Aflalo ff3844e4e1 Implements Nullable (#487)
* Add nullable support

Fixes #407

* Add nullable to setProperty

Better do it like this to still be able to override the base type if wanted

* Cleanup nullableColumns between models iterations

Also rename it to nullableColumns since it contains multiple columns

* Fix formatting
2017-04-08 10:19:23 +02:00
JC Lee d11bf58084 Fix #480 where tinyint is casts as bool (#481)
* Fix #480 where tinyint is casts as bool

`tinyint` is classified by bool as doctrine/dbal, but it should not be so in our use case. `tinyint` is better PHPDoc'ed as int. If the user wants bool, he should use Eloquent's `$casts` property to do that.

* Pass PSR-2 check

* Remove comment as requested
2017-04-05 09:45:19 +02:00
theMadness 75e1f22ec6 Decoupled from main app View Factory (#475) 2017-03-31 11:14:28 +02:00
Ivan Boldyrev 144a50e8ee Add disable write magic methods on models (#466)
* Add desable write magic methods on models

* Fix property name

* Opps commit

* Fix

* Change default parameter of property
2017-03-16 11:46:50 +01:00
Florian Lefèvre b611cb5eff Add namespaced aliases (#456)
* Add namespaced aliases

* Move aliases regouping logic in Generator

* Fix getValidAliases return type
2017-03-05 20:04:42 +01:00
19 changed files with 938 additions and 231 deletions
+5 -9
View File
@@ -1,10 +1,9 @@
language: php language: php
php: php:
- 5.5
- 5.6
- 7.0 - 7.0
- hhvm - 7.1
- 7.2
# This triggers builds to run on the new TravisCI infrastructure. # This triggers builds to run on the new TravisCI infrastructure.
# See: http://docs.travis-ci.com/user/workers/container-based-infrastructure/ # See: http://docs.travis-ci.com/user/workers/container-based-infrastructure/
@@ -17,15 +16,12 @@ cache:
matrix: matrix:
include: include:
- php: 5.5 - php: 7.0
env: 'COMPOSER_FLAGS="--prefer-stable --prefer-lowest"' env: 'COMPOSER_FLAGS="--prefer-stable --prefer-lowest"'
before_script: before_script:
- travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-dist - travis_wait 20 travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-dist
script: script:
- vendor/bin/phpcs --standard=psr2 src/ - vendor/bin/phpcs --standard=psr2 src/
- vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover - vendor/bin/phpunit
after_script:
- if [[ $TRAVIS_PHP_VERSION != 'hhvm' && $TRAVIS_PHP_VERSION != '7.0' ]]; then php vendor/bin/ocular code-coverage:upload --format=php-clover coverage.clover; fi
+1 -1
View File
@@ -1,6 +1,6 @@
# The MIT License (MIT) # The MIT License (MIT)
Copyright (c) 2016 Barry vd. Heuvel <barryvdh@gmail.com> Copyright (c) Barry vd. Heuvel <barryvdh@gmail.com>
> Permission is hereby granted, free of charge, to any person obtaining a copy > Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal > of this software and associated documentation files (the "Software"), to deal
+22 -16
View File
@@ -10,21 +10,21 @@
} }
], ],
"require": { "require": {
"php": ">=5.4.0", "php": ">=7",
"illuminate/support": "^5.0,<5.5", "illuminate/support": "^5.5|^6",
"illuminate/console": "^5.0,<5.5", "illuminate/console": "^5.5|^6",
"illuminate/filesystem": "^5.0,<5.5", "illuminate/filesystem": "^5.5|^6",
"barryvdh/reflection-docblock": "^2.0.4", "barryvdh/reflection-docblock": "^2.0.6",
"symfony/class-loader": "^2.3|^3.0" "composer/composer": "^1.6",
},
"require-dev": {
"phpunit/phpunit" : "4.*",
"scrutinizer/ocular": "~1.1",
"squizlabs/php_codesniffer": "~2.3",
"doctrine/dbal": "~2.3" "doctrine/dbal": "~2.3"
}, },
"suggest": { "require-dev": {
"doctrine/dbal": "Load information from the database about models for phpdocs (~2.3)" "illuminate/config": "^5.5|^6",
"illuminate/view": "^5.5|^6",
"phpro/grumphp": "^0.14",
"phpunit/phpunit" : "4.*",
"scrutinizer/ocular": "~1.1",
"squizlabs/php_codesniffer": "^3"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
@@ -33,16 +33,22 @@
}, },
"autoload-dev": { "autoload-dev": {
"psr-4": { "psr-4": {
":vendor\\:package_name\\": "tests" "Barryvdh\\LaravelIdeHelper\\": "tests"
} }
}, },
"scripts": { "scripts": {
"test": "phpunit", "test": "phpunit",
"cs": "phpcs --standard=psr2 src/" "check-style": "phpcs -p --standard=PSR2 src/",
"fix-style": "phpcbf -p --standard=PSR2 src/"
}, },
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "2.3-dev" "dev-master": "2.6-dev"
},
"laravel": {
"providers": [
"Barryvdh\\LaravelIdeHelper\\IdeHelperServiceProvider"
]
} }
} }
} }
+47 -18
View File
@@ -14,6 +14,8 @@ return array(
'filename' => '_ide_helper', 'filename' => '_ide_helper',
'format' => 'php', 'format' => 'php',
'meta_filename' => '.phpstorm.meta.php',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Fluent helpers | Fluent helpers
@@ -25,6 +27,32 @@ return array(
'include_fluent' => false, 'include_fluent' => false,
/*
|--------------------------------------------------------------------------
| Write Model Magic methods
|--------------------------------------------------------------------------
|
| Set to false to disable write magic methods of model
|
*/
'write_model_magic_where' => true,
/*
|--------------------------------------------------------------------------
| Write Eloquent Model Mixins
|--------------------------------------------------------------------------
|
| This will add the necessary DocBlock mixins to the model class
| contained in the Laravel Framework. This helps the IDE with
| auto-completion.
|
| Please be aware that this setting changes a file within the /vendor directory.
|
*/
'write_eloquent_model_mixins' => false,
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Helper files to include | Helper files to include
@@ -70,18 +98,7 @@ return array(
'Session' => array('Illuminate\Session\Store'), 'Session' => array('Illuminate\Session\Store'),
), ),
'magic' => array( 'magic' => array(),
'Log' => array(
'debug' => 'Monolog\Logger::addDebug',
'info' => 'Monolog\Logger::addInfo',
'notice' => 'Monolog\Logger::addNotice',
'warning' => 'Monolog\Logger::addWarning',
'error' => 'Monolog\Logger::addError',
'critical' => 'Monolog\Logger::addCritical',
'alert' => 'Monolog\Logger::addAlert',
'emergency' => 'Monolog\Logger::addEmergency',
)
),
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@@ -140,13 +157,13 @@ return array(
| |
| For example, normally you would see this: | For example, normally you would see this:
| |
| * @property \Carbon\Carbon $created_at | * @property \Illuminate\Support\Carbon $created_at
| * @property \Carbon\Carbon $updated_at | * @property \Illuminate\Support\Carbon $updated_at
| |
| With this enabled, the properties will be this: | With this enabled, the properties will be this:
| |
| * @property \Carbon\Carbon $createdAt | * @property \Illuminate\Support\Carbon $createdAt
| * @property \Carbon\Carbon $updatedAt | * @property \Illuminate\Support\Carbon $updatedAt
| |
| Note, it is currently an all-or-nothing option. | Note, it is currently an all-or-nothing option.
| |
@@ -161,8 +178,20 @@ return array(
| Cast the given "real type" to the given "type". | Cast the given "real type" to the given "type".
| |
*/ */
'type_overrides' => array( 'type_overrides' => array(
'integer' => 'int', 'integer' => 'int',
'boolean' => 'bool', 'boolean' => 'bool',
), ),
/*
|--------------------------------------------------------------------------
| Include DocBlocks from classes
|--------------------------------------------------------------------------
|
| Include DocBlocks from classes to allow additional code inspection for
| magic methods and properties.
|
*/
'include_class_docblocks' => false,
); );
+15
View File
@@ -0,0 +1,15 @@
parameters:
git_dir: .
bin_dir: vendor/bin
tasks:
phpunit:
config_file: ~
testsuite: ~
group: []
always_execute: false
phpcs:
standard: PSR2
warning_severity: ~
ignore_patterns:
- tests/
triggered_by: [php]
+1 -8
View File
@@ -10,7 +10,7 @@
processIsolation="false" processIsolation="false"
stopOnFailure="false"> stopOnFailure="false">
<testsuites> <testsuites>
<testsuite name=":vendor Test Suite"> <testsuite name="Unit Tests">
<directory>tests</directory> <directory>tests</directory>
</testsuite> </testsuite>
</testsuites> </testsuites>
@@ -19,11 +19,4 @@
<directory suffix=".php">src/</directory> <directory suffix=".php">src/</directory>
</whitelist> </whitelist>
</filter> </filter>
<logging>
<log type="tap" target="build/report.tap"/>
<log type="junit" target="build/report.junit.xml"/>
<log type="coverage-html" target="build/coverage" charset="UTF-8" yui="true" highlight="true"/>
<log type="coverage-text" target="build/coverage.txt"/>
<log type="coverage-clover" target="build/logs/clover.xml"/>
</logging>
</phpunit> </phpunit>
+20 -20
View File
@@ -1,4 +1,4 @@
## Laravel 5 IDE Helper Generator ## Laravel IDE Helper Generator
[![Latest Version on Packagist][ico-version]][link-packagist] [![Latest Version on Packagist][ico-version]][link-packagist]
[![Software License][ico-license]](LICENSE.md) [![Software License][ico-license]](LICENSE.md)
@@ -22,14 +22,14 @@ If you don't want to generate it, you can add a pre-generated file to the root f
* Generated version for Lumen: https://gist.github.com/barryvdh/be17164b0ad51f832f20 * Generated version for Lumen: https://gist.github.com/barryvdh/be17164b0ad51f832f20
* Generated Phpstorm Meta file: https://gist.github.com/barryvdh/bb6ffc5d11e0a75dba67 * Generated Phpstorm Meta file: https://gist.github.com/barryvdh/bb6ffc5d11e0a75dba67
Note: You do need CodeIntel for Sublime Text: https://github.com/SublimeCodeIntel/SublimeCodeIntel Note: You do need CodeComplice for Sublime Text: https://github.com/spectacles/CodeComplice
### Install ### Install
Require this package with composer using the following command: Require this package with composer using the following command:
```bash ```bash
composer require barryvdh/laravel-ide-helper composer require --dev barryvdh/laravel-ide-helper
``` ```
After updating composer, add the service provider to the `providers` array in `config/app.php` After updating composer, add the service provider to the `providers` array in `config/app.php`
@@ -37,12 +37,7 @@ After updating composer, add the service provider to the `providers` array in `c
```php ```php
Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class, Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class,
``` ```
**Laravel 5.5** uses Package Auto-Discovery, so doesn't require you to manually add the ServiceProvider.
To install this package on only development systems, add the `--dev` flag to your composer command:
```bash
composer require --dev barryvdh/laravel-ide-helper
```
In Laravel, instead of adding the service provider in the `config/app.php` file, you can add the following code to your `app/Providers/AppServiceProvider.php` file, within the `register()` method: In Laravel, instead of adding the service provider in the `config/app.php` file, you can add the following code to your `app/Providers/AppServiceProvider.php` file, within the `register()` method:
@@ -66,7 +61,7 @@ You can now re-generate the docs yourself (for future updates)
php artisan ide-helper:generate php artisan ide-helper:generate
``` ```
Note: `bootstrap/compiled.php` has to be cleared first, so run `php artisan clear-compiled` before generating (and `php artisan optimize` after). Note: `bootstrap/compiled.php` has to be cleared first, so run `php artisan clear-compiled` before generating.
You can configure your composer.json to do this after each commit: You can configure your composer.json to do this after each commit:
@@ -75,8 +70,7 @@ You can configure your composer.json to do this after each commit:
"post-update-cmd": [ "post-update-cmd": [
"Illuminate\\Foundation\\ComposerScripts::postUpdate", "Illuminate\\Foundation\\ComposerScripts::postUpdate",
"php artisan ide-helper:generate", "php artisan ide-helper:generate",
"php artisan ide-helper:meta", "php artisan ide-helper:meta"
"php artisan optimize"
] ]
}, },
``` ```
@@ -90,18 +84,18 @@ php artisan vendor:publish --provider="Barryvdh\LaravelIdeHelper\IdeHelperServic
The generator tries to identify the real class, but if it cannot be found, you can define it in the config file. The generator tries to identify the real class, but if it cannot be found, you can define it in the config file.
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.
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.
### Automatic phpDocs for models ### Automatic phpDocs for models
> You need to require `doctrine/dbal: ~2.3` in your own composer.json to get database columns. > You need to add `doctrine/dbal: ~2.3` to require-dev in your own composer.json to get database columns.
```bash ```bash
composer require doctrine/dbal composer require --dev doctrine/dbal
``` ```
If you don't want to write your properties yourself, you can use the command `php artisan ide-helper:models` to generate If you don't want to write your properties yourself, you can use the command `php artisan ide-helper:models` to generate
@@ -122,8 +116,8 @@ php artisan ide-helper:models Post
* @property integer $author_id * @property integer $author_id
* @property string $title * @property string $title
* @property string $text * @property string $text
* @property \Carbon\Carbon $created_at * @property \Illuminate\Support\Carbon $created_at
* @property \Carbon\Carbon $updated_at * @property \Illuminate\Support\Carbon $updated_at
* @property-read \User $author * @property-read \User $author
* @property-read \Illuminate\Database\Eloquent\Collection|\Comment[] $comments * @property-read \Illuminate\Database\Eloquent\Collection|\Comment[] $comments
*/ */
@@ -149,18 +143,24 @@ Models can be ignored using the `--ignore (-I)` option
php artisan ide-helper:models --ignore="Post,User" php artisan ide-helper:models --ignore="Post,User"
``` ```
Note: With namespaces, wrap your model name in " signs: `php artisan ide-helper:models "API\User"`, or escape the slashes (`Api\\User`) Note: With namespaces, wrap your model name in double-quotes (`"`): `php artisan ide-helper:models "API\User"`, or escape the slashes (`Api\\User`)
For properly recognition of `Model` methods (i.e. `paginate`, `findOrFail`) you should extend `\Eloquent` or add
```php
/** @mixin \Eloquent */
```
for your model class.
### Automatic phpDocs generation for Laravel Fluent methods ### Automatic phpDocs generation for Laravel Fluent methods
If you need phpDocs support for Fluent methods in migration, for example If you need phpDocs support for Fluent methods in migration, for example
```php ```php
$table->string(“somestring”)->nullable()->index(); $table->string("somestring")->nullable()->index();
``` ```
After publishing vendor, simply change the `include_fluent` line your `config/ide-helper.php` file into: After publishing vendor, simply change the `include_fluent` line your `config/ide-helper.php` file into:
```php ```php
'include_fluent' => true, 'include_fluent' => true,
``` ```
And then run `php artisan ide-helper:generate` , you will now see all of the Fluent methods are recognized by your IDE now. And then run `php artisan ide-helper:generate` , you will now see all of the Fluent methods are recognized by your IDE.
## PhpStorm Meta for Container instances ## PhpStorm Meta for Container instances
+44 -26
View File
@@ -1,67 +1,84 @@
<?= '<?php' ?> <?= '<?php' ?>
<?php
/**
* @var \Barryvdh\LaravelIdeHelper\Alias[][] $namespaces_by_alias_ns
* @var \Barryvdh\LaravelIdeHelper\Alias[][] $namespaces_by_extends_ns
* @var bool $include_fluent
* @var string $helpers
*/
?>
// @formatter:off
/** /**
* A helper file for Laravel 5, to provide autocomplete information to your IDE * A helper file for Laravel 5, to provide autocomplete information to your IDE
* Generated for Laravel <?= $version ?> on <?= date("Y-m-d") ?>. * Generated for Laravel <?= $version ?> on <?= date("Y-m-d H:i:s") ?>.
*
* This file should not be included in your code, only analyzed by your IDE!
* *
* @author Barry vd. Heuvel <[email protected]> * @author Barry vd. Heuvel <[email protected]>
* @see https://github.com/barryvdh/laravel-ide-helper * @see https://github.com/barryvdh/laravel-ide-helper
*/ */
namespace {
exit("This file should not be included, only analyzed by your IDE");
}
<?php foreach($namespaces as $namespace => $aliases): ?> <?php foreach($namespaces_by_extends_ns as $namespace => $aliases): ?>
<?php if ($namespace == '\Illuminate\Database\Eloquent'): continue; endif; ?> <?php if ($namespace == '\Illuminate\Database\Eloquent'): continue; endif; ?>
namespace <?= $namespace == '__root' ? '' : trim($namespace, '\\') ?> { namespace <?= $namespace == '__root' ? '' : trim($namespace, '\\') ?> {
<?php foreach($aliases as $alias): ?> <?php foreach($aliases as $alias): ?>
<?= trim($alias->getDocComment(' ')) ?>
<?= $alias->getClassType() ?> <?= $alias->getExtendsClass() ?> { <?= $alias->getClassType() ?> <?= $alias->getExtendsClass() ?> {
<?php foreach($alias->getMethods() as $method): ?> <?php foreach($alias->getMethods() as $method): ?>
<?= trim($method->getDocComment(' ')) ?> <?= trim($method->getDocComment(' ')) ?>
public static function <?= $method->getName() ?>(<?= $method->getParamsWithDefault() ?>) public static function <?= $method->getName() ?>(<?= $method->getParamsWithDefault() ?>)
{<?php if($method->getDeclaringClass() !== $method->getRoot()): ?> {<?php if($method->getDeclaringClass() !== $method->getRoot()): ?>
//Method inherited from <?= $method->getDeclaringClass() ?> //Method inherited from <?= $method->getDeclaringClass() ?>
<?php endif; ?> <?php endif; ?>
<?= $method->shouldReturn() ? 'return ': '' ?><?= $method->getRoot() ?>::<?= $method->getName() ?>(<?= $method->getParams() ?>); <?php if($method->isInstanceCall()):?>
/** @var <?=$method->getRoot()?> $instance */
<?php endif?>
<?= $method->shouldReturn() ? 'return ': '' ?><?= $method->getRootMethodCall() ?>;
} }
<?php endforeach; ?> <?php endforeach; ?>
} }
<?php endforeach; ?> <?php endforeach; ?>
} }
<?php endforeach; ?> <?php endforeach; ?>
namespace { <?php foreach($namespaces_by_alias_ns as $namespace => $aliases): ?>
<?= $helpers ?> namespace <?= $namespace == '__root' ? '' : trim($namespace, '\\') ?> {
<?php foreach($namespaces as $namespace => $aliases): ?>
<?php foreach($aliases as $alias): ?> <?php foreach($aliases as $alias): ?>
<?= $alias->getClassType() ?> <?= $alias->getShortName() ?> extends <?= $alias->getExtends() ?> {<?php if ($namespace == '\Illuminate\Database\Eloquent'): ?>
<?php foreach($alias->getMethods() as $method): ?>
<?= trim($method->getDocComment(' ')) ?> <?= $alias->getClassType() ?> <?= $alias->getShortName() ?> extends <?= $alias->getExtends() ?> {<?php if ($alias->getExtendsNamespace() == '\Illuminate\Database\Eloquent'): ?>
<?php foreach($alias->getMethods() as $method): ?>
<?= trim($method->getDocComment(' ')) ?>
public static function <?= $method->getName() ?>(<?= $method->getParamsWithDefault() ?>)
{<?php if($method->getDeclaringClass() !== $method->getRoot()): ?>
public static function <?= $method->getName() ?>(<?= $method->getParamsWithDefault() ?>) //Method inherited from <?= $method->getDeclaringClass() ?>
{<?php if($method->getDeclaringClass() !== $method->getRoot()): ?> <?php endif; ?>
//Method inherited from <?= $method->getDeclaringClass() ?> <?php if($method->isInstanceCall()):?>
<?php endif; ?> /** @var <?=$method->getRoot()?> $instance */
<?php endif?>
<?= $method->shouldReturn() ? 'return ': '' ?><?= $method->getRoot() ?>::<?= $method->getName() ?>(<?= $method->getParams() ?>); <?= $method->shouldReturn() ? 'return ': '' ?><?= $method->getRootMethodCall() ?>;
} }
<?php endforeach; ?> <?php endforeach; ?>
<?php endif; ?>} <?php endif; ?>}
<?php endforeach; ?>
<?php endforeach; ?> <?php endforeach; ?>
} }
<?php endforeach; ?>
<?php if($helpers): ?>
namespace {
<?= $helpers ?>
}
<?php endif; ?>
<?php if($include_fluent): ?> <?php if($include_fluent): ?>
namespace Illuminate\Support { namespace Illuminate\Support {
/** /**
@@ -71,7 +88,7 @@ namespace Illuminate\Support {
* @method Fluent charset(string $charset) Add the character set modifier * @method Fluent charset(string $charset) Add the character set modifier
* @method Fluent collation(string $collation) Add the collation modifier * @method Fluent collation(string $collation) Add the collation modifier
* @method Fluent comment(string $comment) Add comment * @method Fluent comment(string $comment) Add comment
* @method Fluent default(mixed $value) Add the default modifier * @method Fluent default($value) Add the default modifier
* @method Fluent first() Select first row * @method Fluent first() Select first row
* @method Fluent index(string $name = null) Add the in dex clause * @method Fluent index(string $name = null) Add the in dex clause
* @method Fluent on(string $table) `on` of a foreign key * @method Fluent on(string $table) `on` of a foreign key
@@ -79,10 +96,11 @@ namespace Illuminate\Support {
* @method Fluent onUpdate(string $action) `on update` of a foreign key * @method Fluent onUpdate(string $action) `on update` of a foreign key
* @method Fluent primary() Add the primary key modifier * @method Fluent primary() Add the primary key modifier
* @method Fluent references(string $column) `references` of a foreign key * @method Fluent references(string $column) `references` of a foreign key
* @method Fluent nullable() Add the nullable modifier * @method Fluent nullable(bool $value = true) Add the nullable modifier
* @method Fluent unique(string $name = null) Add unique index clause * @method Fluent unique(string $name = null) Add unique index clause
* @method Fluent unsigned() Add the unsigned modifier * @method Fluent unsigned() Add the unsigned modifier
* @method Fluent useCurrent() Add the default timestamp value * @method Fluent useCurrent() Add the default timestamp value
* @method Fluent change() Add the change modifier
*/ */
class Fluent {} class Fluent {}
} }
+41 -9
View File
@@ -1,21 +1,53 @@
<?= '<?php' ?> <?= '<?php' ?>
// @formatter:off
namespace PHPSTORM_META { namespace PHPSTORM_META {
/** /**
* PhpStorm Meta file, to provide autocomplete information for PhpStorm * PhpStorm Meta file, to provide autocomplete information for PhpStorm
* Generated on <?= date("Y-m-d") ?>. * Generated on <?= date("Y-m-d H:i:s") ?>.
* *
* @author Barry vd. Heuvel <[email protected]> * @author Barry vd. Heuvel <[email protected]>
* @see https://github.com/barryvdh/laravel-ide-helper * @see https://github.com/barryvdh/laravel-ide-helper
*/ */
$STATIC_METHOD_TYPES = [ <?php foreach ($methods as $method): ?>
<?php foreach($methods as $method): ?> override(<?= $method ?>, map([
<?= $method ?> => [ '' => '@',
'' == '@',
<?php foreach($bindings as $abstract => $class): ?> <?php foreach($bindings as $abstract => $class): ?>
'<?= $abstract ?>' instanceof \<?= $class ?>, '<?= $abstract ?>' => \<?= $class ?>::class,
<?php endforeach ?> ], <?php endforeach; ?>
<?php endforeach ?> ]));
]; <?php endforeach; ?>
override(\Illuminate\Support\Arr::add(0), type(0));
override(\Illuminate\Support\Arr::except(0), type(0));
override(\Illuminate\Support\Arr::first(0), elementType(0));
override(\Illuminate\Support\Arr::last(0), elementType(0));
override(\Illuminate\Support\Arr::get(0), elementType(0));
override(\Illuminate\Support\Arr::only(0), type(0));
override(\Illuminate\Support\Arr::prepend(0), type(0));
override(\Illuminate\Support\Arr::pull(0), elementType(0));
override(\Illuminate\Support\Arr::set(0), type(0));
override(\Illuminate\Support\Arr::shuffle(0), type(0));
override(\Illuminate\Support\Arr::sort(0), type(0));
override(\Illuminate\Support\Arr::sortRecursive(0), type(0));
override(\Illuminate\Support\Arr::where(0), type(0));
override(\array_add(0), type(0));
override(\array_except(0), type(0));
override(\array_first(0), elementType(0));
override(\array_last(0), elementType(0));
override(\array_get(0), elementType(0));
override(\array_only(0), type(0));
override(\array_prepend(0), type(0));
override(\array_pull(0), elementType(0));
override(\array_set(0), type(0));
override(\array_sort(0), type(0));
override(\array_sort_recursive(0), type(0));
override(\array_where(0), type(0));
override(\head(0), elementType(0));
override(\last(0), elementType(0));
override(\with(0), type(0));
override(\tap(0), type(0));
} }
+143 -8
View File
@@ -10,6 +10,14 @@
namespace Barryvdh\LaravelIdeHelper; namespace Barryvdh\LaravelIdeHelper;
use Closure;
use ReflectionClass;
use Barryvdh\Reflection\DocBlock;
use Barryvdh\Reflection\DocBlock\Context;
use Barryvdh\Reflection\DocBlock\Tag\MethodTag;
use Illuminate\Config\Repository as ConfigRepository;
use Barryvdh\Reflection\DocBlock\Serializer as DocBlockSerializer;
class Alias class Alias
{ {
protected $alias; protected $alias;
@@ -27,18 +35,24 @@ class Alias
protected $valid = false; protected $valid = false;
protected $magicMethods = array(); protected $magicMethods = array();
protected $interfaces = array(); protected $interfaces = array();
protected $phpdoc = null;
/** @var ConfigRepository */
protected $config;
/** /**
* @param string $alias * @param ConfigRepository $config
* @param string $facade * @param string $alias
* @param array $magicMethods * @param string $facade
* @param array $interfaces * @param array $magicMethods
* @param array $interfaces
*/ */
public function __construct($alias, $facade, $magicMethods = array(), $interfaces = array()) public function __construct($config, $alias, $facade, $magicMethods = array(), $interfaces = array())
{ {
$this->alias = $alias; $this->alias = $alias;
$this->magicMethods = $magicMethods; $this->magicMethods = $magicMethods;
$this->interfaces = $interfaces; $this->interfaces = $interfaces;
$this->config = $config;
// Make the class absolute // Make the class absolute
$facade = '\\' . ltrim($facade, '\\'); $facade = '\\' . ltrim($facade, '\\');
@@ -53,10 +67,17 @@ class Alias
} }
$this->addClass($this->root); $this->addClass($this->root);
$this->detectFake();
$this->detectNamespace(); $this->detectNamespace();
$this->detectClassType(); $this->detectClassType();
$this->detectExtendsNamespace(); $this->detectExtendsNamespace();
if (!empty($this->namespace)) {
//Create a DocBlock and serializer instance
$this->phpdoc = new DocBlock(new ReflectionClass($alias), new Context($this->namespace));
}
if ($facade === '\Illuminate\Database\Eloquent\Model') { if ($facade === '\Illuminate\Database\Eloquent\Model') {
$this->usedMethods = array('decrement', 'increment'); $this->usedMethods = array('decrement', 'increment');
} }
@@ -158,15 +179,43 @@ class Alias
/** /**
* Get the methods found by this Alias * Get the methods found by this Alias
* *
* @return array * @return array|Method[]
*/ */
public function getMethods() public function getMethods()
{ {
if (count($this->methods) > 0) {
return $this->methods;
}
$this->addMagicMethods(); $this->addMagicMethods();
$this->detectMethods(); $this->detectMethods();
return $this->methods; return $this->methods;
} }
/**
* Detect class returned by ::fake()
*/
protected function detectFake()
{
$facade = $this->facade;
if (!method_exists($facade, 'fake')) {
return;
}
$real = $facade::getFacadeRoot();
try {
$facade::fake();
$fake = $facade::getFacadeRoot();
if ($fake !== $real) {
$this->addClass(get_class($fake));
}
} finally {
$facade::swap($real);
}
}
/** /**
* Detect the namespace * Detect the namespace
*/ */
@@ -267,13 +316,13 @@ class Alias
{ {
foreach ($this->magicMethods as $magic => $real) { foreach ($this->magicMethods as $magic => $real) {
list($className, $name) = explode('::', $real); list($className, $name) = explode('::', $real);
if (!class_exists($className) && !interface_exists($className)) { if ((!class_exists($className) && !interface_exists($className)) || !method_exists($className, $name)) {
continue; continue;
} }
$method = new \ReflectionMethod($className, $name); $method = new \ReflectionMethod($className, $name);
$class = new \ReflectionClass($className); $class = new \ReflectionClass($className);
if (!in_array($method->name, $this->usedMethods)) { if (!in_array($magic, $this->usedMethods)) {
if ($class !== $this->root) { if ($class !== $this->root) {
$this->methods[] = new Method($method, $this->alias, $class, $magic, $this->interfaces); $this->methods[] = new Method($method, $this->alias, $class, $magic, $this->interfaces);
} }
@@ -312,6 +361,92 @@ class Alias
} }
} }
} }
// Check if the class is macroable
$traits = collect($reflection->getTraitNames());
if ($traits->contains('Illuminate\Support\Traits\Macroable')) {
$properties = $reflection->getStaticProperties();
$macros = isset($properties['macros']) ? $properties['macros'] : [];
foreach ($macros as $macro_name => $macro_func) {
if (!in_array($macro_name, $this->usedMethods)) {
// Add macros
$this->methods[] = new Macro(
$this->getMacroFunction($macro_func),
$this->alias,
$reflection,
$macro_name,
$this->interfaces
);
$this->usedMethods[] = $macro_name;
}
}
}
}
}
/**
* @param $macro_func
*
* @return \ReflectionFunctionAbstract
* @throws \ReflectionException
*/
protected function getMacroFunction($macro_func)
{
if (is_array($macro_func) && is_callable($macro_func)) {
return new \ReflectionMethod($macro_func[0], $macro_func[1]);
}
if (is_object($macro_func) && is_callable($macro_func) && !$macro_func instanceof Closure) {
return new \ReflectionMethod($macro_func, '__invoke');
}
return new \ReflectionFunction($macro_func);
}
/*
* Get the docblock for this alias
*
* @param string $prefix
* @return mixed
*/
public function getDocComment($prefix = "\t\t")
{
$serializer = new DocBlockSerializer(1, $prefix);
if ($this->phpdoc) {
if ($this->config->get('ide-helper.include_class_docblocks')) {
// if a class doesn't expose any DocBlock tags
// we can perform reflection on the class and
// add in the original class DocBlock
if (count($this->phpdoc->getTags()) === 0) {
$class = new ReflectionClass($this->root);
$this->phpdoc = new DocBlock($class->getDocComment());
}
}
$this->removeDuplicateMethodsFromPhpDoc();
return $serializer->getDocComment($this->phpdoc);
}
return '';
}
/**
* Removes method tags from the doc comment that already appear as functions inside the class.
* This prevents duplicate function errors in the IDE.
*
* @return void
*/
protected function removeDuplicateMethodsFromPhpDoc()
{
$methodNames = array_map(function (Method $method) {
return $method->getName();
}, $this->getMethods());
foreach ($this->phpdoc->getTags() as $tag) {
if ($tag instanceof MethodTag && in_array($tag->getMethodName(), $methodNames)) {
$this->phpdoc->deleteTag($tag);
}
} }
} }
+61
View File
@@ -0,0 +1,61 @@
<?php
/**
* Laravel IDE Helper Generator - Eloquent Model Mixin
*
* @author Charles A. Peterson <[email protected]>
* @copyright 2017 Charles A. Peterson / Fruitcake Studio (http://www.fruitcakestudio.nl)
* @license http://www.opensource.org/licenses/mit-license.php MIT
* @link https://github.com/barryvdh/laravel-ide-helper
*/
namespace Barryvdh\LaravelIdeHelper\Console;
use Barryvdh\LaravelIdeHelper\Eloquent;
use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
/**
* A command to add \Eloquent mixin to Eloquent\Model
*
* @author Charles A. Peterson <[email protected]>
*/
class EloquentCommand extends Command
{
/**
* The console command name.
*
* @var string
*/
protected $name = 'ide-helper:eloquent';
/**
* @var Filesystem $files
*/
protected $files;
/**
* The console command description.
*
* @var string
*/
protected $description = 'Add \Eloquent helper to \Eloquent\Model';
/**
* @param Filesystem $files
*/
public function __construct(Filesystem $files)
{
parent::__construct();
$this->files = $files;
}
/**
* Execute the console command.
*
* @return void
*/
public function handle()
{
Eloquent::writeEloquentModelHelper($this, $this->files);
}
}
+8 -2
View File
@@ -10,8 +10,8 @@
namespace Barryvdh\LaravelIdeHelper\Console; namespace Barryvdh\LaravelIdeHelper\Console;
use Barryvdh\LaravelIdeHelper\Eloquent;
use Barryvdh\LaravelIdeHelper\Generator; use Barryvdh\LaravelIdeHelper\Generator;
use Illuminate\Config\Repository as ConfigRepository;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem; use Illuminate\Filesystem\Filesystem;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
@@ -74,7 +74,7 @@ class GeneratorCommand extends Command
* *
* @return void * @return void
*/ */
public function fire() public function handle()
{ {
if (file_exists(base_path() . '/vendor/compiled.php') || if (file_exists(base_path() . '/vendor/compiled.php') ||
file_exists(base_path() . '/bootstrap/cache/compiled.php') || file_exists(base_path() . '/bootstrap/cache/compiled.php') ||
@@ -115,6 +115,10 @@ class GeneratorCommand extends Command
if ($written !== false) { if ($written !== false) {
$this->info("A new helper file was written to $filename"); $this->info("A new helper file was written to $filename");
if ($this->option('write_mixins')) {
Eloquent::writeEloquentModelHelper($this, $this->files);
}
} else { } else {
$this->error("The helper file could not be created at $filename"); $this->error("The helper file could not be created at $filename");
} }
@@ -158,9 +162,11 @@ class GeneratorCommand extends Command
protected function getOptions() protected function getOptions()
{ {
$format = $this->config->get('ide-helper.format'); $format = $this->config->get('ide-helper.format');
$writeMixins = $this->config->get('ide-helper.write_eloquent_model_mixins');
return array( return array(
array('format', "F", InputOption::VALUE_OPTIONAL, 'The format for the IDE Helper', $format), array('format', "F", InputOption::VALUE_OPTIONAL, 'The format for the IDE Helper', $format),
array('write_mixins', "W", InputOption::VALUE_OPTIONAL, 'Write mixins to Laravel Model?', $writeMixins),
array('helpers', "H", InputOption::VALUE_NONE, 'Include the helper files'), array('helpers', "H", InputOption::VALUE_NONE, 'Include the helper files'),
array('memory', "M", InputOption::VALUE_NONE, 'Use sqlite memory driver'), array('memory', "M", InputOption::VALUE_NONE, 'Use sqlite memory driver'),
array('sublime', "S", InputOption::VALUE_NONE, 'DEPRECATED: Use different style for SublimeText CodeIntel'), array('sublime', "S", InputOption::VALUE_NONE, 'DEPRECATED: Use different style for SublimeText CodeIntel'),
+27 -12
View File
@@ -28,7 +28,6 @@ class MetaCommand extends Command
* @var string * @var string
*/ */
protected $name = 'ide-helper:meta'; protected $name = 'ide-helper:meta';
protected $filename = '.phpstorm.meta.php';
/** /**
* The console command description. * The console command description.
@@ -43,22 +42,31 @@ class MetaCommand extends Command
/** @var \Illuminate\Contracts\View\Factory */ /** @var \Illuminate\Contracts\View\Factory */
protected $view; protected $view;
/** @var \Illuminate\Contracts\Config */
protected $config;
protected $methods = [ protected $methods = [
'new \Illuminate\Contracts\Container\Container', 'new \Illuminate\Contracts\Container\Container',
'\Illuminate\Contracts\Container\Container::make(\'\')', '\Illuminate\Container\Container::makeWith(0)',
'\App::make(\'\')', '\Illuminate\Contracts\Container\Container::make(0)',
'\app(\'\')', '\Illuminate\Contracts\Container\Container::makeWith(0)',
'\App::make(0)',
'\App::makeWith(0)',
'\app(0)',
'\resolve(0)',
]; ];
/** /**
* *
* @param \Illuminate\Contracts\Filesystem\Filesystem $files * @param \Illuminate\Contracts\Filesystem\Filesystem $files
* @param \Illuminate\Contracts\View\Factory $view * @param \Illuminate\Contracts\View\Factory $view
* @param \Illuminate\Contracts\Config $config
*/ */
public function __construct($files, $view) public function __construct($files, $view, $config)
{ {
$this->files = $files; $this->files = $files;
$this->view = $view; $this->view = $view;
$this->config = $config;
parent::__construct(); parent::__construct();
} }
@@ -67,7 +75,7 @@ class MetaCommand extends Command
* *
* @return void * @return void
*/ */
public function fire() public function handle()
{ {
$this->registerClassAutoloadExceptions(); $this->registerClassAutoloadExceptions();
@@ -80,17 +88,18 @@ class MetaCommand extends Command
try { try {
$concrete = $this->laravel->make($abstract); $concrete = $this->laravel->make($abstract);
if (is_object($concrete)) { $reflectionClass = new \ReflectionClass($concrete);
if (is_object($concrete) && !$reflectionClass->isAnonymous()) {
$bindings[$abstract] = get_class($concrete); $bindings[$abstract] = get_class($concrete);
} }
} catch (\Exception $e) { } catch (\Throwable $e) {
if ($this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) { if ($this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
$this->comment("Cannot make '$abstract': ".$e->getMessage()); $this->comment("Cannot make '$abstract': ".$e->getMessage());
} }
} }
} }
$content = $this->view->make('ide-helper::meta', [ $content = $this->view->make('meta', [
'bindings' => $bindings, 'bindings' => $bindings,
'methods' => $this->methods, 'methods' => $this->methods,
])->render(); ])->render();
@@ -115,7 +124,11 @@ class MetaCommand extends Command
$abstracts = $this->laravel->getBindings(); $abstracts = $this->laravel->getBindings();
// Return the abstract names only // Return the abstract names only
return array_keys($abstracts); $keys = array_keys($abstracts);
sort($keys);
return $keys;
} }
/** /**
@@ -124,7 +137,7 @@ class MetaCommand extends Command
protected function registerClassAutoloadExceptions() protected function registerClassAutoloadExceptions()
{ {
spl_autoload_register(function ($class) { spl_autoload_register(function ($class) {
throw new \Exception("Class '$class' not found."); throw new \ReflectionException("Class '$class' not found.");
}); });
} }
@@ -135,8 +148,10 @@ class MetaCommand extends Command
*/ */
protected function getOptions() protected function getOptions()
{ {
$filename = $this->config->get('ide-helper.meta_filename');
return array( return array(
array('filename', 'F', InputOption::VALUE_OPTIONAL, 'The path to the meta file', $this->filename), array('filename', 'F', InputOption::VALUE_OPTIONAL, 'The path to the meta file', $filename),
); );
} }
} }
+176 -46
View File
@@ -10,14 +10,15 @@
namespace Barryvdh\LaravelIdeHelper\Console; namespace Barryvdh\LaravelIdeHelper\Console;
use Composer\Autoload\ClassMapGenerator;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Illuminate\Filesystem\Filesystem; use Illuminate\Filesystem\Filesystem;
use ReflectionClass;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\ClassLoader\ClassMapGenerator;
use Barryvdh\Reflection\DocBlock; use Barryvdh\Reflection\DocBlock;
use Barryvdh\Reflection\DocBlock\Context; use Barryvdh\Reflection\DocBlock\Context;
use Barryvdh\Reflection\DocBlock\Tag; use Barryvdh\Reflection\DocBlock\Tag;
@@ -50,11 +51,17 @@ class ModelsCommand extends Command
*/ */
protected $description = 'Generate autocompletion for models'; protected $description = 'Generate autocompletion for models';
protected $write_model_magic_where;
protected $properties = array(); protected $properties = array();
protected $methods = array(); protected $methods = array();
protected $write = false; protected $write = false;
protected $dirs = array(); protected $dirs = array();
protected $reset; protected $reset;
protected $keep_text;
/**
* @var bool[string]
*/
protected $nullableColumns = [];
/** /**
* @param Filesystem $files * @param Filesystem $files
@@ -70,7 +77,7 @@ class ModelsCommand extends Command
* *
* @return void * @return void
*/ */
public function fire() public function handle()
{ {
$filename = $this->option('filename'); $filename = $this->option('filename');
$this->write = $this->option('write'); $this->write = $this->option('write');
@@ -81,11 +88,15 @@ class ModelsCommand extends Command
$model = $this->argument('model'); $model = $this->argument('model');
$ignore = $this->option('ignore'); $ignore = $this->option('ignore');
$this->reset = $this->option('reset'); $this->reset = $this->option('reset');
if ($this->option('smart-reset')) {
$this->keep_text = $this->reset = true;
}
$this->write_model_magic_where = $this->laravel['config']->get('ide-helper.write_model_magic_where', true);
//If filename is default and Write is not specified, ask what to do //If filename is default and Write is not specified, ask what to do
if (!$this->write && $filename === $this->filename && !$this->option('nowrite')) { if (!$this->write && $filename === $this->filename && !$this->option('nowrite')) {
if ($this->confirm( if ($this->confirm(
"Do you want to overwrite the existing model files? Choose no to write to $filename instead? (Yes/No): " "Do you want to overwrite the existing model files? Choose no to write to $filename instead"
) )
) { ) {
$this->write = true; $this->write = true;
@@ -130,6 +141,7 @@ class ModelsCommand extends Command
array('write', 'W', InputOption::VALUE_NONE, 'Write to Model file'), array('write', 'W', InputOption::VALUE_NONE, 'Write to Model file'),
array('nowrite', 'N', InputOption::VALUE_NONE, 'Don\'t write to Model file'), array('nowrite', 'N', InputOption::VALUE_NONE, 'Don\'t write to Model file'),
array('reset', 'R', InputOption::VALUE_NONE, 'Remove the original phpdocs instead of appending'), array('reset', 'R', InputOption::VALUE_NONE, 'Remove the original phpdocs instead of appending'),
array('smart-reset', 'r', InputOption::VALUE_NONE, 'Refresh the properties/methods list, but keep the text'),
array('ignore', 'I', InputOption::VALUE_OPTIONAL, 'Which models to ignore', ''), array('ignore', 'I', InputOption::VALUE_OPTIONAL, 'Which models to ignore', ''),
); );
} }
@@ -139,6 +151,8 @@ class ModelsCommand extends Command
$output = "<?php $output = "<?php
// @formatter:off
/** /**
* A helper file for your Eloquent Models * A helper file for your Eloquent Models
* Copy the phpDocs from this file to the correct Model, * Copy the phpDocs from this file to the correct Model,
@@ -173,10 +187,9 @@ class ModelsCommand extends Command
if (class_exists($name)) { if (class_exists($name)) {
try { try {
// handle abstract classes, interfaces, ... // handle abstract classes, interfaces, ...
$reflectionClass = new \ReflectionClass($name); $reflectionClass = new ReflectionClass($name);
if (!$reflectionClass->isSubclassOf('Illuminate\Database\Eloquent\Model') if (!$reflectionClass->isSubclassOf('Illuminate\Database\Eloquent\Model')) {
|| $reflectionClass->isSubclassOf('Illuminate\Database\Eloquent\Relations\Pivot')) {
continue; continue;
} }
@@ -200,9 +213,11 @@ class ModelsCommand extends Command
} }
$this->getPropertiesFromMethods($model); $this->getPropertiesFromMethods($model);
$output .= $this->createPhpDocs($name); $this->getSoftDeleteMethods($model);
$ignore[] = $name; $output .= $this->createPhpDocs($name);
} catch (\Exception $e) { $ignore[] = $name;
$this->nullableColumns = [];
} catch (\Throwable $e) {
$this->error("Exception: " . $e->getMessage() . "\nCould not analyze class $name."); $this->error("Exception: " . $e->getMessage() . "\nCould not analyze class $name.");
} }
} }
@@ -269,13 +284,13 @@ class ModelsCommand extends Command
break; break;
case 'date': case 'date':
case 'datetime': case 'datetime':
$realType = '\Carbon\Carbon'; $realType = '\Illuminate\Support\Carbon';
break; break;
case 'collection': case 'collection':
$realType = '\Illuminate\Support\Collection'; $realType = '\Illuminate\Support\Collection';
break; break;
default: default:
$realType = 'mixed'; $realType = class_exists($type) ? ('\\' . $type) : 'mixed';
break; break;
} }
@@ -283,6 +298,10 @@ class ModelsCommand extends Command
continue; continue;
} else { } else {
$this->properties[$name]['type'] = $this->getTypeOverride($realType); $this->properties[$name]['type'] = $this->getTypeOverride($realType);
if (isset($this->nullableColumns[$name])) {
$this->properties[$name]['type'] .= '|null';
}
} }
} }
} }
@@ -329,7 +348,7 @@ class ModelsCommand extends Command
foreach ($columns as $column) { foreach ($columns as $column) {
$name = $column->getName(); $name = $column->getName();
if (in_array($name, $model->getDates())) { if (in_array($name, $model->getDates())) {
$type = '\Carbon\Carbon'; $type = '\Illuminate\Support\Carbon';
} else { } else {
$type = $column->getType()->getName(); $type = $column->getType()->getName();
switch ($type) { switch ($type) {
@@ -347,13 +366,21 @@ class ModelsCommand extends Command
case 'smallint': case 'smallint':
$type = 'integer'; $type = 'integer';
break; break;
case 'boolean':
switch (config('database.default')) {
case 'sqlite':
case 'mysql':
$type = 'integer';
break;
default:
$type = 'boolean';
break;
}
break;
case 'decimal': case 'decimal':
case 'float': case 'float':
$type = 'float'; $type = 'float';
break; break;
case 'boolean':
$type = 'boolean';
break;
default: default:
$type = 'mixed'; $type = 'mixed';
break; break;
@@ -361,12 +388,17 @@ class ModelsCommand extends Command
} }
$comment = $column->getComment(); $comment = $column->getComment();
$this->setProperty($name, $type, true, true, $comment); if (!$column->getNotnull()) {
$this->setMethod( $this->nullableColumns[$name] = true;
Str::camel("where_" . $name), }
'\Illuminate\Database\Query\Builder|\\' . get_class($model), $this->setProperty($name, $type, true, true, $comment, !$column->getNotnull());
array('$value') if ($this->write_model_magic_where) {
); $this->setMethod(
Str::camel("where_" . $name),
'\Illuminate\Database\Eloquent\Builder|\\' . get_class($model),
array('$value')
);
}
} }
} }
} }
@@ -410,13 +442,21 @@ class ModelsCommand extends Command
$args = $this->getParameters($reflection); $args = $this->getParameters($reflection);
//Remove the first ($query) argument //Remove the first ($query) argument
array_shift($args); array_shift($args);
$this->setMethod($name, '\Illuminate\Database\Query\Builder|\\' . $reflection->class, $args); $this->setMethod($name, '\Illuminate\Database\Eloquent\Builder|\\' . $reflection->class, $args);
} }
} elseif (in_array($method, ['query', 'newQuery', 'newModelQuery'])) {
$reflection = new \ReflectionClass($model);
$builder = get_class($model->newModelQuery());
$this->setMethod($method, "\\{$builder}|\\" . $reflection->getName());
} elseif (!method_exists('Illuminate\Database\Eloquent\Model', $method) } elseif (!method_exists('Illuminate\Database\Eloquent\Model', $method)
&& !Str::startsWith($method, 'get') && !Str::startsWith($method, 'get')
) { ) {
//Use reflection to inspect the code, based on Illuminate/Support/SerializableClosure.php //Use reflection to inspect the code, based on Illuminate/Support/SerializableClosure.php
$reflection = new \ReflectionMethod($model, $method); $reflection = new \ReflectionMethod($model, $method);
// php 7.x type or fallback to docblock
$type = (string) ($reflection->getReturnType() ?: $this->getReturnTypeFromDocBlock($reflection));
$file = new \SplFileObject($reflection->getFileName()); $file = new \SplFileObject($reflection->getFileName());
$file->seek($reflection->getStartLine() - 1); $file->seek($reflection->getStartLine() - 1);
@@ -431,26 +471,39 @@ class ModelsCommand extends Command
$code = substr($code, $begin, strrpos($code, '}') - $begin + 1); $code = substr($code, $begin, strrpos($code, '}') - $begin + 1);
foreach (array( foreach (array(
'hasMany', 'hasMany' => '\Illuminate\Database\Eloquent\Relations\HasMany',
'hasManyThrough', 'hasManyThrough' => '\Illuminate\Database\Eloquent\Relations\HasManyThrough',
'belongsToMany', 'belongsToMany' => '\Illuminate\Database\Eloquent\Relations\BelongsToMany',
'hasOne', 'hasOne' => '\Illuminate\Database\Eloquent\Relations\HasOne',
'belongsTo', 'belongsTo' => '\Illuminate\Database\Eloquent\Relations\BelongsTo',
'morphOne', 'morphOne' => '\Illuminate\Database\Eloquent\Relations\MorphOne',
'morphTo', 'morphTo' => '\Illuminate\Database\Eloquent\Relations\MorphTo',
'morphMany', 'morphMany' => '\Illuminate\Database\Eloquent\Relations\MorphMany',
'morphToMany' 'morphToMany' => '\Illuminate\Database\Eloquent\Relations\MorphToMany',
) as $relation) { 'morphedByMany' => '\Illuminate\Database\Eloquent\Relations\MorphToMany'
) as $relation => $impl) {
$search = '$this->' . $relation . '('; $search = '$this->' . $relation . '(';
if ($pos = stripos($code, $search)) { if (stripos($code, $search) || stripos($impl, (string)$type) !== false) {
//Resolve the relation's model to a Relation object. //Resolve the relation's model to a Relation object.
$methodReflection = new \ReflectionMethod($model, $method);
if ($methodReflection->getNumberOfParameters()) {
continue;
}
$relationObj = $model->$method(); $relationObj = $model->$method();
if ($relationObj instanceof Relation) { if ($relationObj instanceof Relation) {
$relatedModel = '\\' . get_class($relationObj->getRelated()); $relatedModel = '\\' . get_class($relationObj->getRelated());
$relations = ['hasManyThrough', 'belongsToMany', 'hasMany', 'morphMany', 'morphToMany']; $relations = [
if (in_array($relation, $relations)) { 'hasManyThrough',
'belongsToMany',
'hasMany',
'morphMany',
'morphToMany',
'morphedByMany',
];
if (strpos(get_class($relationObj), 'Many') !== false) {
//Collection or array of models (because Collection is Arrayable) //Collection or array of models (because Collection is Arrayable)
$this->setProperty( $this->setProperty(
$method, $method,
@@ -458,6 +511,12 @@ class ModelsCommand extends Command
true, true,
null null
); );
$this->setProperty(
Str::snake($method) . '_count',
'int|null',
true,
false
);
} elseif ($relation === "morphTo") { } elseif ($relation === "morphTo") {
// Model isn't specified because relation is polymorphic // Model isn't specified because relation is polymorphic
$this->setProperty( $this->setProperty(
@@ -468,7 +527,14 @@ class ModelsCommand extends Command
); );
} else { } else {
//Single model is returned //Single model is returned
$this->setProperty($method, $relatedModel, true, null); $this->setProperty(
$method,
$relatedModel,
true,
null,
'',
$this->isRelationForeignKeyNullable($relationObj)
);
} }
} }
} }
@@ -479,13 +545,33 @@ class ModelsCommand extends Command
} }
/** /**
* @param string $name * Check if the foreign key of the relation is nullable
* @param string|null $type *
* @param bool|null $read * @param Relation $relation
* @param bool|null $write *
* @param string|null $comment * @return bool
*/ */
protected function setProperty($name, $type = null, $read = null, $write = null, $comment = '') private function isRelationForeignKeyNullable(Relation $relation)
{
$reflectionObj = new \ReflectionObject($relation);
if (!$reflectionObj->hasProperty('foreignKey')) {
return false;
}
$fkProp = $reflectionObj->getProperty('foreignKey');
$fkProp->setAccessible(true);
return isset($this->nullableColumns[$fkProp->getValue($relation)]);
}
/**
* @param string $name
* @param string|null $type
* @param bool|null $read
* @param bool|null $write
* @param string|null $comment
* @param bool $nullable
*/
protected function setProperty($name, $type = null, $read = null, $write = null, $comment = '', $nullable = false)
{ {
if (!isset($this->properties[$name])) { if (!isset($this->properties[$name])) {
$this->properties[$name] = array(); $this->properties[$name] = array();
@@ -495,7 +581,11 @@ class ModelsCommand extends Command
$this->properties[$name]['comment'] = (string) $comment; $this->properties[$name]['comment'] = (string) $comment;
} }
if ($type !== null) { if ($type !== null) {
$this->properties[$name]['type'] = $this->getTypeOverride($type); $newType = $this->getTypeOverride($type);
if ($nullable) {
$newType .='|null';
}
$this->properties[$name]['type'] = $newType;
} }
if ($read !== null) { if ($read !== null) {
$this->properties[$name]['read'] = $read; $this->properties[$name]['read'] = $read;
@@ -523,13 +613,19 @@ class ModelsCommand extends Command
protected function createPhpDocs($class) protected function createPhpDocs($class)
{ {
$reflection = new \ReflectionClass($class); $reflection = new ReflectionClass($class);
$namespace = $reflection->getNamespaceName(); $namespace = $reflection->getNamespaceName();
$classname = $reflection->getShortName(); $classname = $reflection->getShortName();
$originalDoc = $reflection->getDocComment(); $originalDoc = $reflection->getDocComment();
$keyword = $this->getClassKeyword($reflection);
if ($this->reset) { if ($this->reset) {
$phpdoc = new DocBlock('', new Context($namespace)); $phpdoc = new DocBlock('', new Context($namespace));
if ($this->keep_text) {
$phpdoc->setText(
(new DocBlock($reflection, new Context($namespace)))->getText()
);
}
} else { } else {
$phpdoc = new DocBlock($reflection, new Context($namespace)); $phpdoc = new DocBlock($reflection, new Context($namespace));
} }
@@ -609,7 +705,7 @@ class ModelsCommand extends Command
} }
} }
$output = "namespace {$namespace}{\n{$docComment}\n\tclass {$classname} extends \Eloquent {}\n}\n\n"; $output = "namespace {$namespace}{\n{$docComment}\n\t{$keyword}class {$classname} extends \Eloquent {}\n}\n\n";
return $output; return $output;
} }
@@ -690,9 +786,43 @@ class ModelsCommand extends Command
$phpdoc = new DocBlock($reflection); $phpdoc = new DocBlock($reflection);
if ($phpdoc->hasTag('return')) { if ($phpdoc->hasTag('return')) {
$type = $phpdoc->getTagsByName('return')[0]->getContent(); $type = $phpdoc->getTagsByName('return')[0]->getType();
} }
return $type; return $type;
} }
/**
* Generates methods provided by the SoftDeletes trait
* @param \Illuminate\Database\Eloquent\Model $model
*/
protected function getSoftDeleteMethods($model)
{
$traits = class_uses(get_class($model), true);
if (in_array('Illuminate\\Database\\Eloquent\\SoftDeletes', $traits)) {
$this->setMethod('forceDelete', 'bool|null', []);
$this->setMethod('restore', 'bool|null', []);
$this->setMethod('withTrashed', '\Illuminate\Database\Query\Builder|\\' . get_class($model), []);
$this->setMethod('withoutTrashed', '\Illuminate\Database\Query\Builder|\\' . get_class($model), []);
$this->setMethod('onlyTrashed', '\Illuminate\Database\Query\Builder|\\' . get_class($model), []);
}
}
/**
* @param ReflectionClass $reflection
* @return string
*/
private function getClassKeyword(ReflectionClass $reflection)
{
if ($reflection->isFinal()) {
$keyword = 'final ';
} elseif ($reflection->isAbstract()) {
$keyword = 'abstract ';
} else {
$keyword = '';
}
return $keyword;
}
} }
+108
View File
@@ -0,0 +1,108 @@
<?php
/**
* Laravel IDE Helper to add \Eloquent mixin to Eloquent\Model
*
* @author Charles A. Peterson <artistan@gmail.com>
*/
namespace Barryvdh\LaravelIdeHelper;
use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
use Barryvdh\Reflection\DocBlock;
use Barryvdh\Reflection\DocBlock\Context;
use Barryvdh\Reflection\DocBlock\Serializer as DocBlockSerializer;
use Barryvdh\Reflection\DocBlock\Tag;
class Eloquent
{
/**
* Write mixin helper to the Eloquent\Model
* This is needed since laravel/framework v5.4.29
*
* @param Command $command
* @param Filesystem $files
*
* @return void
*/
public static function writeEloquentModelHelper(Command $command, Filesystem $files)
{
$class = 'Illuminate\Database\Eloquent\Model';
$reflection = new \ReflectionClass($class);
$namespace = $reflection->getNamespaceName();
$originalDoc = $reflection->getDocComment();
if (!$originalDoc) {
$command->info('Unexpected no document on ' . $class);
}
$phpdoc = new DocBlock($reflection, new Context($namespace));
$mixins = $phpdoc->getTagsByName('mixin');
$expectedMixins = [
'\Eloquent' => false,
'\Illuminate\Database\Eloquent\Builder' => false,
'\Illuminate\Database\Query\Builder' => false,
];
foreach ($mixins as $m) {
$mixin = $m->getContent();
if (isset($expectedMixins[$mixin])) {
$command->info('Tag Exists: @mixin ' . $mixin . ' in ' . $class);
$expectedMixins[$mixin] = true;
}
}
$changed = false;
foreach ($expectedMixins as $expectedMixin => $present) {
if ($present === false) {
$phpdoc->appendTag(Tag::createInstance('@mixin ' . $expectedMixin, $phpdoc));
$changed = true;
}
}
// If nothing's changed, stop here.
if (!$changed) {
return;
}
$serializer = new DocBlockSerializer();
$serializer->getDocComment($phpdoc);
$docComment = $serializer->getDocComment($phpdoc);
/*
The new DocBlock is appended to the beginning of the class declaration.
Since there is no DocBlock, the declaration is used as a guide.
*/
if (!$originalDoc) {
$originalDoc = 'abstract class Model implements';
$docComment .= "\nabstract class Model implements";
}
$filename = $reflection->getFileName();
if ($filename) {
$contents = $files->get($filename);
if ($contents) {
$count = 0;
$contents = str_replace($originalDoc, $docComment, $contents, $count);
if ($count > 0) {
if ($files->put($filename, $contents)) {
$command->info('Wrote expected docblock to ' . $filename);
} else {
$command->error('File write failed to ' . $filename);
}
} else {
$command->error('Content did not change ' . $contents);
}
} else {
$command->error('No file contents found ' . $filename);
}
} else {
$command->error('Filename not found ' . $class);
}
}
}
+47 -21
View File
@@ -12,7 +12,7 @@ namespace Barryvdh\LaravelIdeHelper;
use Illuminate\Foundation\Application; use Illuminate\Foundation\Application;
use Illuminate\Foundation\AliasLoader; use Illuminate\Foundation\AliasLoader;
use Illuminate\Config\Repository as ConfigRepository; use Illuminate\Support\Collection;
use ReflectionClass; use ReflectionClass;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
@@ -80,18 +80,19 @@ class Generator
public function generatePhpHelper() public function generatePhpHelper()
{ {
$app = app(); $app = app();
return $this->view->make('ide-helper::helper') return $this->view->make('helper')
->with('namespaces', $this->getNamespaces()) ->with('namespaces_by_extends_ns', $this->getAliasesByExtendsNamespace())
->with('namespaces_by_alias_ns', $this->getAliasesByAliasNamespace())
->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', false)) ->with('include_fluent', $this->config->get('ide-helper.include_fluent', true))
->render(); ->render();
} }
public function generateJsonHelper() public function generateJsonHelper()
{ {
$classes = array(); $classes = array();
foreach ($this->getNamespaces() as $aliases) { foreach ($this->getValidAliases() as $aliases) {
foreach ($aliases as $alias) { foreach ($aliases as $alias) {
$functions = array(); $functions = array();
foreach ($alias->getMethods() as $method) { foreach ($alias->getMethods() as $method) {
@@ -186,38 +187,58 @@ class Generator
} }
/** /**
* Find all namespaces/aliases that are valid for us to render * Find all aliases that are valid for us to render
* *
* @return array * @return Collection
*/ */
protected function getNamespaces() protected function getValidAliases()
{ {
$namespaces = array(); $aliases = new Collection();
// Get all aliases // Get all aliases
foreach ($this->getAliases() as $name => $facade) { foreach ($this->getAliases() as $name => $facade) {
// Skip the Redis facade, if not available (otherwise Fatal PHP Error) // Skip the Redis facade, if not available (otherwise Fatal PHP Error)
if ($facade == 'Illuminate\Support\Facades\Redis' && !class_exists('Predis\Client')) { if ($facade == 'Illuminate\Support\Facades\Redis' && $name == 'Redis' && !class_exists('Predis\Client')) {
continue; continue;
} }
$magicMethods = array_key_exists($name, $this->magic) ? $this->magic[$name] : array(); $magicMethods = array_key_exists($name, $this->magic) ? $this->magic[$name] : array();
$alias = new Alias($name, $facade, $magicMethods, $this->interfaces); $alias = new Alias($this->config, $name, $facade, $magicMethods, $this->interfaces);
if ($alias->isValid()) { if ($alias->isValid()) {
//Add extra methods, from other classes (magic static calls) //Add extra methods, from other classes (magic static calls)
if (array_key_exists($name, $this->extra)) { if (array_key_exists($name, $this->extra)) {
$alias->addClass($this->extra[$name]); $alias->addClass($this->extra[$name]);
} }
$namespace = $alias->getExtendsNamespace() ?: $alias->getNamespace(); $aliases[] = $alias;
if (!isset($namespaces[$namespace])) {
$namespaces[$namespace] = array();
}
$namespaces[$namespace][] = $alias;
} }
} }
return $namespaces; return $aliases;
}
/**
* Regroup aliases by namespace of extended classes
*
* @return Collection
*/
protected function getAliasesByExtendsNamespace()
{
return $this->getValidAliases()->groupBy(function (Alias $alias) {
return $alias->getExtendsNamespace();
});
}
/**
* Regroup aliases by namespace of alias
*
* @return Collection
*/
protected function getAliasesByAliasNamespace()
{
return $this->getValidAliases()->groupBy(function (Alias $alias) {
return $alias->getNamespace();
});
} }
protected function getAliases() protected function getAliases()
@@ -244,15 +265,20 @@ class Generator
'Schema' => 'Illuminate\Support\Facades\Schema', 'Schema' => 'Illuminate\Support\Facades\Schema',
'Session' => 'Illuminate\Support\Facades\Session', 'Session' => 'Illuminate\Support\Facades\Session',
'Storage' => 'Illuminate\Support\Facades\Storage', 'Storage' => 'Illuminate\Support\Facades\Storage',
//'Validator' => 'Illuminate\Support\Facades\Validator', 'Validator' => 'Illuminate\Support\Facades\Validator',
'Gate' => 'Illuminate\Support\Facades\Gate',
]; ];
$facades = array_merge($facades, $this->config->get('app.aliases', [])); $facades = array_merge($facades, $this->config->get('app.aliases', []));
// Only return the ones that actually exist // Only return the ones that actually exist
return array_filter($facades, function ($alias) { return array_filter(
return class_exists($alias); $facades,
}); function ($alias) {
return class_exists($alias);
},
ARRAY_FILTER_USE_KEY
);
} }
/** /**
+45 -9
View File
@@ -10,10 +10,15 @@
namespace Barryvdh\LaravelIdeHelper; namespace Barryvdh\LaravelIdeHelper;
use Illuminate\Support\ServiceProvider; use Barryvdh\LaravelIdeHelper\Console\EloquentCommand;
use Barryvdh\LaravelIdeHelper\Console\GeneratorCommand;
use Barryvdh\LaravelIdeHelper\Console\MetaCommand; use Barryvdh\LaravelIdeHelper\Console\MetaCommand;
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand; use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
use Barryvdh\LaravelIdeHelper\Console\GeneratorCommand; use Illuminate\Support\ServiceProvider;
use Illuminate\View\Engines\EngineResolver;
use Illuminate\View\Engines\PhpEngine;
use Illuminate\View\Factory;
use Illuminate\View\FileViewFinder;
class IdeHelperServiceProvider extends ServiceProvider class IdeHelperServiceProvider extends ServiceProvider
{ {
@@ -32,8 +37,10 @@ class IdeHelperServiceProvider extends ServiceProvider
*/ */
public function boot() public function boot()
{ {
$viewPath = __DIR__.'/../resources/views'; if ($this->app->has('view')) {
$this->loadViewsFrom($viewPath, 'ide-helper'); $viewPath = __DIR__ . '/../resources/views';
$this->loadViewsFrom($viewPath, 'ide-helper');
}
$configPath = __DIR__ . '/../config/ide-helper.php'; $configPath = __DIR__ . '/../config/ide-helper.php';
if (function_exists('config_path')) { if (function_exists('config_path')) {
@@ -53,11 +60,12 @@ class IdeHelperServiceProvider extends ServiceProvider
{ {
$configPath = __DIR__ . '/../config/ide-helper.php'; $configPath = __DIR__ . '/../config/ide-helper.php';
$this->mergeConfigFrom($configPath, 'ide-helper'); $this->mergeConfigFrom($configPath, 'ide-helper');
$localViewFactory = $this->createLocalViewFactory();
$this->app->singleton( $this->app->singleton(
'command.ide-helper.generate', 'command.ide-helper.generate',
function ($app) { function ($app) use ($localViewFactory) {
return new GeneratorCommand($app['config'], $app['files'], $app['view']); return new GeneratorCommand($app['config'], $app['files'], $localViewFactory);
} }
); );
@@ -70,12 +78,24 @@ class IdeHelperServiceProvider extends ServiceProvider
$this->app->singleton( $this->app->singleton(
'command.ide-helper.meta', 'command.ide-helper.meta',
function ($app) { function ($app) use ($localViewFactory) {
return new MetaCommand($app['files'], $app['view']); return new MetaCommand($app['files'], $localViewFactory, $app['config']);
} }
); );
$this->commands('command.ide-helper.generate', 'command.ide-helper.models', 'command.ide-helper.meta'); $this->app->singleton(
'command.ide-helper.eloquent',
function ($app) use ($localViewFactory) {
return new EloquentCommand($app['files']);
}
);
$this->commands(
'command.ide-helper.generate',
'command.ide-helper.models',
'command.ide-helper.meta',
'command.ide-helper.eloquent'
);
} }
/** /**
@@ -87,4 +107,20 @@ class IdeHelperServiceProvider extends ServiceProvider
{ {
return array('command.ide-helper.generate', 'command.ide-helper.models'); return array('command.ide-helper.generate', 'command.ide-helper.models');
} }
/**
* @return Factory
*/
private function createLocalViewFactory()
{
$resolver = new EngineResolver();
$resolver->register('php', function () {
return new PhpEngine();
});
$finder = new FileViewFinder($this->app['files'], [__DIR__ . '/../resources/views']);
$factory = new Factory($resolver, $finder, $this->app['events']);
$factory->addExtension('php', 'php');
return $factory;
}
} }
+46
View File
@@ -0,0 +1,46 @@
<?php
namespace Barryvdh\LaravelIdeHelper;
use Barryvdh\Reflection\DocBlock;
use Barryvdh\Reflection\DocBlock\Tag;
class Macro extends Method
{
/**
* Macro constructor.
*
* @param \ReflectionFunctionAbstract $method
* @param string $alias
* @param \ReflectionClass $class
* @param null $methodName
* @param array $interfaces
*/
public function __construct(
$method,
$alias,
$class,
$methodName = null,
$interfaces = array()
) {
parent::__construct($method, $alias, $class, $methodName, $interfaces);
}
/**
* @param \ReflectionFunctionAbstract $method
*/
protected function initPhpDoc($method)
{
$this->phpdoc = new DocBlock($method);
}
/**
* @param \ReflectionFunctionAbstract $method
* @param \ReflectionClass $class
*/
protected function initClassDefinedProperties($method, \ReflectionClass $class)
{
$this->namespace = $class->getNamespaceName();
$this->declaringClassName = '\\' . ltrim($class->name, '\\');
}
}
+61 -6
View File
@@ -26,29 +26,36 @@ class Method
protected $method; protected $method;
protected $output = ''; protected $output = '';
protected $declaringClassName;
protected $name; protected $name;
protected $namespace; protected $namespace;
protected $params = array(); protected $params = array();
protected $params_with_default = array(); protected $params_with_default = array();
protected $interfaces = array(); protected $interfaces = array();
protected $real_name;
protected $return = null; protected $return = null;
protected $root;
/** /**
* @param \ReflectionMethod $method * @param \ReflectionMethod|\ReflectionFunctionAbstract $method
* @param string $alias * @param string $alias
* @param \ReflectionClass $class * @param \ReflectionClass $class
* @param string|null $methodName * @param string|null $methodName
* @param array $interfaces * @param array $interfaces
*/ */
public function __construct(\ReflectionMethod $method, $alias, $class, $methodName = null, $interfaces = array()) public function __construct($method, $alias, $class, $methodName = null, $interfaces = array())
{ {
$this->method = $method; $this->method = $method;
$this->interfaces = $interfaces; $this->interfaces = $interfaces;
$this->name = $methodName ?: $method->name; $this->name = $methodName ?: $method->name;
$this->namespace = $method->getDeclaringClass()->getNamespaceName(); $this->real_name = $method->isClosure() ? $this->name : $method->name;
$this->initClassDefinedProperties($method, $class);
//Reference the 'real' function in the declaring class
$this->root = '\\' . ltrim($class->getName(), '\\');
//Create a DocBlock and serializer instance //Create a DocBlock and serializer instance
$this->phpdoc = new DocBlock($method, new Context($this->namespace)); $this->initPhpDoc($method);
//Normalize the description and inherit the docs from parents/interfaces //Normalize the description and inherit the docs from parents/interfaces
try { try {
@@ -63,11 +70,25 @@ class Method
//Make the method static //Make the method static
$this->phpdoc->appendTag(Tag::createInstance('@static', $this->phpdoc)); $this->phpdoc->appendTag(Tag::createInstance('@static', $this->phpdoc));
}
//Reference the 'real' function in the declaringclass /**
* @param \ReflectionMethod $method
*/
protected function initPhpDoc($method)
{
$this->phpdoc = new DocBlock($method, new Context($this->namespace));
}
/**
* @param \ReflectionMethod $method
* @param \ReflectionClass $class
*/
protected function initClassDefinedProperties($method, \ReflectionClass $class)
{
$declaringClass = $method->getDeclaringClass(); $declaringClass = $method->getDeclaringClass();
$this->namespace = $declaringClass->getNamespaceName();
$this->declaringClassName = '\\' . ltrim($declaringClass->name, '\\'); $this->declaringClassName = '\\' . ltrim($declaringClass->name, '\\');
$this->root = '\\' . ltrim($class->getName(), '\\');
} }
/** /**
@@ -90,6 +111,26 @@ class Method
return $this->root; return $this->root;
} }
/**
* @return bool
*/
public function isInstanceCall()
{
return ! ($this->method->isClosure() || $this->method->isStatic());
}
/**
* @return string
*/
public function getRootMethodCall()
{
if ($this->isInstanceCall()) {
return "\$instance->{$this->getRealName()}({$this->getParams()})";
} else {
return "{$this->getRoot()}::{$this->getRealName()}({$this->getParams()})";
}
}
/** /**
* Get the docblock for this method * Get the docblock for this method
* *
@@ -112,6 +153,16 @@ class Method
return $this->name; return $this->name;
} }
/**
* Get the real method name
*
* @return string
*/
public function getRealName()
{
return $this->real_name;
}
/** /**
* Get the parameters for this method * Get the parameters for this method
* *
@@ -213,6 +264,10 @@ class Method
// Set the changed content // Set the changed content
$tag->setContent($returnValue . ' ' . $tag->getDescription()); $tag->setContent($returnValue . ' ' . $tag->getDescription());
$this->return = $returnValue; $this->return = $returnValue;
if ($tag->getType() === '$this') {
$tag->setType($this->root);
}
} else { } else {
$this->return = null; $this->return = null;
} }