Compare commits

..
8 Commits
4 changed files with 88 additions and 44 deletions
+13 -6
View File
@@ -8,6 +8,11 @@ Add the helper file to your laravel folder (not in a public folder). The file is
* SublimeText CodeIntel version: https://gist.github.com/barryvdh/5227814 * SublimeText CodeIntel version: https://gist.github.com/barryvdh/5227814
### Automatic phpDoc generation for Laravel Facades ### Automatic phpDoc generation for Laravel Facades
#### NOTE: run before optimising. If bootstrap/compiled.php is loaded, it doesn't work.
php artisan clear-compiled
php artisan ide-helper:generate
php artisan optimize
Require this package in your composer.json: Require this package in your composer.json:
@@ -31,8 +36,8 @@ You can configure your composer.json to do this after each commit:
"scripts":{ "scripts":{
"post-update-cmd":[ "post-update-cmd":[
"php artisan optimize",
"php artisan ide-helper:generate", "php artisan ide-helper:generate",
"php artisan optimize"
] ]
}, },
@@ -52,21 +57,23 @@ The Illuminate/Support/helpers.php is already set-up, but you can add/remove you
### Work in progress: Model docs ### Work in progress: Model docs
If you don't want to write your properties yourself, you can use the (experimental) command `ide-helper:models` to generate If you don't want to write your properties yourself, you can use the (experimental) command `ide-helper:models` to generate
phpDocs, based on table columns, relations and getters/setters. Very alpha, so please provide feedback if you want. phpDocs, based on table columns, relations and getters/setters. Still in beta, so please provide feedback if you want.
Docs are written to a phpfile in the root of the project, so you can move the docs to the real model. Docs are written to a phpfile (_ide_helper_models.php) in the root of the project, so you can move the docs to the real model.
For now, only models in app/models are scanned. The optional argument tells what models to use. You can now also write the comments directly to your Model file, using the -W argument. Please make sure to backup your models, before writing the info.
It should keep the existing comments and only append new properties/methods.
For now, only models in app/models are scanned. The optional argument tells what models to use (also outside app/models).
`php artisan ide-helper:models Post,User` `php artisan ide-helper:models Post,User`
Note: With namespaces, uses \\ instead of \ Note: With namespaces, uses \\ instead of \
`php artisan ide-helper:models API\\User` `php artisan ide-helper:models API\\User`
This creates a file with the phpDocs for each Model. You should check and change them to be more accurate. This creates a file with the phpDocs for each Model. You should check and change them to be more accurate.
It doesn't know if datetimes are returned as string or DateTime/Carbon, but I assume they are.
Also, all relations are Eloquent|Eloquent[] by default, you can change them to the actual Model. Also, all relations are Eloquent|Eloquent[] by default, you can change them to the actual Model.
After copying the phpdocs to your model, you can clear the file, so your IDE only uses the real source. After copying the phpdocs to your model, you can clear the file, so your IDE only uses the real source.
### License ### License
The Laravel IDE Helper Generator is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT) The Laravel IDE Helper Generator is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
@@ -52,34 +52,37 @@ class GeneratorCommand extends Command {
*/ */
public function fire() public function fire()
{ {
$filename = $this->argument('filename'); if (file_exists($compiled = base_path().'/bootstrap/compiled.php')){
$this->error('Error generating IDE Helper: first delete bootstrap/compiled.php (php artisan clear-compiled)');
if($this->option('memory')){
$this->useMemoryDriver();
}
$this->extra = \Config::get('laravel-ide-helper::extra');
$this->nonstatic = \Config::get('laravel-ide-helper::nonstatic');
$this->onlyExtend = \Config::get('laravel-ide-helper::only_extend');
if( $this->option('helpers') || (\Config::get('laravel-ide-helper::include_helpers') && ! $this->option('nohelpers'))){
$this->helpers = \Config::get('laravel-ide-helper::helper_files');
}else{ }else{
$this->helpers = array(); $filename = $this->argument('filename');
}
if($this->option('memory')){
$this->sublime = $this->option('sublime') || \Config::get('laravel-ide-helper::sublime'); $this->useMemoryDriver();
}
$content = $this->generateDocs();
$this->extra = \Config::get('laravel-ide-helper::extra');
$written = \File::put($filename, $content); $this->nonstatic = \Config::get('laravel-ide-helper::nonstatic');
$this->onlyExtend = \Config::get('laravel-ide-helper::only_extend');
if($written !== false){
$this->info("A new helper file was written to $filename"); if( $this->option('helpers') || (\Config::get('laravel-ide-helper::include_helpers') && ! $this->option('nohelpers'))){
}else{ $this->helpers = \Config::get('laravel-ide-helper::helper_files');
$this->error("The helper file could not be created at $filename"); }else{
} $this->helpers = array();
}
$this->sublime = $this->option('sublime') || \Config::get('laravel-ide-helper::sublime');
$content = $this->generateDocs();
$written = \File::put($filename, $content);
if($written !== false){
$this->info("A new helper file was written to $filename");
}else{
$this->error("The helper file could not be created at $filename");
}
}
} }
protected function useMemoryDriver(){ protected function useMemoryDriver(){
@@ -315,6 +318,8 @@ namespace {\n\tdie('Only to be used as an helper for your IDE');\n}\n\n";
$returnValue = "static"; $returnValue = "static";
}elseif(!$this->sublime and $alias == 'Eloquent' and in_array($method->name, array('all', 'get'))){ }elseif(!$this->sublime and $alias == 'Eloquent' and in_array($method->name, array('all', 'get'))){
$returnValue .= "|\Eloquent[]|static[]"; $returnValue .= "|\Eloquent[]|static[]";
}elseif($alias == 'Eloquent' and in_array($method->name, array('hasOne', 'hasMany', 'belongsTo', 'belongsToMany', 'morphOne', 'morphTo', 'morphMany'))){
$returnValue .= "|\Eloquent";
} }
$tag->setContent($returnValue . " ". $tag->getDescription()); $tag->setContent($returnValue . " ". $tag->getDescription());
}else{ }else{
+42 -10
View File
@@ -40,6 +40,9 @@ class ModelsCommand extends Command {
protected $properties = array(); protected $properties = array();
protected $methods = array(); protected $methods = array();
protected $write = false;
protected $dir;
/** /**
@@ -50,16 +53,19 @@ class ModelsCommand extends Command {
public function fire() public function fire()
{ {
$filename = $this->option('filename'); $filename = $this->option('filename');
$this->write = $this->option('write');
$this->dir = $this->option('dir');
$model = $this->argument('model'); $model = $this->argument('model');
$content = $this->generateDocs($model); $content = $this->generateDocs($model);
$written = \File::put($filename, $content); if(!$this->write){
$written = \File::put($filename, $content);
if($written !== false){ if($written !== false){
$this->info("Model information was written to $filename"); $this->info("Model information was written to $filename");
}else{ }else{
$this->error("Failed to write model information to $filename"); $this->error("Failed to write model information to $filename");
}
} }
} }
@@ -87,6 +93,8 @@ class ModelsCommand extends Command {
{ {
return array( return array(
array('filename', 'F', InputOption::VALUE_OPTIONAL, 'The path to the helper file', '_ide_helper_models.php'), array('filename', 'F', InputOption::VALUE_OPTIONAL, 'The path to the helper file', '_ide_helper_models.php'),
array('dir', 'D', InputOption::VALUE_OPTIONAL, 'The model dir','app/models'),
array('write', 'W', InputOption::VALUE_NONE, 'Write to Model file'),
); );
} }
@@ -133,9 +141,12 @@ class ModelsCommand extends Command {
protected function loadModels(){ protected function loadModels(){
$dir = base_path().'/'.$this->dir;
$models = array(); $models = array();
foreach(ClassMapGenerator::createMap(app_path().'/models') as $model=> $path){ if(file_exists($dir)){
$models[] = $model; foreach(ClassMapGenerator::createMap($dir) as $model=> $path){
$models[] = $model;
}
} }
return $models; return $models;
} }
@@ -297,6 +308,8 @@ class ModelsCommand extends Command {
$reflection = new \ReflectionClass($class); $reflection = new \ReflectionClass($class);
$namespace = $reflection->getNamespaceName(); $namespace = $reflection->getNamespaceName();
$classname = $reflection->getShortName();
$originalDoc = $reflection->getDocComment();
$phpdoc = new DocBlock($reflection, new Context($namespace)); $phpdoc = new DocBlock($reflection, new Context($namespace));
if(!$phpdoc->getText()){ if(!$phpdoc->getText()){
@@ -339,11 +352,30 @@ class ModelsCommand extends Command {
$phpdoc->appendTag($tag); $phpdoc->appendTag($tag);
} }
$serializer = new DocBlockSerializer(1, "\t"); $serializer = new DocBlockSerializer();
$serializer->getDocComment($phpdoc); $serializer->getDocComment($phpdoc);
$docComment = $serializer->getDocComment($phpdoc); $docComment = $serializer->getDocComment($phpdoc);
$output = "namespace {$namespace}{\n{$docComment}\n\tclass {$class} {}\n}\n\n";
if($this->write){
$filename = $reflection->getFileName();
$contents = \File::get($filename);
if($originalDoc){
$contents = str_replace($originalDoc, $docComment, $contents);
}else{
$needle = "class {$classname}";
$replace = "{$docComment}\nclass {$classname}";
$pos = strpos($contents,$needle);
if ($pos !== false) {
$contents = substr_replace($contents,$replace,$pos,strlen($needle));
}
}
if(\File::put($filename, $contents)){
$this->info('Written new phpDocBlock to '.$filename);
}
}
$output = "namespace {$namespace}{\n{$docComment}\n\tclass {$classname} {}\n}\n\n";
return $output; return $output;
} }
+1 -1
View File
@@ -70,7 +70,7 @@ return array(
*/ */
'nonstatic' => array( 'nonstatic' => array(
'Eloquent' => array('freshTimestamp', 'newCollection', 'toArray', 'toJson', 'toSql'), 'Eloquent' => array('freshTimestamp', 'newCollection', 'toArray', 'toJson', 'toSql', 'delete'),
), ),
/* /*