diff --git a/.gitignore b/.gitignore
index 335df2d..d53f981 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,3 @@
/vendor
composer.lock
-.idea
+.idea/
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..6825241
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,26 @@
+language: php
+php:
+ - 5.4
+ - 5.5
+ - 5.6
+ - hhvm
+
+matrix:
+ include:
+ - php: 5.3
+ dist: precise
+ allow_failures:
+ - php: hhvm
+ fast_finish: true
+
+cache:
+ directories:
+ - vendor
+ - $HOME/.composer/cache
+
+before_script:
+ - travis_retry composer self-update
+ - travis_retry composer install --no-interaction --no-suggest --no-progress
+
+script:
+ - vendor/bin/phpunit
diff --git a/composer.json b/composer.json
index 5363cd8..1fe035d 100644
--- a/composer.json
+++ b/composer.json
@@ -11,14 +11,18 @@
],
"require": {
"php": ">=5.3.0",
+ "illuminate/config": "4.x",
"illuminate/support": "4.x",
"illuminate/console": "4.x",
"illuminate/filesystem": "4.x",
- "barryvdh/reflection-docblock": "^2.0.4",
+ "illuminate/database": "4.x",
+ "illuminate/view": "4.x",
+ "phpdocumentor/reflection-docblock": "^2.0.4",
"symfony/class-loader": "~2.3"
},
"require-dev": {
- "doctrine/dbal": "~2.3"
+ "doctrine/dbal": "~2.3",
+ "phpunit/phpunit": "~4.0"
},
"suggest": {
"doctrine/dbal": "Load information from the database about models for phpdocs (~2.3)"
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 0000000..7660980
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,18 @@
+
+
+
+
+ ./tests/
+
+
+
diff --git a/readme.md b/readme.md
index e2696a3..9d2efb1 100644
--- a/readme.md
+++ b/readme.md
@@ -7,7 +7,7 @@
_Checkout [this Laracasts video](https://laracasts.com/series/how-to-be-awesome-in-phpstorm/episodes/15) for a quick introduction/explanation!_
-This packages generates a file that your IDE can understand, so it can provide accurate autocompletion. Generation is done, based on the files in your project, so they are alway up-to-date.
+This packages generates a file that your IDE can understand, so it can provide accurate autocompletion. Generation is done, based on the files in your project, so they are always up-to-date.
If you don't want to generate it, you can add a pre-generated file to the root folder of your laravel project. (But this isn't as up-to-date as self generated files)
* Generated version: https://gist.github.com/barryvdh/5227822
@@ -18,15 +18,18 @@ Note: You do need CodeIntel for Sublime Text: https://github.com/SublimeCodeInte
It's possible to generate a PhpStorm meta file, to [add support for factory design pattern](https://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Advanced+Metadata). For Laravel, this means we can make PhpStorm understand what kind of object we are resolving from the IoC Container. For example, `events` will return ann `Illuminate\Events\Dispatcher` object, so with the meta file you can call `app('events')` and it will autocomplete the Dispatcher methods.
- php artisan ide-helper:meta
-
- app('events')->fire();
- \App::make('events')->fire();
-
- /** @var \Illuminate\Foundation\Application $app */
- $app->make('events')->fire();
+```bash
+php artisan ide-helper:meta
+```
+```php
+app('events')->fire();
+\App::make('events')->fire();
-Pre-generated example: https://gist.github.com/barryvdh/bb6ffc5d11e0a75dba67
+/** @var \Illuminate\Foundation\Application $app */
+$app->make('events')->fire();
+```
+
+Pre-generated example: https://gist.github.com/barryvdh/bb6ffc5d11e0a75dba67
> Note: You might need to restart PhpStorm and make sure `.phpstorm.meta.php` is indexed.
@@ -34,31 +37,41 @@ Pre-generated example: https://gist.github.com/barryvdh/bb6ffc5d11e0a75dba67
Require this package with composer using the following command:
- composer require barryvdh/laravel-ide-helper ~1.11
+```bash
+composer require barryvdh/laravel-ide-helper ~1.11
+```
After updating composer, add the ServiceProvider to the providers array in `app/config/app.php`
- 'Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider',
+```php
+'Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider',
+```
You can now re-generate the docs yourself (for future updates) in artisan
- php artisan ide-helper:generate
+```bash
+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..)
You can configure your composer.json to do this after each commit:
- "scripts":{
- "post-update-cmd":[
- "php artisan clear-compiled",
- "php artisan ide-helper:generate",
- "php artisan optimize"
- ]
- },
+```json
+"scripts":{
+ "post-update-cmd":[
+ "php artisan clear-compiled",
+ "php artisan ide-helper:generate",
+ "php artisan optimize"
+ ]
+},
+```
You can also publish the config-file to change implementations (ie. interface to specific class) or set defaults for --helpers or --sublime.
- php artisan config:publish barryvdh/laravel-ide-helper
+```bash
+php artisan config:publish barryvdh/laravel-ide-helper
+```
The generator tries to identify the real class, but if it cannot be found, you can define it in the config file.
@@ -70,7 +83,7 @@ The Illuminate/Support/helpers.php is already set-up, but you can add/remove you
### Automatic phpDocs for Models
-> **Note:** Since v1.10 you need to require `doctrine/dbal: ~2.3` in your own composer.json.
+> **Note:** Since v1.10 you need to require `doctrine/dbal: ~2.3` in your own composer.json.
If you don't want to write your properties yourself, you can use the command `ide-helper:models` to generate
phpDocs, based on table columns, relations and getters/setters. You can write the comments directly to your Model file, using the `--write (-W)` option. By default, you are asked to overwrite or write to a separate file (\_ide\_helper\_models.php) (You can force No with `--nowrite (-N)`).
@@ -78,34 +91,43 @@ Please make sure to backup your models, before writing the info.
It should keep the existing comments and only append new properties/methods. The existing phpdoc is replaced, or added if not found.
With the `--reset (-R)` option, the existing phpdocs are ignored, only the newly found columns/relations are saved as phpdocs.
- php artisan ide-helper:models Post
-
- /**
- * An Eloquent Model: 'Post'
- *
- * @property integer $id
- * @property integer $author_id
- * @property string $title
- * @property string $text
- * @property \Carbon\Carbon $created_at
- * @property \Carbon\Carbon $updated_at
- * @property-read \User $author
- * @property-read \Illuminate\Database\Eloquent\Collection|\Comment[] $comments
- */
+```bash
+php artisan ide-helper:models Post
+```
+```php
+/**
+ * An Eloquent Model: 'Post'
+ *
+ * @property integer $id
+ * @property integer $author_id
+ * @property string $title
+ * @property string $text
+ * @property \Carbon\Carbon $created_at
+ * @property \Carbon\Carbon $updated_at
+ * @property-read \User $author
+ * @property-read \Illuminate\Database\Eloquent\Collection|\Comment[] $comments
+ */
+```
By default, 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
+```bash
+php artisan ide-helper:models Post User
+```
You can also scan a different directory, using the --dir option (relative from the base path):
- php artisan ide-helper:models --dir="app/workbench/name/package/models" --dir="app/src/Model"
-
+```bash
+php artisan ide-helper:models --dir="app/workbench/name/package/models" --dir="app/src/Model"
+```
+
You can publish the config file (`php artisan config:publish barryvdh/laravel-ide-helper`) and set the default directories.
Models can be ignored using the --ignore (-I) option
- php artisan ide-helper:models --ignore="Post,User"
+```bash
+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`)
diff --git a/src/Alias.php b/src/Alias.php
index 3996931..745b327 100644
--- a/src/Alias.php
+++ b/src/Alias.php
@@ -1,284 +1,287 @@
-
- * @copyright 2014 Barry vd. Heuvel / 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;
-
-class Alias
-{
- protected $alias;
- protected $facade;
- protected $extends = null;
- protected $classType = 'class';
- protected $short;
- protected $namespace = '__root';
- protected $root = null;
- protected $classes = array();
- protected $methods = array();
- protected $usedMethods = array();
- protected $valid = false;
- protected $magicMethods = array();
- protected $interfaces = array();
-
- /**
- * @param string $alias
- * @param string $facade
- * @param array $magicMethods
- * @param array $interfaces
- */
- public function __construct($alias, $facade, $magicMethods = array(), $interfaces = array())
- {
- $this->alias = $alias;
- $this->magicMethods = $magicMethods;
- $this->interfaces = $interfaces;
-
- // Make the class absolute
- $facade = '\\' . ltrim($facade, '\\');
- $this->facade = $facade;
-
- $this->detectRoot();
-
- if ((!$this->isTrait() && $this->root)) {
- $this->valid = true;
- } else {
- return;
- }
-
- $this->addClass($this->root);
- $this->detectNamespace();
- $this->detectClassType();
-
- if($facade === '\Illuminate\Database\Eloquent\Model'){
- $this->usedMethods = array('decrement', 'increment');
- }
- }
-
- /**
- * Add one or more classes to analyze
- *
- * @param array|string $classes
- */
- public function addClass($classes)
- {
- $classes = (array)$classes;
- foreach ($classes as $class) {
- if (class_exists($class) || interface_exists($class)) {
- $this->classes[] = $class;
- }else{
- echo "Class not exists: $class\r\n";
- }
- }
- }
-
- /**
- * Check if this class is valid to process.
- * @return bool
- */
- public function isValid()
- {
- return $this->valid;
- }
-
- /**
- * Get the classtype, 'interface' or 'class'
- *
- * @return string
- */
- public function getClasstype()
- {
- return $this->classType;
- }
-
- /**
- * Get the class which this alias extends
- *
- * @return null|string
- */
- public function getExtends()
- {
- return $this->extends;
- }
-
- /**
- * Get the Alias by which this class is called
- *
- * @return string
- */
- public function getAlias()
- {
- return $this->alias;
- }
-
- /**
- * Return the short name (without namespace)
- */
- public function getShortName(){
- return $this->short;
- }
- /**
- * Get the namespace from the alias
- *
- * @return string
- */
- public function getNamespace()
- {
- return $this->namespace;
- }
-
- /**
- * Get the methods found by this Alias
- *
- * @return array
- */
- public function getMethods()
- {
- $this->addMagicMethods();
- $this->detectMethods();
- return $this->methods;
- }
-
- /**
- * Detect the namespace
- */
- protected function detectNamespace()
- {
- if (strpos($this->alias, '\\')) {
- $nsParts = explode('\\', $this->alias);
- $this->short = array_pop($nsParts);
- $this->namespace = implode('\\', $nsParts);
- }else{
- $this->short = $this->alias;
- }
- }
-
- /**
- * Detect the class type
- */
- protected function detectClassType()
- {
- //Some classes extend the facade
- if (interface_exists($this->facade)) {
- $this->classType = 'interface';
- $this->extends = $this->facade;
- } else {
- $this->classType = 'class';
- if (class_exists($this->facade)) {
- $this->extends = $this->facade;
- }
- }
- }
-
- /**
- * Get the real root of a facade
- *
- * @return bool|string
- */
- protected function detectRoot()
- {
- $facade = $this->facade;
-
- try {
- //If possible, get the facade root
- if (method_exists($facade, 'getFacadeRoot')) {
- $root = get_class($facade::getFacadeRoot());
- } else {
- $root = $facade;
- }
-
- //If it doesn't exist, skip it
- if (!class_exists($root) && !interface_exists($root)) {
- return;
- }
-
- $this->root = $root;
-
- //When the database connection is not set, some classes will be skipped
- } catch (\PDOException $e) {
- $this->error(
- "PDOException: " . $e->getMessage() . "\nPlease configure your database connection correctly, or use the sqlite memory driver (-M). Skipping $facade."
- );
- } catch (\Exception $e) {
- $this->error("Exception: " . $e->getMessage() . "\nSkipping $facade.");
- }
- }
-
- /**
- * Detect if this class is a trait or not.
- *
- * @return bool
- */
- protected function isTrait()
- {
- // Check if the facade is not a Trait
- if (function_exists('trait_exists') && trait_exists($this->facade)) {
- return true;
- }
- return false;
- }
-
- /**
- * Add magic methods, as defined in the configuration files
- */
- protected function addMagicMethods()
- {
- foreach($this->magicMethods as $magic => $real){
- list($className, $name) = explode('::', $real);
- if(!class_exists($className) && !interface_exists($className)){
- continue;
- }
- $method = new \ReflectionMethod($className, $name);
- $class = new \ReflectionClass($className);
-
- if(!in_array($method->name, $this->usedMethods)){
- if($class !== $this->root){
- $this->methods[] = new Method($method, $this->alias, $class, $magic, $this->interfaces);
- }
- $this->usedMethods[] = $magic;
- }
- }
- }
-
- /**
- * Get the methods for one or multiple classes.
- *
- * @return string
- */
- protected function detectMethods()
- {
-
- foreach ($this->classes as $class) {
- $reflection = new \ReflectionClass($class);
-
- $methods = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC);
- if ($methods) {
- foreach ($methods as $method) {
- if (!in_array($method->name, $this->usedMethods)) {
- // Only add the methods to the output when the root is not the same as the class.
- // And don't add the __*() methods
- if ($this->extends !== $class && substr($method->name, 0, 2) !== '__') {
- $this->methods[] = new Method($method, $this->alias, $reflection, $method->name, $this->interfaces);
- }
- $this->usedMethods[] = $method->name;
- }
- }
- }
- }
- }
-
- /**
- * Output an error.
- *
- * @param string $string
- * @return void
- */
- protected function error($string)
- {
- echo $string . "\r\n";
- }
-}
+
+ * @copyright 2014 Barry vd. Heuvel / 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;
+
+class Alias
+{
+ protected $alias;
+ protected $facade;
+ protected $extends = null;
+ protected $classType = 'class';
+ protected $short;
+ protected $namespace = '__root';
+ protected $root = null;
+ protected $classes = array();
+ protected $methods = array();
+ protected $usedMethods = array();
+ protected $valid = false;
+ protected $magicMethods = array();
+ protected $interfaces = array();
+
+ /**
+ * @param string $alias
+ * @param string $facade
+ * @param array $magicMethods
+ * @param array $interfaces
+ */
+ public function __construct($alias, $facade, $magicMethods = array(), $interfaces = array())
+ {
+ $this->alias = $alias;
+ $this->magicMethods = $magicMethods;
+ $this->interfaces = $interfaces;
+
+ // Make the class absolute
+ $facade = '\\' . ltrim($facade, '\\');
+ $this->facade = $facade;
+
+ $this->detectRoot();
+
+ if ((!$this->isTrait() && $this->root)) {
+ $this->valid = true;
+ } else {
+ return;
+ }
+
+ $this->addClass($this->root);
+ $this->detectNamespace();
+ $this->detectClassType();
+
+ if ($facade === '\Illuminate\Database\Eloquent\Model') {
+ $this->usedMethods = array('decrement', 'increment');
+ }
+ }
+
+ /**
+ * Add one or more classes to analyze
+ *
+ * @param array|string $classes
+ */
+ public function addClass($classes)
+ {
+ $classes = (array)$classes;
+ foreach ($classes as $class) {
+ if (class_exists($class) || interface_exists($class)) {
+ $this->classes[] = $class;
+ } else {
+ $this->error('Class not exists: ' . $class);
+ }
+ }
+ }
+
+ /**
+ * Check if this class is valid to process.
+ * @return bool
+ */
+ public function isValid()
+ {
+ return $this->valid;
+ }
+
+ /**
+ * Get the classType, 'interface' or 'class'
+ *
+ * @return string
+ */
+ public function getClassType()
+ {
+ return $this->classType;
+ }
+
+ /**
+ * Get the class which this alias extends
+ *
+ * @return null|string
+ */
+ public function getExtends()
+ {
+ return $this->extends;
+ }
+
+ /**
+ * Get the Alias by which this class is called
+ *
+ * @return string
+ */
+ public function getAlias()
+ {
+ return $this->alias;
+ }
+
+ /**
+ * Return the short name (without namespace)
+ *
+ * @return string
+ */
+ public function getShortName()
+ {
+ return $this->short;
+ }
+
+ /**
+ * Get the namespace from the alias
+ *
+ * @return string
+ */
+ public function getNamespace()
+ {
+ return $this->namespace;
+ }
+
+ /**
+ * Get the methods found by this Alias
+ *
+ * @return array|Method[]
+ */
+ public function getMethods()
+ {
+ $this->addMagicMethods();
+ $this->detectMethods();
+ return $this->methods;
+ }
+
+ /**
+ * Detect the namespace
+ */
+ protected function detectNamespace()
+ {
+ if (strpos($this->alias, '\\')) {
+ $nsParts = explode('\\', $this->alias);
+ $this->short = array_pop($nsParts);
+ $this->namespace = implode('\\', $nsParts);
+ } else {
+ $this->short = $this->alias;
+ }
+ }
+
+ /**
+ * Detect the class type
+ */
+ protected function detectClassType()
+ {
+ //Some classes extend the facade
+ if (interface_exists($this->facade)) {
+ $this->classType = 'interface';
+ $this->extends = $this->facade;
+ } else {
+ $this->classType = 'class';
+ if (class_exists($this->facade)) {
+ $this->extends = $this->facade;
+ }
+ }
+ }
+
+ /**
+ * Get the real root of a facade
+ *
+ * @return bool|string
+ */
+ protected function detectRoot()
+ {
+ $facade = $this->facade;
+
+ try {
+ //If possible, get the facade root
+ if (method_exists($facade, 'getFacadeRoot')) {
+ $root = get_class($facade::getFacadeRoot());
+ } else {
+ $root = $facade;
+ }
+
+ //If it doesn't exist, skip it
+ if (!class_exists($root) && !interface_exists($root)) {
+ return;
+ }
+
+ $this->root = $root;
+
+ //When the database connection is not set, some classes will be skipped
+ } catch (\PDOException $e) {
+ $this->error(
+ 'PDOException: ' . $e->getMessage() . "\nPlease configure your database connection correctly, or use the sqlite memory driver (-M). Skipping $facade."
+ );
+ } catch (\Exception $e) {
+ $this->error('Exception: ' . $e->getMessage() . "\nSkipping $facade.");
+ }
+ }
+
+ /**
+ * Detect if this class is a trait or not.
+ *
+ * @return bool
+ */
+ protected function isTrait()
+ {
+ // Check if the facade is not a Trait
+ if (function_exists('trait_exists') && trait_exists($this->facade)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Add magic methods, as defined in the configuration files
+ */
+ protected function addMagicMethods()
+ {
+ foreach ($this->magicMethods as $magic => $real) {
+ list($className, $name) = explode('::', $real);
+ if (!class_exists($className) && !interface_exists($className)) {
+ continue;
+ }
+ $method = new \ReflectionMethod($className, $name);
+ $class = new \ReflectionClass($className);
+
+ if (!in_array($method->name, $this->usedMethods)) {
+ if ($class !== $this->root) {
+ $this->methods[] = new Method($method, $this->alias, $class, $magic, $this->interfaces);
+ }
+ $this->usedMethods[] = $magic;
+ }
+ }
+ }
+
+ /**
+ * Get the methods for one or multiple classes.
+ *
+ * @return string
+ */
+ protected function detectMethods()
+ {
+ foreach ($this->classes as $class) {
+ $reflection = new \ReflectionClass($class);
+
+ $methods = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC);
+ if ($methods) {
+ foreach ($methods as $method) {
+ if (!in_array($method->name, $this->usedMethods)) {
+ // Only add the methods to the output when the root is not the same as the class.
+ // And don't add the __*() methods
+ if ($this->extends !== $class && substr($method->name, 0, 2) !== '__') {
+ $this->methods[] = new Method($method, $this->alias, $reflection, $method->name, $this->interfaces);
+ }
+ $this->usedMethods[] = $method->name;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Output an error.
+ *
+ * @param string $string
+ * @return void
+ */
+ protected function error($string)
+ {
+ echo $string . "\r\n";
+ }
+}
diff --git a/src/Console/GeneratorCommand.php b/src/Console/GeneratorCommand.php
index e1a9477..cc19df5 100644
--- a/src/Console/GeneratorCommand.php
+++ b/src/Console/GeneratorCommand.php
@@ -17,7 +17,6 @@ use Illuminate\Filesystem\Filesystem;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
-
/**
* A command to generate autocomplete information for your IDE
*
@@ -27,16 +26,12 @@ class GeneratorCommand extends Command
{
/**
- * The console command name.
- *
- * @var string
+ * {@inheritdoc}
*/
protected $name = 'ide-helper:generate';
/**
- * The console command description.
- *
- * @var string
+ * {@inheritdoc}
*/
protected $description = 'Generate a new IDE Helper file.';
@@ -51,18 +46,14 @@ class GeneratorCommand extends Command
protected $onlyExtend;
-
/**
+ * {@inheritdoc}
*
* @param \Illuminate\Config\Repository $config
* @param \Illuminate\Filesystem\Filesystem $files
* @param \Illuminate\View\Factory $view
*/
- public function __construct(
- ConfigRepository $config,
- Filesystem $files, /* Illuminate\View\Factory */
- $view
- ) {
+ public function __construct(ConfigRepository $config, Filesystem $files, $view) {
$this->config = $config;
$this->files = $files;
$this->view = $view;
@@ -95,7 +86,6 @@ class GeneratorCommand extends Command
$this->useMemoryDriver();
}
-
$helpers = '';
if ($this->option('helpers') || ($this->config->get('laravel-ide-helper::include_helpers'))) {
foreach ($this->config->get('laravel-ide-helper::helper_files', array()) as $helper) {
@@ -133,9 +123,7 @@ class GeneratorCommand extends Command
}
/**
- * Get the console command arguments.
- *
- * @return array
+ * {@inheritdoc}
*/
protected function getArguments()
{
@@ -149,19 +137,17 @@ class GeneratorCommand extends Command
}
/**
- * Get the console command options.
- *
- * @return array
+ * {@inheritdoc}
*/
protected function getOptions()
{
$format = $this->config->get('laravel-ide-helper::format');
return array(
- array('format', "F", InputOption::VALUE_OPTIONAL, 'The format for the IDE Helper', $format),
- array('helpers', "H", InputOption::VALUE_NONE, 'Include the helper files'),
- array('memory', "M", InputOption::VALUE_NONE, 'Use sqlite memory driver'),
- array('sublime', "S", InputOption::VALUE_NONE, 'DEPRECATED: Use different style for SublimeText CodeIntel'),
+ array('format', 'F', InputOption::VALUE_OPTIONAL, 'The format for the IDE Helper', $format),
+ array('helpers', 'H', InputOption::VALUE_NONE, 'Include the helper files'),
+ array('memory', 'M', InputOption::VALUE_NONE, 'Use sqlite memory driver'),
+ array('sublime', 'S', InputOption::VALUE_NONE, 'DEPRECATED: Use different style for SublimeText CodeIntel'),
);
}
diff --git a/src/Console/MetaCommand.php b/src/Console/MetaCommand.php
index 23e29bb..1e36bf0 100644
--- a/src/Console/MetaCommand.php
+++ b/src/Console/MetaCommand.php
@@ -17,21 +17,18 @@ use Symfony\Component\Console\Input\InputOption;
* A command to generate phpstorm meta data
*
* @author Barry vd. Heuvel
+ * @property \Illuminate\Container\Container $laravel
*/
class MetaCommand extends Command {
/**
- * The console command name.
- *
- * @var string
+ * {@inheritdoc}
*/
protected $name = 'ide-helper:meta';
protected $filename = '.phpstorm.meta.php';
/**
- * The console command description.
- *
- * @var string
+ * {@inheritdoc}
*/
protected $description = 'Generate metadata for PhpStorm';
@@ -40,22 +37,25 @@ class MetaCommand extends Command {
/** @var \Illuminate\View\Factory */
protected $view;
-
+
protected $methods = array(
- '\Illuminate\Foundation\Application::make',
- '\Illuminate\Container\Container::make',
- '\App::make',
- 'app',
+ //'\Illuminate\Foundation\Application::make',
+ 'new \Illuminate\Container\Container',
+ '\Illuminate\Container\Container::make',
+ '\App::make',
+ 'app',
);
/**
+ * {@inheritdoc}
*
- * @param \Illuminate\Filesystem\Filesystem $files
- * @param \Illuminate\View\Factory $view
+ * @param \Illuminate\Container\Container $app
*/
- public function __construct($files, $view) {
- $this->files = $files;
- $this->view = $view;
+ public function __construct($app)
+ {
+ $this->laravel = $app;
+ $this->files = $app['files'];
+ $this->view = $app['view'];
parent::__construct();
}
@@ -66,23 +66,32 @@ class MetaCommand extends Command {
*/
public function fire()
{
- $bindings = array();
+ $bindings = array_flip($this->getAppAliases());
+ $exclude = $this->option('exclude');
+ if (!empty($exclude)) {
+ $exclude = '/' . str_replace('\|', '|', preg_quote($exclude, '/')) . '/';
+ }
+
foreach ($this->getAbstracts() as $abstract) {
+ if (!empty($exclude) && preg_match($exclude, $abstract))
+ continue;
+
try {
$concrete = $this->laravel->make($abstract);
if (is_object($concrete)) {
$bindings[$abstract] = get_class($concrete);
}
- }catch (\Exception $e) {
- $this->error("Cannot make $abstract: ".$e->getMessage());
+ } catch (\Exception $e) {
+ $this->error("Cannot make $abstract: " . $e->getMessage());
}
}
-
+ asort($bindings);
+
$content = $this->view->make('laravel-ide-helper::meta', array(
- 'bindings' => $bindings,
- 'methods' => $this->methods,
+ 'bindings' => $bindings,
+ 'methods' => $this->methods,
))->render();
-
+
$filename = $this->option('filename');
$written = $this->files->put($filename, $content);
@@ -92,10 +101,10 @@ class MetaCommand extends Command {
$this->error("The meta file could not be created at $filename");
}
}
-
+
/**
* Get a list of abstracts from the Laravel Application.
- *
+ *
* @return array
*/
protected function getAbstracts()
@@ -104,14 +113,28 @@ class MetaCommand extends Command {
}
/**
- * Get the console command options.
+ * Get a list of aliases from the Laravel Application.
*
* @return array
*/
+ protected function getAppAliases()
+ {
+ static $aliasProp;
+ if (!isset($aliasProp)) {
+ $aliasProp = new \ReflectionProperty('Illuminate\Container\Container', 'aliases');
+ $aliasProp->setAccessible(true);
+ }
+ return $aliasProp->getValue($this->laravel);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
protected function getOptions()
{
return array(
array('filename', 'F', InputOption::VALUE_OPTIONAL, 'The path to the meta file', $this->filename),
+ array('exclude', 'E', InputOption::VALUE_OPTIONAL, 'Laravel bindings to exclude (e.g. "bar.|.foo")'),
);
}
}
diff --git a/src/Console/ModelsCommand.php b/src/Console/ModelsCommand.php
index 1100e58..a9f1e40 100644
--- a/src/Console/ModelsCommand.php
+++ b/src/Console/ModelsCommand.php
@@ -15,31 +15,27 @@ use Illuminate\Support\Str;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\ClassLoader\ClassMapGenerator;
-use Barryvdh\Reflection\DocBlock;
-use Barryvdh\Reflection\DocBlock\Context;
-use Barryvdh\Reflection\DocBlock\Tag;
-use Barryvdh\Reflection\DocBlock\Serializer as DocBlockSerializer;
+use phpDocumentor\Reflection\DocBlock;
+use phpDocumentor\Reflection\DocBlock\Context;
+use phpDocumentor\Reflection\DocBlock\Tag;
/**
* A command to generate autocomplete information for your IDE
*
* @author Barry vd. Heuvel
+ * @property \Illuminate\Container\Container $laravel
*/
class ModelsCommand extends Command
{
/**
- * The console command name.
- *
- * @var string
+ * {@inheritdoc}
*/
protected $name = 'ide-helper:models';
protected $filename = '_ide_helper_models.php';
/**
- * The console command description.
- *
- * @var string
+ * {@inheritdoc}
*/
protected $description = 'Generate autocompletion for models';
@@ -49,6 +45,20 @@ class ModelsCommand extends Command
protected $dirs = array();
protected $reset;
+ /** @var \Illuminate\Filesystem\Filesystem */
+ protected $files;
+
+ /**
+ * {@inheritdoc}
+ *
+ * @param \Illuminate\Container\Container $app
+ */
+ public function __construct($app)
+ {
+ $this->laravel = $app;
+ $this->files = $app['files'];
+ parent::__construct();
+ }
/**
* Execute the console command.
@@ -69,10 +79,7 @@ class ModelsCommand extends Command
//If filename is default and Write is not specified, ask what to do
if (!$this->write && $filename === $this->filename && !$this->option('nowrite')) {
- if ($this->confirm(
- "Do you want to overwrite the existing model files? Choose no to write to $filename instead? (Yes/No): "
- )
- ) {
+ if ($this->confirm("Do you want to overwrite the existing model files? Choose no to write to $filename instead? (Yes/No): ")) {
$this->write = true;
}
}
@@ -80,7 +87,7 @@ class ModelsCommand extends Command
$content = $this->generateDocs($model, $ignore);
if (!$this->write) {
- $written = \File::put($filename, $content);
+ $written = $this->files->put($filename, $content);
if ($written !== false) {
$this->info("Model information was written to $filename");
} else {
@@ -89,11 +96,8 @@ class ModelsCommand extends Command
}
}
-
/**
- * Get the console command arguments.
- *
- * @return array
+ * {@inheritdoc}
*/
protected function getArguments()
{
@@ -103,9 +107,7 @@ class ModelsCommand extends Command
}
/**
- * Get the console command options.
- *
- * @return array
+ * {@inheritdoc}
*/
protected function getOptions()
{
@@ -121,8 +123,6 @@ class ModelsCommand extends Command
protected function generateDocs($loadModels, $ignore = '')
{
-
-
$output = "comment("Loading model '$name'");
- if (!$reflectionClass->IsInstantiable()) {
+ if (!$reflectionClass->isInstantiable()) {
throw new \Exception($name . ' is not instantiable.');
}
@@ -177,7 +177,7 @@ class ModelsCommand extends Command
$this->getPropertiesFromMethods($model);
$output .= $this->createPhpDocs($name);
} catch (\Exception $e) {
- $this->error("Exception: " . $e->getMessage() . "\nCould not analyze class $name.");
+ $this->error('Exception: ' . $e->getMessage() . "\nCould not analyze class $name.");
}
}
@@ -190,10 +190,8 @@ class ModelsCommand extends Command
}
return $output;
-
}
-
protected function loadModels()
{
$models = array();
@@ -259,7 +257,7 @@ class ModelsCommand extends Command
$comment = $column->getComment();
$this->setProperty($name, $type, true, true, $comment);
$this->setMethod(
- Str::camel("where_" . $name),
+ Str::camel('where_' . $name),
'\Illuminate\Database\Query\Builder|\\' . get_class($model),
array('$value')
);
@@ -275,21 +273,13 @@ class ModelsCommand extends Command
$methods = get_class_methods($model);
if ($methods) {
foreach ($methods as $method) {
- if (Str::startsWith($method, 'get') && Str::endsWith(
- $method,
- 'Attribute'
- ) && $method !== 'getAttribute'
- ) {
+ if (Str::startsWith($method, 'get') && Str::endsWith($method, 'Attribute') && $method !== 'getAttribute') {
//Magic getAttribute
$name = Str::snake(substr($method, 3, -9));
if (!empty($name)) {
$this->setProperty($name, null, true, null);
}
- } elseif (Str::startsWith($method, 'set') && Str::endsWith(
- $method,
- 'Attribute'
- ) && $method !== 'setAttribute'
- ) {
+ } elseif (Str::startsWith($method, 'set') && Str::endsWith($method, 'Attribute') && $method !== 'setAttribute') {
//Magic setAttribute
$name = Str::snake(substr($method, 3, -9));
if (!empty($name)) {
@@ -321,22 +311,14 @@ class ModelsCommand extends Command
$begin = strpos($code, 'function(');
$code = substr($code, $begin, strrpos($code, '}') - $begin + 1);
- foreach (array(
- 'hasMany',
- 'belongsToMany',
- 'hasOne',
- 'belongsTo',
- 'morphTo',
- 'morphMany',
- 'morphToMany'
- ) as $relation) {
+ foreach (array('hasMany', 'belongsToMany', 'hasOne', 'belongsTo', 'morphTo', 'morphMany', 'morphToMany') as $relation) {
$search = '$this->' . $relation . '(';
if ($pos = stripos($code, $search)) {
$code = substr($code, $pos + strlen($search));
$arguments = explode(',', substr($code, 0, strpos($code, ');')));
//Remove quotes, ensure 1 \ in front of the model
$returnModel = $this->getClassName($arguments[0], $model);
- if ($relation === "belongsToMany" or $relation === 'hasMany' or $relation === 'morphMany' or $relation === 'morphToMany') {
+ if ($relation === 'belongsToMany' or $relation === 'hasMany' or $relation === 'morphMany' or $relation === 'morphToMany') {
//Collection or array of models (because Collection is Arrayable)
$this->setProperty(
$method,
@@ -363,14 +345,14 @@ class ModelsCommand extends Command
* @param bool|null $write
* @param string|null $comment
*/
- protected function setProperty($name, $type = null, $read = null, $write = null, $comment='')
+ protected function setProperty($name, $type = null, $read = null, $write = null, $comment = '')
{
if (!isset($this->properties[$name])) {
$this->properties[$name] = array();
$this->properties[$name]['type'] = 'mixed';
$this->properties[$name]['read'] = false;
$this->properties[$name]['write'] = false;
- $this->properties[$name]['comment'] = (string) $comment;
+ $this->properties[$name]['comment'] = (string)$comment;
}
if ($type !== null) {
$this->properties[$name]['type'] = $type;
@@ -398,10 +380,9 @@ class ModelsCommand extends Command
*/
protected function createPhpDocs($class)
{
-
$reflection = new \ReflectionClass($class);
$namespace = $reflection->getNamespaceName();
- $classname = $reflection->getShortName();
+ $className = $reflection->getShortName();
$originalDoc = $reflection->getDocComment();
if ($this->reset) {
@@ -417,10 +398,11 @@ class ModelsCommand extends Command
$properties = array();
$methods = array();
foreach ($phpdoc->getTags() as $tag) {
+ /* @var Tag|Tag\PropertyTag|Tag\MethodTag $tag */
$name = $tag->getName();
- if ($name == "property" || $name == "property-read" || $name == "property-write") {
+ if ($name == 'property' || $name == 'property-read' || $name == 'property-write') {
$properties[] = $tag->getVariableName();
- } elseif ($name == "method") {
+ } elseif ($name == 'method') {
$methods[] = $tag->getMethodName();
}
}
@@ -450,47 +432,46 @@ class ModelsCommand extends Command
$phpdoc->appendTag($tag);
}
- $serializer = new DocBlockSerializer();
+ $serializer = new DocBlock\Serializer();
$serializer->getDocComment($phpdoc);
$docComment = $serializer->getDocComment($phpdoc);
-
if ($this->write) {
$filename = $reflection->getFileName();
- $contents = \File::get($filename);
+ $contents = $this->files->get($filename);
if ($originalDoc) {
$contents = str_replace($originalDoc, $docComment, $contents);
} else {
- $needle = "class {$classname}";
- $replace = "{$docComment}\nclass {$classname}";
+ $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)) {
+ if ($this->files->put($filename, $contents)) {
$this->info('Written new phpDocBlock to ' . $filename);
}
}
- $output = "namespace {$namespace}{\n{$docComment}\n\tclass {$classname} {}\n}\n\n";
+ $output = "namespace {$namespace}{\n{$docComment}\n\tclass {$className} {}\n}\n\n";
return $output;
}
/**
* Get the parameters and format them correctly
*
- * @param $method
+ * @param \ReflectionMethod $method
* @return array
*/
public function getParameters($method)
{
- //Loop through the default values for paremeters, and make the correct output string
- $params = array();
+ //Loop through the default values for parameters, and make the correct output string
$paramsWithDefault = array();
+
foreach ($method->getParameters() as $param) {
$paramStr = '$' . $param->getName();
- $params[] = $paramStr;
+
if ($param->isOptional()) {
$default = $param->getDefaultValue();
if (is_bool($default)) {
@@ -508,6 +489,7 @@ class ModelsCommand extends Command
}
$paramsWithDefault[] = $paramStr;
}
+
return $paramsWithDefault;
}
@@ -529,6 +511,6 @@ class ModelsCommand extends Command
return substr($className, 0, $end);
}
- return "\\" . ltrim(trim($className, " \"'"), "\\") ;
+ return '\\' . ltrim(trim($className, ' "\''), '\\');
}
}
diff --git a/src/Generator.php b/src/Generator.php
index 74d8fd8..39e2bf5 100644
--- a/src/Generator.php
+++ b/src/Generator.php
@@ -1,235 +1,245 @@
-
- * @copyright 2014 Barry vd. Heuvel / 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;
-
-use Illuminate\Foundation\AliasLoader;
-use Illuminate\Config\Repository as ConfigRepository;
-use Symfony\Component\Console\Output\OutputInterface;
-
-class Generator
-{
- /** @var \Illuminate\Config\Repository */
- protected $config;
-
- /** @var \Illuminate\View\Factory */
- protected $view;
-
- /** @var \Symfony\Component\Console\Output\OutputInterface */
- protected $output;
-
- protected $extra = array();
- protected $magic = array();
- protected $interfaces = array();
- protected $helpers;
-
- /**
- * @param \Illuminate\Config\Repository $config
- * @param \Illuminate\View\Factory $view
- * @param \Symfony\Component\Console\Output\OutputInterface $output
- * @param string $helpers
- */
- public function __construct(ConfigRepository $config,
- /* Illuminate\View\Factory */ $view,
- OutputInterface $output = null,
- $helpers = ''
- ) {
- $this->config = $config;
- $this->view = $view;
-
- // Find the drivers to add to the extra/interfaces
- $this->detectDrivers();
-
- $this->extra = array_merge($this->extra, $this->config->get('laravel-ide-helper::extra'));
- $this->magic = array_merge($this->magic, $this->config->get('laravel-ide-helper::magic'));
- $this->interfaces = array_merge($this->interfaces, $this->config->get('laravel-ide-helper::interfaces'));
- // Make all interface classes absolute
- foreach ($this->interfaces as &$interface) {
- $interface = '\\' . ltrim($interface, '\\');
- }
- $this->helpers = $helpers;
- }
-
- /**
- * Generate the helper file contents;
- *
- * @param string $format The format to generate the helper in (php/json)
- * @return string;
- */
- public function generate($format = 'php')
- {
- // Check if the generator for this format exists
- $method = 'generate'.ucfirst($format).'Helper';
- if (method_exists($this, $method)) {
- return $this->$method();
- }
-
- return $this->generatePhpHelper();
- }
-
- public function generatePhpHelper()
- {
- $app = app();
- return $this->view->make('laravel-ide-helper::ide-helper')
- ->with('namespaces', $this->getNamespaces())
- ->with('helpers', $this->helpers)
- ->with('version', $app::VERSION)
- ->render();
- }
-
- public function generateJsonHelper()
- {
- $classes = array();
- foreach ($this->getNamespaces() as $aliases) {
- foreach($aliases as $alias) {
- $functions = array();
- foreach ($alias->getMethods() as $method) {
- $functions[$method->getName()] = '('. $method->getParamsWithDefault().')';
- }
- $classes[$alias->getAlias()] = array(
- 'functions' => $functions,
- );
- }
- }
-
- $flags = JSON_FORCE_OBJECT;
- if (defined('JSON_PRETTY_PRINT')) {
- $flags |= JSON_PRETTY_PRINT;
- }
-
- return json_encode(array(
- 'php' => array(
- 'classes' => $classes,
- ),
- ), $flags);
- }
-
- protected function detectDrivers()
- {
- try{
+
+ * @copyright 2014 Barry vd. Heuvel / 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;
+
+use /** @noinspection PhpUndefinedNamespaceInspection,PhpUndefinedClassInspection */Illuminate\Foundation\AliasLoader;
+use Illuminate\Config\Repository as ConfigRepository;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class Generator
+{
+ /** @var \Illuminate\Config\Repository */
+ protected $config;
+
+ /** @var \Illuminate\View\Factory */
+ protected $view;
+
+ /** @var \Symfony\Component\Console\Output\OutputInterface */
+ protected $output;
+
+ protected $extra = array();
+ protected $magic = array();
+ protected $interfaces = array();
+ protected $helpers;
+
+ /**
+ * @param \Illuminate\Config\Repository $config
+ * @param \Illuminate\View\Factory $view
+ * @param \Symfony\Component\Console\Output\OutputInterface $output
+ * @param string $helpers
+ */
+ public function __construct(ConfigRepository $config, $view, OutputInterface $output = null, $helpers = '')
+ {
+ $this->config = $config;
+ $this->view = $view;
+
+ // Find the drivers to add to the extra/interfaces
+ $this->detectDrivers();
+
+ $this->extra = array_merge($this->extra, $this->config->get('laravel-ide-helper::extra'));
+ $this->magic = array_merge($this->magic, $this->config->get('laravel-ide-helper::magic'));
+ $this->interfaces = array_merge($this->interfaces, $this->config->get('laravel-ide-helper::interfaces'));
+
+ // Make all interface classes absolute
+ foreach ($this->interfaces as &$interface) {
+ $interface = '\\' . ltrim($interface, '\\');
+ }
+ $this->helpers = $helpers;
+ }
+
+ /**
+ * Generate the helper file contents;
+ *
+ * @param string $format The format to generate the helper in (php/json)
+ * @return string;
+ */
+ public function generate($format = 'php')
+ {
+ // Check if the generator for this format exists
+ $method = 'generate' . ucfirst($format) . 'Helper';
+ if (method_exists($this, $method)) {
+ return $this->$method();
+ }
+
+ return $this->generatePhpHelper();
+ }
+
+ public function generatePhpHelper()
+ {
+ $app = app();
+ return $this->view->make('laravel-ide-helper::ide-helper')
+ ->with('namespaces', $this->getNamespaces())
+ ->with('helpers', $this->helpers)
+ ->with('version', $app::VERSION)
+ ->render();
+ }
+
+ public function generateJsonHelper()
+ {
+ $classes = array();
+ foreach ($this->getNamespaces() as $aliases) {
+ foreach ($aliases as $alias) {
+ $functions = array();
+ foreach ($alias->getMethods() as $method) {
+ $functions[$method->getName()] = '(' . $method->getParamsWithDefault() . ')';
+ }
+ $classes[$alias->getAlias()] = array(
+ 'functions' => $functions,
+ );
+ }
+ }
+
+ $flags = JSON_FORCE_OBJECT;
+ if (defined('JSON_PRETTY_PRINT')) {
+ $flags |= JSON_PRETTY_PRINT;
+ }
+
+ return json_encode(array(
+ 'php' => array(
+ 'classes' => $classes,
+ ),
+ ), $flags);
+ }
+
+ protected function detectDrivers()
+ {
+ try {
if (class_exists('Auth') && is_a('Auth', '\Illuminate\Support\Facades\Auth', true)) {
- $class = get_class(\Auth::driver());
- $this->extra['Auth'] = array($class);
- $this->interfaces['\Illuminate\Auth\UserProviderInterface'] = $class;
- }
- }catch (\Exception $e) {}
-
- try{
- if (class_exists('DB') && is_a('DB', '\Illuminate\Support\Facades\DB', true)) {
- $class = get_class(\DB::connection());
- $this->extra['DB'] = array($class);
- $this->interfaces['\Illuminate\Database\ConnectionInterface'] = $class;
- }
- }catch (\Exception $e) {}
-
- try{
- if (class_exists('Cache') && is_a('Cache', '\Illuminate\Support\Facades\Cache', true)) {
- $driver = get_class(\Cache::driver());
- $store = get_class(\Cache::getStore());
- $this->extra['Cache'] = array($driver, $store);
- $this->interfaces['\Illuminate\Cache\StoreInterface'] = $store;
- }
- }catch (\Exception $e) {}
-
- try{
- if (class_exists('Queue') && is_a('Queue', '\Illuminate\Support\Facades\Queue', true)) {
- $class = get_class(\Queue::connection());
- $this->extra['Queue'] = array($class);
- $this->interfaces['\Illuminate\Queue\QueueInterface'] = $class;
- }
- }catch (\Exception $e) {}
-
- try{
- if (class_exists('SSH') && is_a('SSH', '\Illuminate\Support\Facades\SSH', true)){
- $class = get_class(\SSH::connection());
- $this->extra['SSH'] = array($class);
- $this->interfaces['\Illuminate\Remote\ConnectionInterface'] = $class;
- }
- }catch (\Exception $e) {}
-
- }
-
- /**
- * Find all namespaces/aliases that are valid for us to render
- *
- * @return array
- */
- protected function getNamespaces()
- {
- $namespaces = array();
-
- // Get all aliases
- foreach (AliasLoader::getInstance()->getAliases() as $name => $facade) {
- $magicMethods = array_key_exists($name, $this->magic) ? $this->magic[$name] : array();
- $alias = new Alias($name, $facade, $magicMethods, $this->interfaces);
- if ($alias->isValid()) {
-
- //Add extra methods, from other classes (magic static calls)
- if (array_key_exists($name, $this->extra)) {
- $alias->addClass($this->extra[$name]);
- }
-
- $namespace = $alias->getNamespace();
- if (!isset($namespaces[$namespace])) {
- $namespaces[$namespace] = array();
- }
- $namespaces[$namespace][] = $alias;
- }
-
- }
-
- return $namespaces;
- }
-
- /**
- * Get the driver/connection/store from the managers
- *
- * @param $alias
- * @return array|bool|string
- */
- public function getDriver($alias)
- {
- try {
- if ($alias == "Auth") {
- $driver = \Auth::driver();
- } elseif ($alias == "DB") {
- $driver = \DB::connection();
- } elseif ($alias == "Cache") {
- $driver = get_class(\Cache::driver());
- $store = get_class(\Cache::getStore());
- return array($driver, $store);
- } elseif ($alias == "Queue") {
- $driver = \Queue::connection();
- } else {
- return false;
- }
-
- return get_class($driver);
- } catch (\Exception $e) {
- $this->error("Could not determine driver/connection for $alias.");
- return false;
- }
- }
-
- /**
- * Write a string as error output.
- *
- * @param string $string
- * @return void
- */
- protected function error($string)
- {
- if($this->output){
- $this->output->writeln("$string");
- }else{
- echo $string . "\r\n";
- }
- }
-}
+ /** @noinspection PhpUndefinedClassInspection */
+ $class = get_class(\Auth::driver());
+ $this->extra['Auth'] = array($class);
+ $this->interfaces['\Illuminate\Auth\UserProviderInterface'] = $class;
+ }
+ } catch (\Exception $e) {}
+
+ try {
+ if (class_exists('DB') && is_a('DB', '\Illuminate\Support\Facades\DB', true)) {
+ /** @noinspection PhpUndefinedClassInspection */
+ $class = get_class(\DB::connection());
+ $this->extra['DB'] = array($class);
+ $this->interfaces['\Illuminate\Database\ConnectionInterface'] = $class;
+ }
+ } catch (\Exception $e) {}
+
+ try {
+ if (class_exists('Cache') && is_a('Cache', '\Illuminate\Support\Facades\Cache', true)) {
+ /** @noinspection PhpUndefinedClassInspection */
+ $driver = get_class(\Cache::driver());
+ /** @noinspection PhpUndefinedClassInspection */
+ $store = get_class(\Cache::getStore());
+ $this->extra['Cache'] = array($driver, $store);
+ $this->interfaces['\Illuminate\Cache\StoreInterface'] = $store;
+ }
+ } catch (\Exception $e) {}
+
+ try {
+ if (class_exists('Queue') && is_a('Queue', '\Illuminate\Support\Facades\Queue', true)) {
+ /** @noinspection PhpUndefinedClassInspection */
+ $class = get_class(\Queue::connection());
+ $this->extra['Queue'] = array($class);
+ $this->interfaces['\Illuminate\Queue\QueueInterface'] = $class;
+ }
+ } catch (\Exception $e) {}
+
+ try {
+ if (class_exists('SSH') && is_a('SSH', '\Illuminate\Support\Facades\SSH', true)) {
+ /** @noinspection PhpUndefinedClassInspection */
+ $class = get_class(\SSH::connection());
+ $this->extra['SSH'] = array($class);
+ $this->interfaces['\Illuminate\Remote\ConnectionInterface'] = $class;
+ }
+ } catch (\Exception $e) {}
+
+ }
+
+ /**
+ * Find all namespaces/aliases that are valid for us to render
+ *
+ * @return array|Alias[][]
+ */
+ protected function getNamespaces()
+ {
+ $namespaces = array();
+
+ // Get all aliases
+ /** @noinspection PhpUndefinedClassInspection */
+ foreach (AliasLoader::getInstance()->getAliases() as $name => $facade) {
+ $magicMethods = array_key_exists($name, $this->magic) ? $this->magic[$name] : array();
+ $alias = new Alias($name, $facade, $magicMethods, $this->interfaces);
+ if ($alias->isValid()) {
+
+ //Add extra methods, from other classes (magic static calls)
+ if (array_key_exists($name, $this->extra)) {
+ $alias->addClass($this->extra[$name]);
+ }
+
+ $namespace = $alias->getNamespace();
+ if (!isset($namespaces[$namespace])) {
+ $namespaces[$namespace] = array();
+ }
+ $namespaces[$namespace][] = $alias;
+ }
+
+ }
+
+ return $namespaces;
+ }
+
+ /**
+ * Get the driver/connection/store from the managers
+ *
+ * @param $alias
+ * @return array|bool|string
+ */
+ public function getDriver($alias)
+ {
+ try {
+ if ($alias == 'Auth') {
+ /** @noinspection PhpUndefinedClassInspection */
+ $driver = \Auth::driver();
+ } elseif ($alias == 'DB') {
+ /** @noinspection PhpUndefinedClassInspection */
+ $driver = \DB::connection();
+ } elseif ($alias == 'Cache') {
+ /** @noinspection PhpUndefinedClassInspection */
+ $driver = get_class(\Cache::driver());
+ /** @noinspection PhpUndefinedClassInspection */
+ $store = get_class(\Cache::getStore());
+ return array($driver, $store);
+ } elseif ($alias == 'Queue') {
+ /** @noinspection PhpUndefinedClassInspection */
+ $driver = \Queue::connection();
+ } else {
+ return false;
+ }
+
+ return get_class($driver);
+ } catch (\Exception $e) {
+ $this->error("Could not determine driver/connection for $alias.");
+ return false;
+ }
+ }
+
+ /**
+ * Write a string as error output.
+ *
+ * @param string $string
+ * @return void
+ */
+ protected function error($string)
+ {
+ if ($this->output) {
+ $this->output->writeln("$string");
+ } else {
+ echo $string . "\r\n";
+ }
+ }
+}
diff --git a/src/IdeHelperServiceProvider.php b/src/IdeHelperServiceProvider.php
index ceace1e..7d70d5d 100644
--- a/src/IdeHelperServiceProvider.php
+++ b/src/IdeHelperServiceProvider.php
@@ -15,20 +15,19 @@ use Barryvdh\LaravelIdeHelper\Console\MetaCommand;
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
use Barryvdh\LaravelIdeHelper\Console\GeneratorCommand;
+/**
+ * @property \Illuminate\Container\Container $app
+ */
class IdeHelperServiceProvider extends ServiceProvider
{
/**
- * Indicates if loading of the provider is deferred.
- *
- * @var bool
+ * {@inheritdoc}
*/
protected $defer = true;
/**
- * Bootstrap the application events.
- *
- * @return void
+ * {@inheritdoc}
*/
public function boot()
{
@@ -36,9 +35,7 @@ class IdeHelperServiceProvider extends ServiceProvider
}
/**
- * Register the service provider.
- *
- * @return void
+ * {@inheritdoc}
*/
public function register()
{
@@ -49,60 +46,34 @@ class IdeHelperServiceProvider extends ServiceProvider
);
$this->app['command.ide-helper.models'] = $this->app->share(
- function () {
- return new ModelsCommand();
+ function ($app) {
+ return new ModelsCommand($app);
}
);
-
+
$this->app['command.ide-helper.meta'] = $this->app->share(
- function ($app) {
- return new MetaCommand($app['files'], $app['view']);
- }
+ function ($app) {
+ return new MetaCommand($app);
+ }
);
$this->commands('command.ide-helper.generate', 'command.ide-helper.models', 'command.ide-helper.meta');
}
/**
- * Get the services provided by the provider.
- *
- * @return array
+ * {@inheritdoc}
*/
public function provides()
{
- return array('command.ide-helper.generate', 'command.ide-helper.models');
+ return array('command.ide-helper.generate', 'command.ide-helper.models', 'command.ide-helper.meta');
}
-
+
/**
- * Register the package's component namespaces.
- *
- * @param string $package
- * @param string $namespace
- * @param string $path
- * @return void
+ * {@inheritdoc}
*/
- public function package($package, $namespace = null, $path = null)
+ protected function getAppViewPath($package, $namespace = null)
{
-
- // Is it possible to register the config?
- if (method_exists($this->app['config'], 'package')) {
- $this->app['config']->package($package, $path.'/config', $namespace);
- } else {
- // Load the config for now..
- $config = $this->app['files']->getRequire($path .'/config/config.php');
- foreach($config as $key => $value){
- $this->app['config']->set($namespace.'::'.$key, $value);
- }
- }
-
- // Register view files
- $appView = $this->app['path']."/views/packages/{$package}";
- if ($this->app['files']->isDirectory($appView))
- {
- $this->app['view']->addNamespace($namespace, $appView);
- }
-
- $this->app['view']->addNamespace($namespace, $path.'/views');
+ return $this->app['path'] . "/views/packages/{$package}";
}
}
diff --git a/src/Method.php b/src/Method.php
index be343e2..4b65ba6 100644
--- a/src/Method.php
+++ b/src/Method.php
@@ -1,311 +1,332 @@
-
- * @copyright 2014 Barry vd. Heuvel / 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;
-
-use Barryvdh\Reflection\DocBlock;
-use Barryvdh\Reflection\DocBlock\Context;
-use Barryvdh\Reflection\DocBlock\Tag;
-use Barryvdh\Reflection\DocBlock\Tag\ReturnTag;
-use Barryvdh\Reflection\DocBlock\Tag\ParamTag;
-use Barryvdh\Reflection\DocBlock\Serializer as DocBlockSerializer;
-
-class Method
-{
- /** @var \Barryvdh\Reflection\DocBlock */
- protected $phpdoc;
-
- /** @var \ReflectionMethod */
- protected $method;
-
- protected $output = '';
- protected $name;
- protected $namespace;
- protected $params = array();
- protected $params_with_default = array();
- protected $interfaces = array();
- protected $return = null;
-
- /**
- * @param \ReflectionMethod $method
- * @param string $alias
- * @param string $class
- * @param string|null $methodName
- * @param array $interfaces
- */
- public function __construct(\ReflectionMethod $method, $alias, $class, $methodName = null, $interfaces = array())
- {
- $this->method = $method;
- $this->interfaces = $interfaces;
- $this->name = $methodName ?: $method->name;
- $this->namespace = $method->getDeclaringClass()->getNamespaceName();
-
- //Create a DocBlock and serializer instance
- $this->phpdoc = new DocBlock($method, new Context($this->namespace));
-
- //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
- $declaringClass = $method->getDeclaringClass();
- $this->declaringClassName = '\\' . ltrim($declaringClass->name, '\\');
- $this->root = '\\' . ltrim($class->getName(), '\\');
- }
-
- /**
- * Get the class wherein the function resides
- *
- * @return string
- */
- public function getDeclaringClass()
- {
- return $this->declaringClassName;
- }
-
- /**
- * Return the class from which this function would be called
- *
- * @return string
- */
- public function getRoot()
- {
- return $this->root;
- }
-
- /**
- * Get the docblock for this method
- *
- * @param string $prefix
- * @return mixed
- */
- public function getDocComment($prefix = "\t\t")
- {
- $serializer = new DocBlockSerializer(1, $prefix);
- return $serializer->getDocComment($this->phpdoc);
- }
-
- /**
- * Get the method name
- *
- * @return string
- */
- public function getName()
- {
- return $this->name;
- }
-
- /**
- * Get the parameters for this method
- *
- * @param bool $implode Wether to implode the array or not
- * @return string
- */
- public function getParams($implode = true)
- {
- return $implode ? implode(', ', $this->params) : $this->params;
- }
-
- /**
- * Get the parameters for this method including default values
- *
- * @param bool $implode Wether to implode the array or not
- * @return string
- */
- public function getParamsWithDefault($implode = true)
- {
- return $implode ? implode(', ', $this->params_with_default) : $this->params_with_default;
- }
-
- /**
- * Get the description and get the inherited docs.
- *
- * @param DocBlock $phpdoc
- */
- protected function normalizeDescription(DocBlock $phpdoc)
- {
- //Get the short + long description from the DocBlock
- $description = $phpdoc->getText();
-
- //Loop through parents/interfaces, to fill in {@inheritdoc}
- if (strpos($description, '{@inheritdoc}') !== false) {
- $inheritdoc = $this->getInheritDoc($this->method);
- $inheritDescription = $inheritdoc->getText();
-
- $description = str_replace('{@inheritdoc}', $inheritDescription, $description);
- $phpdoc->setText($description);
-
- $this->normalizeParams($inheritdoc);
- $this->normalizeReturn($inheritdoc);
-
- //Add the tags that are inherited
- $inheritTags = $inheritdoc->getTags();
- if ($inheritTags) {
- /** @var Tag $tag */
- foreach ($inheritTags as $tag) {
- $tag->setDocBlock();
- $phpdoc->appendTag($tag);
- }
- }
- }
- }
-
- /**
- * Normalize the parameters
- *
- * @param DocBlock $phpdoc
- */
- protected function normalizeParams(DocBlock $phpdoc)
- {
- //Get the return type and adjust them for beter autocomplete
- $paramTags = $phpdoc->getTagsByName('param');
- if ($paramTags) {
- /** @var ParamTag $tag */
- foreach($paramTags as $tag){
- // Convert the keywords
- $content = $this->convertKeywords($tag->getContent());
- $tag->setContent($content);
-
- // Get the expanded type and re-set the content
- $content = $tag->getType() . ' ' . $tag->getVariableName() . ' ' . $tag->getDescription();
- $tag->setContent(trim($content));
- }
- }
- }
-
- /**
- * Normalize the return tag (make full namespace, replace interfaces)
- *
- * @param DocBlock $phpdoc
- */
- protected function normalizeReturn(DocBlock $phpdoc)
- {
- //Get the return type and adjust them for beter autocomplete
- $returnTags = $phpdoc->getTagsByName('return');
- if ($returnTags) {
- /** @var ReturnTag $tag */
- $tag = reset($returnTags);
- // Get the expanded type
- $returnValue = $tag->getType();
-
- // Replace the interfaces
- foreach($this->interfaces as $interface => $real){
- $returnValue = str_replace($interface, $real, $returnValue);
- }
-
- // Set the changed content
- $tag->setContent($returnValue . ' ' . $tag->getDescription());
- $this->return = $returnValue;
- }else{
- $this->return = null;
- }
- }
-
- /**
- * Convert keywwords that are incorrect.
- *
- * @param string $string
- * @return string
- */
- protected function convertKeywords($string)
- {
- $string = str_replace('\Closure', 'Closure', $string);
- $string = str_replace('Closure', '\Closure', $string);
- $string = str_replace('dynamic', 'mixed', $string);
-
- return $string;
- }
-
- /**
- * Should the function return a value?
- *
- * @return bool
- */
- public function shouldReturn()
- {
- if($this->return !== "void" && $this->method->name !== "__construct"){
- return true;
- }
-
- return false;
- }
-
- /**
- * Get the parameters and format them correctly
- *
- * @param $method
- * @return array
- */
- public function getParameters($method)
- {
- //Loop through the default values for paremeters, and make the correct output string
- $params = array();
- $paramsWithDefault = array();
- foreach ($method->getParameters() as $param) {
- $paramStr = '$' . $param->getName();
- $params[] = $paramStr;
- if ($param->isOptional()) {
- $default = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null;
- if (is_bool($default)) {
- $default = $default ? 'true' : 'false';
- } elseif (is_array($default)) {
- $default = 'array()';
- } elseif (is_null($default)) {
- $default = 'null';
- } elseif (is_int($default)) {
- //$default = $default;
- } else {
- $default = "'" . trim($default) . "'";
- }
- $paramStr .= " = $default";
- }
- $paramsWithDefault[] = $paramStr;
- }
-
- $this->params = $params;
- $this->params_with_default = $paramsWithDefault;
- }
-
- /**
- * @param \ReflectionMethod $reflectionMethod
- * @return DocBlock
- */
- protected function getInheritDoc($reflectionMethod)
- {
- $parentClass = $reflectionMethod->getDeclaringClass()->getParentClass();
-
- //Get either a parent or the interface
- if ($parentClass) {
- $method = $parentClass->getMethod($reflectionMethod->getName());
- } else {
- $method = $reflectionMethod->getPrototype();
- }
- if ($method) {
- $namespace = $method->getDeclaringClass()->getNamespaceName();
- $phpdoc = new DocBlock($method, new Context($namespace));
-
- if (strpos($phpdoc->getText(), '{@inheritdoc}') !== false) {
- //Not at the end yet, try another parent/interface..
- return $this->getInheritDoc($method);
- } else {
- return $phpdoc;
- }
- }
- }
-}
+
+ * @copyright 2014 Barry vd. Heuvel / 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;
+
+use phpDocumentor\Reflection\DocBlock;
+use phpDocumentor\Reflection\DocBlock\Context;
+use phpDocumentor\Reflection\DocBlock\Tag;
+use phpDocumentor\Reflection\DocBlock\Tag\ReturnTag;
+
+class Method
+{
+ /** @var \phpDocumentor\Reflection\DocBlock */
+ protected $phpdoc;
+
+ /** @var \ReflectionMethod */
+ protected $method;
+
+ protected $name;
+ protected $namespace;
+ protected $params = array();
+ protected $params_with_default = array();
+ protected $interfaces = array();
+ protected $return = null;
+
+ /**
+ * @param \ReflectionMethod $method
+ * @param string $alias
+ * @param \ReflectionClass $class
+ * @param string|null $methodName
+ * @param array $interfaces
+ */
+ public function __construct(\ReflectionMethod $method, $alias, $class, $methodName = null, $interfaces = array())
+ {
+ $this->method = $method;
+ $this->interfaces = $interfaces;
+ $this->name = $methodName ?: $method->name;
+ $declaringClass = $method->getDeclaringClass();
+ $this->namespace = $declaringClass->getNamespaceName();
+
+ //Create a DocBlock and serializer instance
+ $this->phpdoc = new DocBlock($method, new Context($this->namespace, static::getUseStatements($declaringClass)));
+
+ //Normalize the description and inherit the docs from parents/interfaces
+ try {
+ $this->normalizeReturnTags($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($declaringClass->name, '\\');
+ $this->root = '\\' . ltrim($class->getName(), '\\');
+ }
+
+ /**
+ * Get the class wherein the function resides
+ *
+ * @return string
+ */
+ public function getDeclaringClass()
+ {
+ return $this->declaringClassName;
+ }
+
+ /**
+ * Return the class from which this function would be called
+ *
+ * @return string
+ */
+ public function getRoot()
+ {
+ return $this->root;
+ }
+
+ /**
+ * Get the docblock for this method
+ *
+ * @param string $prefix
+ * @param bool $trim
+ * @return string
+ */
+ public function getDocComment($prefix = "\t\t", $trim = false)
+ {
+ $serializer = new DocBlock\Serializer(1, $prefix);
+ $str = $serializer->getDocComment($this->phpdoc);
+ if ($trim) {
+ $str = preg_replace(array('/\s+$/m', '#^(\s*/\*\*[\r\n])(?:\s*\*[\r\n])+#u', '#(?:[\r\n]\s*\*)+([\r\n]\s*\*/)$#u'), array('', '$1', '$1'), $str);
+ }
+ return $str;
+ }
+
+ /**
+ * Get the method name
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * Checks whether the method is deprecated
+ *
+ * @return bool
+ */
+ public function isDeprecated()
+ {
+ return $this->phpdoc->hasTag('deprecated');
+ }
+
+ /**
+ * Get the declared parameters for this method
+ *
+ * @return array
+ */
+ public function getDocParams()
+ {
+ return $this->phpdoc->getTagsByName('param');
+ }
+
+ /**
+ * Get the parameters for this method
+ *
+ * @param bool $implode Whether to implode the array or not
+ * @return string|array
+ */
+ public function getParams($implode = true)
+ {
+ return $implode ? implode(', ', $this->params) : $this->params;
+ }
+
+ /**
+ * Get the parameters for this method including default values
+ *
+ * @param bool $implode Whether to implode the array or not
+ * @return string|array
+ */
+ public function getParamsWithDefault($implode = true)
+ {
+ return $implode ? implode(', ', $this->params_with_default) : $this->params_with_default;
+ }
+
+ /**
+ * Get the description and get the inherited docs.
+ *
+ * @param DocBlock $phpdoc
+ */
+ protected function normalizeDescription(DocBlock $phpdoc)
+ {
+ //Get the short + long description from the DocBlock
+ $description = $phpdoc->getText();
+
+ //Loop through parents/interfaces, to fill in {@inheritdoc}
+ if (stripos($description, '{@inheritdoc}') !== false && ($inheritdoc = $this->getInheritDoc($this->method))) {
+ $inheritDescription = $inheritdoc->getText();
+
+ $description = str_ireplace('{@inheritdoc}', $inheritDescription, $description);
+ $phpdoc->setText($description);
+
+ $this->normalizeReturnTags($inheritdoc);
+
+ //Add the tags that are inherited
+ foreach ($inheritdoc->getTags() as $tag) {
+ $tag->setDocBlock();
+ $phpdoc->appendTag($tag);
+ }
+ }
+ }
+
+ /**
+ * Normalize the return tag (make full namespace, replace interfaces)
+ *
+ * @param DocBlock $phpdoc
+ */
+ protected function normalizeReturnTags(DocBlock $phpdoc)
+ {
+ static $typeProp;
+ if (!isset($typeProp)) {
+ $typeProp = new \ReflectionProperty('phpDocumentor\Reflection\DocBlock\Tag\ReturnTag', 'type');
+ $typeProp->setAccessible(true);
+ }
+
+ $this->return = null;
+ //Get the return type and adjust them for better autocomplete
+ foreach ($phpdoc->getTags() as $tag) {
+ if ($tag instanceof ReturnTag) {
+ // Convert the keywords
+ $typeValue = static::convertKeywords($typeProp->getValue($tag));
+ $typeProp->setValue($tag, $typeValue);
+
+ // Get the expanded type
+ $typeValue = $tag->getType();
+
+ // Replace the interfaces
+ if (preg_match('/\bReturnTag$/', get_class($tag))) {
+ foreach ($this->interfaces as $interface => $real) {
+ $typeValue = preg_replace('/(^|\|)' . preg_quote($interface, '/') . '\b/', $real, $typeValue);
+ }
+ $this->return = $typeValue;
+ }
+
+ // Re-set the type
+ $typeProp->setValue($tag, $typeValue);
+ $tag->setDescription($tag->getDescription());
+ }
+ }
+ }
+
+ /**
+ * Convert keywords that are incorrect.
+ *
+ * @param string $string
+ * @return string
+ */
+ protected static function convertKeywords($string)
+ {
+ $types = explode('|', $string);
+ foreach ($types as &$type) {
+ if ($type === 'Closure')
+ $type = '\Closure';
+ elseif ($type === 'dynamic')
+ $type = 'mixed';
+ elseif (strrpos($type, '\\') && $type[0] !== '\\' && (class_exists($type) || interface_exists($type)))
+ $type = '\\' . $type;
+ }
+ return implode('|', $types);
+ }
+
+ /**
+ * Should the function return a value?
+ *
+ * @return bool|int
+ */
+ public function shouldReturn()
+ {
+ if ($this->return !== 'void' && $this->method->name !== '__construct') {
+ return isset($this->return) ? true : 1;
+ }
+
+ return false;
+ }
+
+ /**
+ * Get the parameters and format them correctly
+ *
+ * @param \ReflectionMethod $method
+ * @return void
+ */
+ public function getParameters($method)
+ {
+ //Loop through the default values for parameters, and make the correct output string
+ $params = array();
+ $paramsWithDefault = array();
+
+ foreach ($method->getParameters() as $param) {
+ $paramStr = '$' . $param->getName();
+ $params[] = $paramStr;
+
+ if ($param->isOptional()) {
+ $default = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null;
+ if (is_bool($default)) {
+ $default = $default ? 'true' : 'false';
+ } elseif (is_array($default)) {
+ $default = 'array()';
+ } elseif (is_null($default)) {
+ $default = 'null';
+ } elseif (is_int($default)) {
+ //$default = $default;
+ } else {
+ $default = "'" . trim($default) . "'";
+ }
+ $paramStr .= " = $default";
+ }
+
+ $paramsWithDefault[] = $paramStr;
+ }
+
+ $this->params = $params;
+ $this->params_with_default = $paramsWithDefault;
+ }
+
+ /**
+ * @param \ReflectionMethod $reflectionMethod
+ * @return DocBlock|null
+ */
+ protected function getInheritDoc($reflectionMethod)
+ {
+ $parentClass = $reflectionMethod->getDeclaringClass()->getParentClass();
+
+ //Get either a parent or the interface
+ if ($parentClass) {
+ $method = $parentClass->getMethod($reflectionMethod->getName());
+ } else {
+ $method = $reflectionMethod->getPrototype();
+ }
+ if ($method) {
+ $namespace = $method->getDeclaringClass()->getNamespaceName();
+ $phpdoc = new DocBlock($method, new Context($namespace, static::getUseStatements($method->getDeclaringClass())));
+
+ if (stripos($phpdoc->getText(), '{@inheritdoc}') !== false) {
+ //Not at the end yet, try another parent/interface..
+ return $this->getInheritDoc($method);
+ } else {
+ return $phpdoc;
+ }
+ }
+ return null;
+ }
+
+ protected static function getUseStatements(\ReflectionClass $class)
+ {
+ try {
+ return PhpReflection::getUseStatements($class);
+ } catch (\Exception $e) {
+ return array();
+ }
+ }
+}
diff --git a/src/PhpReflection.php b/src/PhpReflection.php
new file mode 100644
index 0000000..053f6a8
--- /dev/null
+++ b/src/PhpReflection.php
@@ -0,0 +1,166 @@
+getName();
+ } elseif ($name[0] === '\\') { // fully qualified name
+ return ltrim($name, '\\');
+ }
+
+ $uses = self::getUseStatements($rc);
+ $parts = explode('\\', $name, 2);
+ if (isset($uses[$parts[0]])) {
+ $parts[0] = $uses[$parts[0]];
+ return implode('\\', $parts);
+ } elseif ($rc->inNamespace()) {
+ return $rc->getNamespaceName() . '\\' . $name;
+ } else {
+ return $name;
+ }
+ }
+
+ /**
+ * @param \ReflectionClass
+ * @return array of [alias => class]
+ */
+ public static function getUseStatements(\ReflectionClass $class)
+ {
+ static $cache = array();
+ if (!isset($cache[$name = $class->getName()])) {
+ if ($class->isInternal() || !($code = @file_get_contents($class->getFileName()))) {
+ $cache[$name] = array();
+ } else {
+ $cache = self::parseUseStatements($code, $name) + $cache;
+ }
+ }
+ return $cache[$name];
+ }
+
+ /**
+ * @param string
+ * @return bool
+ */
+ public static function isBuiltinType($type)
+ {
+ return in_array(strtolower($type), array('string', 'int', 'float', 'bool', 'array', 'callable'), true);
+ }
+
+ /**
+ * Parses PHP code.
+ *
+ * @param string $code
+ * @param string $forClass
+ * @return array of [class => [alias => class, ...]]
+ */
+ public static function parseUseStatements($code, $forClass = null)
+ {
+ $tokens = token_get_all($code);
+ $namespace = $class = $classLevel = $level = null;
+ $res = $uses = array();
+
+ while ($token = current($tokens)) {
+ next($tokens);
+ switch (is_array($token) ? $token[0] : $token) {
+ case T_NAMESPACE:
+ $namespace = ltrim(self::fetch($tokens, array(T_STRING, T_NS_SEPARATOR)) . '\\', '\\');
+ $uses = array();
+ break;
+
+ case T_CLASS:
+ case T_INTERFACE:
+ case PHP_VERSION_ID < 50400 ? -1 : T_TRAIT:
+ if ($name = self::fetch($tokens, T_STRING)) {
+ $class = $namespace . $name;
+ $classLevel = $level + 1;
+ $res[$class] = $uses;
+ if ($class === $forClass) {
+ return $res;
+ }
+ }
+ break;
+
+ case T_USE:
+ while (!$class && ($name = self::fetch($tokens, array(T_STRING, T_NS_SEPARATOR)))) {
+ $name = ltrim($name, '\\');
+ if (self::fetch($tokens, '{')) {
+ while ($suffix = self::fetch($tokens, array(T_STRING, T_NS_SEPARATOR))) {
+ if (self::fetch($tokens, T_AS)) {
+ $uses[self::fetch($tokens, T_STRING)] = $name . $suffix;
+ } else {
+ $tmp = explode('\\', $suffix);
+ $uses[end($tmp)] = $name . $suffix;
+ }
+ if (!self::fetch($tokens, ',')) {
+ break;
+ }
+ }
+
+ } elseif (self::fetch($tokens, T_AS)) {
+ $uses[self::fetch($tokens, T_STRING)] = $name;
+
+ } else {
+ $tmp = explode('\\', $name);
+ $uses[end($tmp)] = $name;
+ }
+ if (!self::fetch($tokens, ',')) {
+ break;
+ }
+ }
+ break;
+
+ case T_CURLY_OPEN:
+ case T_DOLLAR_OPEN_CURLY_BRACES:
+ case '{':
+ $level++;
+ break;
+
+ case '}':
+ if ($level === $classLevel) {
+ $class = $classLevel = null;
+ }
+ $level--;
+ }
+ }
+
+ return $res;
+ }
+
+ private static function fetch(&$tokens, $take)
+ {
+ $res = null;
+ while ($token = current($tokens)) {
+ list($token, $s) = is_array($token) ? $token : array($token, $token);
+ if (in_array($token, (array)$take, true)) {
+ $res .= $s;
+ } elseif (!in_array($token, array(T_DOC_COMMENT, T_WHITESPACE, T_COMMENT), true)) {
+ break;
+ }
+ next($tokens);
+ }
+ return $res;
+ }
+}
diff --git a/src/views/ide-helper.php b/src/views/ide-helper.php
index 473dc71..0f2679b 100644
--- a/src/views/ide-helper.php
+++ b/src/views/ide-helper.php
@@ -1,39 +1,46 @@
-= '
-
-/**
- * An helper file for Laravel 4, to provide autocomplete information to your IDE
- * Generated for Laravel = $version ?> on = date("Y-m-d") ?>.
- *
- * @author Barry vd. Heuvel
- * @see https://github.com/barryvdh/laravel-ide-helper
- */
-
- $aliases): ?>
-namespace = $namespace == '__root' ? '' : $namespace ?>{
-
- exit("This file should not be included, only analyzed by your IDE");
-= $helpers ?>
-
-
-
- = $alias->getClassType() ?> = $alias->getShortName() ?> = $alias->getExtends() ? 'extends ' . $alias->getExtends() : '' ?>{
- getMethods() as $method): ?>
-
- = trim($method->getDocComment(' ')) ?>
-
- public static function = $method->getName() ?>(= $method->getParamsWithDefault() ?>){getDeclaringClass() !== $method->getRoot()): ?>
-
- //Method inherited from = $method->getDeclaringClass() ?>
-
-
- = $method->shouldReturn() ? 'return ': '' ?>= $method->getRoot() ?>::= $method->getName() ?>(= $method->getParams() ?>);
- }
-
-
- }
-
-
-
-}
-
-
+= '
+
+/**
+ * An helper file for Laravel 4, to provide autocomplete information to your IDE
+ * Generated for Laravel = $version ?> on = date('Y-m-d') ?>.
+ *
+ * @author Barry vd. Heuvel
+ * @see https://github.com/barryvdh/laravel-ide-helper
+ */
+
+ $aliases/* @var \Barryvdh\LaravelIdeHelper\Alias[] $aliases */): ?>
+namespace = $namespace == '__root' ? '' : $namespace ?>{
+
+ exit('This file should not be included, only analyzed by your IDE');
+= $helpers ?>
+
+
+
+getExtends())) != $alias->getExtends() && $cBase != $alias->getShortName()): ?>
+ /** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */
+
+ = $alias->getClassType() ?> = $alias->getShortName() ?> = $alias->getExtends() ? 'extends ' . $alias->getExtends() : '' ?>{
+getMethods() as $method): ?>
+
+getDocParams())) > count($mParams = $method->getParamsWithDefault(false))): ?>
+ /** @noinspection PhpDocSignatureInspection */
+
+getDocComment("\t\t", true)))): ?>
+ = $docComment ?>
+
+
+ public static function = $method->getName() ?>(= ($docComment && $nParams < count($mParams)) ? '/** @noinspection PhpDocSignatureInspection */' . implode(', /** @noinspection PhpDocSignatureInspection */', $mParams) : $method->getParamsWithDefault() ?>){
+getDeclaringClass() !== $method->getRoot()): ?>
+ //Method inherited from = $method->getDeclaringClass() ?>
+
+
+ /** @noinspection PhpUnnecessaryFullyQualifiedNameInspection,PhpDynamicAsStaticMethodCallInspection= ($method->shouldReturn() === 1 ? ',PhpVoidFunctionResultUsedInspection' : '') . ($method->isDeprecated() ? ',PhpDeprecationInspection' : '') ?> */
+ = $method->shouldReturn() ? 'return ' : '' ?>= $method->getRoot() ?>::= $method->getName() ?>(= $method->getParams() ?>);
+ }
+
+
+ }
+
+
+}
+
diff --git a/src/views/meta.php b/src/views/meta.php
index c51754a..837617a 100644
--- a/src/views/meta.php
+++ b/src/views/meta.php
@@ -1,22 +1,22 @@
= ' namespace PHPSTORM_META {
- /**
- * PhpStorm Meta file, to provide autocomplete information for PhpStorm
- * Generated on = date("Y-m-d") ?>.
- *
- * @author Barry vd. Heuvel
- * @see https://github.com/barryvdh/laravel-ide-helper
- */
+ /**
+ * PhpStorm Meta file, to provide autocomplete information for PhpStorm
+ * Generated on = date('Y-m-d') ?>.
+ *
+ * @author Barry vd. Heuvel
+ * @see https://github.com/barryvdh/laravel-ide-helper
+ */
- /** @noinspection PhpIllegalArrayKeyTypeInspection */
- /** @noinspection PhpUnusedLocalVariableInspection */
- /** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */
- $STATIC_METHOD_TYPES = array(
-
- = $method ?>('') => array(
- $class): ?>
- '= $abstract ?>' instanceof \= $class ?>,
- ),
+ /** @noinspection PhpIllegalArrayKeyTypeInspection,PhpUnusedLocalVariableInspection,PhpUnnecessaryFullyQualifiedNameInspection */
+ $STATIC_METHOD_TYPES = array(
+
+ = strpos($method, 'new ') === 0 ? $method : $method . '(\'\')' ?> => array(
+ $class): ?>
+ = var_export($abstract, true) ?> instanceof \= $class ?>,
- );
+ ),
+
+ );
+
}
diff --git a/tests/MethodTest.php b/tests/MethodTest.php
new file mode 100644
index 0000000..c8b64bc
--- /dev/null
+++ b/tests/MethodTest.php
@@ -0,0 +1,38 @@
+assertSame('\PHPUnit_Framework_TestCase', $object->getDeclaringClass());
+ $this->assertSame('\\' . get_class($this), $object->getRoot());
+ $this->assertSame('getMock', $object->getName());
+
+ $prop = new \ReflectionProperty(get_class($object), 'namespace');
+ $prop->setAccessible(true);
+ $this->assertSame('', $prop->getValue($object));
+
+ $this->assertFalse($object->isDeprecated());
+ $this->assertCount($method->getNumberOfParameters(), $object->getDocParams());
+
+ $doc = $object->getDocComment('', true);
+ $this->assertContains("\n * " . '@param array|null $methods', $doc);
+ $this->assertContains("\n * " . '@return \PHPUnit_Framework_MockObject_MockObject', $doc);
+ $this->assertContains("\n * " . '@throws \PHPUnit_Framework_Exception', $doc);
+
+ $this->assertTrue($object->shouldReturn());
+ }
+
+}
diff --git a/tests/ServiceProviderTest.php b/tests/ServiceProviderTest.php
new file mode 100644
index 0000000..ae72be0
--- /dev/null
+++ b/tests/ServiceProviderTest.php
@@ -0,0 +1,83 @@
+getMock('Illuminate\Container\Container', array('make', 'bind'));
+
+ $fs = $testCase->getMock('Illuminate\Filesystem\Filesystem', null);
+ $config = $testCase->getMock('Illuminate\Config\Repository', array('get', 'set', 'package'), array(), '', false);
+ $events = $testCase->getMock('Illuminate\Events\Dispatcher', array('listen'), array($app));
+ $view = $testCase->getMock('Illuminate\View\Factory', array('addNamespace'), array(), '', false);
+
+ $app->expects($testCase->any())->method('make')->willReturnMap(array(
+ array('files', array(), $fs),
+ array('config', array(), $config),
+ array('events', array(), $events),
+ array('view', array(), $view),
+ array('path', array(), __DIR__),
+ ));
+
+ return $app;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function setUp()
+ {
+ $this->app = static::makeAppMock($this);
+ /** @noinspection PhpParamsInspection */
+ $this->provider = new IdeHelperServiceProvider($this->app);
+ }
+
+ public function testDeferred()
+ {
+ $this->assertTrue($this->provider->isDeferred());
+ }
+
+ public function testProvides()
+ {
+ $this->assertEquals(array('command.ide-helper.generate', 'command.ide-helper.models', 'command.ide-helper.meta'), $this->provider->provides());
+ }
+
+ public function testRegister()
+ {
+ $this->app->expects($this->exactly(3))->method('bind')->withConsecutive(
+ array('command.ide-helper.generate', $this->isType(\PHPUnit_Framework_Constraint_IsType::TYPE_CALLABLE), $this->isFalse()),
+ array('command.ide-helper.models', $this->isType(\PHPUnit_Framework_Constraint_IsType::TYPE_CALLABLE), $this->isFalse()),
+ array('command.ide-helper.meta', $this->isType(\PHPUnit_Framework_Constraint_IsType::TYPE_CALLABLE), $this->isFalse())
+ );
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject|\Illuminate\Events\Dispatcher $events */
+ $events = $this->app['events'];
+ $events->expects($this->once())->method('listen')->with('artisan.start', $this->callback(function ($listener) {
+ $params = print_r(array('commands' => array('command.ide-helper.generate', 'command.ide-helper.models', 'command.ide-helper.meta')), true);
+ return strpos(preg_replace('/^\s+/mu', '', print_r($listener, true)), preg_replace('/^\s+/mu', '', $params));
+ }), 0);
+
+ $this->provider->register();
+ }
+
+ public function testBoot()
+ {
+ $path = realpath(__DIR__ . '/../src');
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject|\Illuminate\Config\Repository $config */
+ $config = $this->app['config'];
+ $config->expects($this->once())->method('package')->with('barryvdh/laravel-ide-helper', $path . '/config', 'laravel-ide-helper');
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject|\Illuminate\View\Factory $view */
+ $view = $this->app['view'];
+ $view->expects($this->once())->method('addNamespace')->with('laravel-ide-helper', $path . '/views');
+
+ $this->provider->boot();
+ }
+
+}