Compare commits

..
Author SHA1 Message Date
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
M. Vugteveen 28f0ac3781 also show time in generated files (#574) 2017-09-13 14:18:03 +02: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
15 changed files with 506 additions and 112 deletions
+2 -2
View File
@@ -4,7 +4,7 @@ php:
- 5.5
- 5.6
- 7.0
- hhvm
- 7.1
# This triggers builds to run on the new TravisCI infrastructure.
# See: http://docs.travis-ci.com/user/workers/container-based-infrastructure/
@@ -28,4 +28,4 @@ script:
- vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover
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
- if [[ $TRAVIS_PHP_VERSION != 'hhvm' && $TRAVIS_PHP_VERSION != '7.0' ]]; then php vendor/bin/ocular code-coverage:upload --format=php-clover coverage.clover; fi
+10 -3
View File
@@ -11,13 +11,15 @@
],
"require": {
"php": ">=5.4.0",
"illuminate/support": "^5.0,<5.5",
"illuminate/console": "^5.0,<5.5",
"illuminate/filesystem": "^5.0,<5.5",
"illuminate/support": "^5.0,<5.7",
"illuminate/console": "^5.0,<5.7",
"illuminate/filesystem": "^5.0,<5.7",
"barryvdh/reflection-docblock": "^2.0.4",
"symfony/class-loader": "^2.3|^3.0"
},
"require-dev": {
"illuminate/config": "^5.0,<5.7",
"illuminate/view": "^5.0,<5.7",
"phpunit/phpunit" : "4.*",
"scrutinizer/ocular": "~1.1",
"squizlabs/php_codesniffer": "~2.3",
@@ -43,6 +45,11 @@
"extra": {
"branch-alias": {
"dev-master": "2.3-dev"
},
"laravel": {
"providers": [
"Barryvdh\\LaravelIdeHelper\\IdeHelperServiceProvider"
]
}
}
}
+13
View File
@@ -13,6 +13,8 @@ return array(
'filename' => '_ide_helper',
'format' => 'php',
'meta_filename' => '.phpstorm.meta.php',
/*
|--------------------------------------------------------------------------
@@ -25,6 +27,17 @@ return array(
'include_fluent' => false,
/*
|--------------------------------------------------------------------------
| Write Model Magic methods
|--------------------------------------------------------------------------
|
| Set to false to disable write magic methods of model
|
*/
'write_model_magic_where' => true,
/*
|--------------------------------------------------------------------------
| Helper files to include
+11 -5
View File
@@ -22,7 +22,7 @@ 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 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
@@ -90,7 +90,7 @@ 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.
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.
The `Illuminate/Support/helpers.php` is already set up, but you can add/remove your own files in the config file.
@@ -149,18 +149,24 @@ Models can be ignored using the `--ignore (-I)` option
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
If you need phpDocs support for Fluent methods in migration, for example
```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:
```php
'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
+32 -32
View File
@@ -2,25 +2,23 @@
/**
* 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]>
* @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; ?>
namespace <?= $namespace == '__root' ? '' : trim($namespace, '\\') ?> {
namespace <?= $namespace == '__root' ? '' : trim($namespace, '\\') ?> {
<?php foreach($aliases as $alias): ?>
<?= $alias->getClassType() ?> <?= $alias->getExtendsClass() ?> {
<?php foreach($alias->getMethods() as $method): ?>
<?= trim($method->getDocComment(' ')) ?>
<?= trim($method->getDocComment(' ')) ?>
public static function <?= $method->getName() ?>(<?= $method->getParamsWithDefault() ?>)
{<?php if($method->getDeclaringClass() !== $method->getRoot()): ?>
@@ -29,39 +27,41 @@ namespace <?= $namespace == '__root' ? '' : trim($namespace, '\\') ?> {
<?= $method->shouldReturn() ? 'return ': '' ?><?= $method->getRoot() ?>::<?= $method->getName() ?>(<?= $method->getParams() ?>);
}
<?php endforeach; ?>
}
<?php endforeach; ?>
<?php endforeach; ?>
}
<?php endforeach; ?>
}
<?php endforeach; ?>
namespace {
<?= $helpers ?>
<?php foreach($namespaces as $namespace => $aliases): ?>
<?php foreach($namespaces_by_alias_ns as $namespace => $aliases): ?>
namespace <?= $namespace == '__root' ? '' : trim($namespace, '\\') ?> {
<?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(' ')) ?>
public static function <?= $method->getName() ?>(<?= $method->getParamsWithDefault() ?>)
{<?php if($method->getDeclaringClass() !== $method->getRoot()): ?>
//Method inherited from <?= $method->getDeclaringClass() ?>
<?php endif; ?>
<?= $method->shouldReturn() ? 'return ': '' ?><?= $method->getRoot() ?>::<?= $method->getName() ?>(<?= $method->getParams() ?>);
}
<?= $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()): ?>
//Method inherited from <?= $method->getDeclaringClass() ?>
<?php endif; ?>
<?= $method->shouldReturn() ? 'return ': '' ?><?= $method->getRoot() ?>::<?= $method->getName() ?>(<?= $method->getParams() ?>);
}
<?php endforeach; ?>
<?php endif; ?>}
<?php endforeach; ?>
<?php endforeach; ?>
<?php endforeach; ?>
}
<?php endforeach; ?>
<?php if($helpers): ?>
namespace {
<?= $helpers ?>
}
<?php endif; ?>
<?php if($include_fluent): ?>
namespace Illuminate\Support {
/**
+39 -9
View File
@@ -4,18 +4,48 @@ namespace PHPSTORM_META {
/**
* 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]>
* @see https://github.com/barryvdh/laravel-ide-helper
*/
$STATIC_METHOD_TYPES = [
<?php foreach($methods as $method): ?>
<?= $method ?> => [
'' == '@',
<?php foreach ($methods as $method): ?>
override(<?= $method ?>, map([
'' => '@',
<?php foreach($bindings as $abstract => $class): ?>
'<?= $abstract ?>' instanceof \<?= $class ?>,
<?php endforeach ?> ],
<?php endforeach ?>
];
'<?= $abstract ?>' => \<?= $class ?>::class,
<?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));
}
+18
View File
@@ -312,6 +312,24 @@ 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) {
$function = new \ReflectionFunction($macro_func);
// Add macros
$this->methods[] = new Macro(
$function,
$this->alias,
$reflection,
$macro_name,
$this->interfaces
);
}
}
}
}
+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);
}
}
+3 -2
View File
@@ -10,8 +10,8 @@
namespace Barryvdh\LaravelIdeHelper\Console;
use Barryvdh\LaravelIdeHelper\Eloquent;
use Barryvdh\LaravelIdeHelper\Generator;
use Illuminate\Config\Repository as ConfigRepository;
use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
use Symfony\Component\Console\Input\InputOption;
@@ -74,7 +74,7 @@ class GeneratorCommand extends Command
*
* @return void
*/
public function fire()
public function handle()
{
if (file_exists(base_path() . '/vendor/compiled.php') ||
file_exists(base_path() . '/bootstrap/cache/compiled.php') ||
@@ -115,6 +115,7 @@ class GeneratorCommand extends Command
if ($written !== false) {
$this->info("A new helper file was written to $filename");
Eloquent::writeEloquentModelHelper($this, $this->files);
} else {
$this->error("The helper file could not be created at $filename");
}
+20 -11
View File
@@ -28,7 +28,6 @@ class MetaCommand extends Command
* @var string
*/
protected $name = 'ide-helper:meta';
protected $filename = '.phpstorm.meta.php';
/**
* The console command description.
@@ -42,23 +41,31 @@ class MetaCommand extends Command
/** @var \Illuminate\Contracts\View\Factory */
protected $view;
/** @var \Illuminate\Contracts\Config */
protected $config;
protected $methods = [
'new \Illuminate\Contracts\Container\Container',
'\Illuminate\Contracts\Container\Container::make(\'\')',
'\App::make(\'\')',
'\app(\'\')',
'\Illuminate\Contracts\Container\Container::make(0)',
'\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\View\Factory $view
* @param \Illuminate\Contracts\Config $config
*/
public function __construct($files, $view)
public function __construct($files, $view, $config)
{
$this->files = $files;
$this->view = $view;
$this->config = $config;
parent::__construct();
}
@@ -67,7 +74,7 @@ class MetaCommand extends Command
*
* @return void
*/
public function fire()
public function handle()
{
$this->registerClassAutoloadExceptions();
@@ -77,7 +84,7 @@ class MetaCommand extends Command
if (in_array($abstract, ['validator', 'seeder'])) {
continue;
}
try {
$concrete = $this->laravel->make($abstract);
if (is_object($concrete)) {
@@ -90,7 +97,7 @@ class MetaCommand extends Command
}
}
$content = $this->view->make('ide-helper::meta', [
$content = $this->view->make('meta', [
'bindings' => $bindings,
'methods' => $this->methods,
])->render();
@@ -113,7 +120,7 @@ class MetaCommand extends Command
protected function getAbstracts()
{
$abstracts = $this->laravel->getBindings();
// Return the abstract names only
return array_keys($abstracts);
}
@@ -135,8 +142,10 @@ class MetaCommand extends Command
*/
protected function getOptions()
{
$filename = $this->config->get('ide-helper.meta_filename');
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),
);
}
}
+91 -22
View File
@@ -50,11 +50,16 @@ class ModelsCommand extends Command
*/
protected $description = 'Generate autocompletion for models';
protected $write_model_magic_where;
protected $properties = array();
protected $methods = array();
protected $write = false;
protected $dirs = array();
protected $reset;
/**
* @var bool[string]
*/
protected $nullableColumns = [];
/**
* @param Filesystem $files
@@ -70,7 +75,7 @@ class ModelsCommand extends Command
*
* @return void
*/
public function fire()
public function handle()
{
$filename = $this->option('filename');
$this->write = $this->option('write');
@@ -81,6 +86,7 @@ class ModelsCommand extends Command
$model = $this->argument('model');
$ignore = $this->option('ignore');
$this->reset = $this->option('reset');
$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 (!$this->write && $filename === $this->filename && !$this->option('nowrite')) {
@@ -200,8 +206,10 @@ class ModelsCommand extends Command
}
$this->getPropertiesFromMethods($model);
$output .= $this->createPhpDocs($name);
$ignore[] = $name;
$this->getSoftDeleteMethods($model);
$output .= $this->createPhpDocs($name);
$ignore[] = $name;
$this->nullableColumns = [];
} catch (\Exception $e) {
$this->error("Exception: " . $e->getMessage() . "\nCould not analyze class $name.");
}
@@ -347,13 +355,21 @@ class ModelsCommand extends Command
case 'smallint':
$type = 'integer';
break;
case 'boolean':
switch (config('database.default')) {
case 'sqlite':
case 'mysql':
$type = 'integer';
break;
default:
$type = 'boolean';
break;
}
break;
case 'decimal':
case 'float':
$type = 'float';
break;
case 'boolean':
$type = 'boolean';
break;
default:
$type = 'mixed';
break;
@@ -361,12 +377,17 @@ class ModelsCommand extends Command
}
$comment = $column->getComment();
$this->setProperty($name, $type, true, true, $comment);
$this->setMethod(
Str::camel("where_" . $name),
'\Illuminate\Database\Query\Builder|\\' . get_class($model),
array('$value')
);
if (!$column->getNotnull()) {
$this->nullableColumns[$name] = true;
}
$this->setProperty($name, $type, true, true, $comment, !$column->getNotnull());
if ($this->write_model_magic_where) {
$this->setMethod(
Str::camel("where_" . $name),
'\Illuminate\Database\Eloquent\Builder|\\' . get_class($model),
array('$value')
);
}
}
}
}
@@ -410,7 +431,7 @@ class ModelsCommand extends Command
$args = $this->getParameters($reflection);
//Remove the first ($query) argument
array_shift($args);
$this->setMethod($name, '\Illuminate\Database\Query\Builder|\\' . $reflection->class, $args);
$this->setMethod($name, '\Illuminate\Database\Eloquent\Builder|\\' . $reflection->class, $args);
}
} elseif (!method_exists('Illuminate\Database\Eloquent\Model', $method)
&& !Str::startsWith($method, 'get')
@@ -468,7 +489,14 @@ class ModelsCommand extends Command
);
} else {
//Single model is returned
$this->setProperty($method, $relatedModel, true, null);
$this->setProperty(
$method,
$relatedModel,
true,
null,
'',
$this->isRelationForeignKeyNullable($relationObj)
);
}
}
}
@@ -479,13 +507,33 @@ class ModelsCommand extends Command
}
/**
* @param string $name
* @param string|null $type
* @param bool|null $read
* @param bool|null $write
* @param string|null $comment
* Check if the foreign key of the relation is nullable
*
* @param Relation $relation
*
* @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])) {
$this->properties[$name] = array();
@@ -495,7 +543,11 @@ class ModelsCommand extends Command
$this->properties[$name]['comment'] = (string) $comment;
}
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) {
$this->properties[$name]['read'] = $read;
@@ -690,9 +742,26 @@ class ModelsCommand extends Command
$phpdoc = new DocBlock($reflection);
if ($phpdoc->hasTag('return')) {
$type = $phpdoc->getTagsByName('return')[0]->getContent();
$type = $phpdoc->getTagsByName('return')[0]->getType();
}
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), []);
}
}
}
+78
View File
@@ -0,0 +1,78 @@
<?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');
foreach ($mixins as $m) {
if ($m->getContent() === '\Eloquent') {
$command->info('Tag Exists: @mixin \Eloquent in ' . $class);
return;
}
}
// add the Eloquent mixin
$phpdoc->appendTag(Tag::createInstance("@mixin \\Eloquent", $phpdoc));
$serializer = new DocBlockSerializer();
$serializer->getDocComment($phpdoc);
$docComment = $serializer->getDocComment($phpdoc);
$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 @mixin \Eloquent 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);
}
}
}
+37 -16
View File
@@ -12,7 +12,7 @@ namespace Barryvdh\LaravelIdeHelper;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\AliasLoader;
use Illuminate\Config\Repository as ConfigRepository;
use Illuminate\Support\Collection;
use ReflectionClass;
use Symfony\Component\Console\Output\OutputInterface;
@@ -80,18 +80,19 @@ class Generator
public function generatePhpHelper()
{
$app = app();
return $this->view->make('ide-helper::helper')
->with('namespaces', $this->getNamespaces())
return $this->view->make('helper')
->with('namespaces_by_extends_ns', $this->getAliasesByExtendsNamespace())
->with('namespaces_by_alias_ns', $this->getAliasesByAliasNamespace())
->with('helpers', $this->helpers)
->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();
}
public function generateJsonHelper()
{
$classes = array();
foreach ($this->getNamespaces() as $aliases) {
foreach ($this->getValidAliases() as $aliases) {
foreach ($aliases as $alias) {
$functions = array();
foreach ($alias->getMethods() as $method) {
@@ -186,13 +187,13 @@ 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
foreach ($this->getAliases() as $name => $facade) {
@@ -208,16 +209,36 @@ class Generator
if (array_key_exists($name, $this->extra)) {
$alias->addClass($this->extra[$name]);
}
$namespace = $alias->getExtendsNamespace() ?: $alias->getNamespace();
if (!isset($namespaces[$namespace])) {
$namespaces[$namespace] = array();
}
$namespaces[$namespace][] = $alias;
$aliases[] = $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()
+44 -10
View File
@@ -10,10 +10,15 @@
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\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
{
@@ -34,7 +39,7 @@ class IdeHelperServiceProvider extends ServiceProvider
{
$viewPath = __DIR__.'/../resources/views';
$this->loadViewsFrom($viewPath, 'ide-helper');
$configPath = __DIR__ . '/../config/ide-helper.php';
if (function_exists('config_path')) {
$publishPath = config_path('ide-helper.php');
@@ -53,11 +58,12 @@ class IdeHelperServiceProvider extends ServiceProvider
{
$configPath = __DIR__ . '/../config/ide-helper.php';
$this->mergeConfigFrom($configPath, 'ide-helper');
$localViewFactory = $this->createLocalViewFactory();
$this->app->singleton(
'command.ide-helper.generate',
function ($app) {
return new GeneratorCommand($app['config'], $app['files'], $app['view']);
function ($app) use ($localViewFactory) {
return new GeneratorCommand($app['config'], $app['files'], $localViewFactory);
}
);
@@ -67,15 +73,27 @@ class IdeHelperServiceProvider extends ServiceProvider
return new ModelsCommand($app['files']);
}
);
$this->app->singleton(
'command.ide-helper.meta',
function ($app) {
return new MetaCommand($app['files'], $app['view']);
function ($app) use ($localViewFactory) {
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 +105,20 @@ class IdeHelperServiceProvider extends ServiceProvider
{
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;
}
}
+47
View File
@@ -0,0 +1,47 @@
<?php
namespace Barryvdh\LaravelIdeHelper;
use Barryvdh\Reflection\DocBlock;
use Barryvdh\Reflection\DocBlock\Tag;
class Macro extends Method
{
/**
* Macro constructor.
*
* @param \ReflectionFunction $method
* @param string $alias
* @param \ReflectionClass $class
* @param null $methodName
* @param array $interfaces
*/
public function __construct(\ReflectionFunction $method, $alias, $class, $methodName = null, $interfaces = array())
{
$this->method = $method;
$this->interfaces = $interfaces;
$this->name = $methodName ?: $method->name;
$this->namespace = $class->getNamespaceName();
//Create a DocBlock and serializer instance
$this->phpdoc = new DocBlock($method);
//Normalize the description and inherit the docs from parents/interfaces
try {
$this->normalizeParams($this->phpdoc);
$this->normalizeReturn($this->phpdoc);
$this->normalizeDescription($this->phpdoc);
} catch (\Exception $e) {
}
//Get the parameters, including formatted default values
$this->getParameters($method);
//Make the method static
$this->phpdoc->appendTag(Tag::createInstance('@static', $this->phpdoc));
//Reference the 'real' function in the declaringclass
$this->declaringClassName = '\\' . ltrim($class->name, '\\');
$this->root = '\\' . ltrim($class->getName(), '\\');
}
}