Compare commits

..
Author SHA1 Message Date
Barry vd. Heuvel eda37f3442 Catch PDO errors when getting drivers/connections 2013-07-12 14:39:12 +02:00
247 changed files with 1051 additions and 15310 deletions
-15
View File
@@ -1,15 +0,0 @@
; This file is for unifying the coding style for different editors and IDEs.
; More information at http://editorconfig.org
root = true
[*]
charset = utf-8
indent_size = 4
indent_style = space
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
-15
View File
@@ -1,15 +0,0 @@
# Path-based git attributes
# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
# Ignore all test and documentation with "export-ignore".
/.editorconfig export-ignore
/.gitattributes export-ignore
/.github export-ignore
/.gitignore export-ignore
/.php-cs-fixer.cache export-ignore
/.php-cs-fixer.php export-ignore
/.php-cs-fixer.tests.cache export-ignore
/phpunit.xml.dist export-ignore
/psalm-baseline.xml export-ignore
/psalm.xml export-ignore
/tests export-ignore
-5
View File
@@ -1,5 +0,0 @@
# These are supported funding model platforms
github: barryvdh
custom: ['https://fruitcake.nl']
-23
View File
@@ -1,23 +0,0 @@
---
name: "🐛 Bug Report"
about: 'Report a general bug.'
labels: bug
---
### Versions:
- ide-helper Version: #.#.#
- Laravel Version: #.#.# <!-- remove if not applicable -->
- PHP Version: #.#.#
### Description:
<!--
Please describe in detail the nature of the bug, code samples, etc.
The more, the better.
-->
### Steps To Reproduce:
-
@@ -1,12 +0,0 @@
---
name: "✨ Feature request"
about: 'Suggest a new feature or other improvements.'
labels: enhancement
---
### Summary
<!--
Describe in detail what you propose, show (preferable) code examples and also signal if you're willing to work on it!
-->
@@ -1,14 +0,0 @@
---
name: "🙋🏼‍♂️ Support question"
about: 'I need assistance or clarification on usage of this library.'
labels: question
---
### Versions:
- ide-helper Version: #.#.#
- Laravel Version: #.#.# <!-- remove if not applicable -->
- PHP Version: #.#.#
### Question:
-17
View File
@@ -1,17 +0,0 @@
## Summary
<!-- Please provide an exhaustive description. -->
## Type of change
<!-- Please delete options that are not relevant. -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update
- [ ] Misc. change (internal, infrastructure, maintenance, etc.)
### Checklist
- [ ] Existing tests have been adapted and/or new tests have been added
- [ ] Update the README.md
- [ ] Code style has been fixed via `composer fix-style`
-10
View File
@@ -1,10 +0,0 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: monthly
groups:
deps:
patterns:
- '*'
-24
View File
@@ -1,24 +0,0 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 90
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 60
# Issues with these labels will never be considered stale
exemptLabels:
- bug
- enhancement
- discussion
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs.
If this issue is still present on the latest version of this library on supported Laravel versions,
please let us know by replying to this issue so we can investigate further.
Thank you for your contribution! Apologies for any delayed response on our side.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false
# Limit to only `issues` or `pulls`
only: issues
-28
View File
@@ -1,28 +0,0 @@
name: normalize composer.json
on:
push:
paths:
- .github/workflows/composer-normalize.yml
- composer.json
jobs:
normalize:
timeout-minutes: 15
runs-on: ubuntu-22.04
steps:
- name: Git checkout
uses: actions/checkout@v4
- name: Validate Composer configuration
run: composer validate --strict
- name: Normalize composer.json
run: |
composer global config --no-plugins allow-plugins.ergebnis/composer-normalize true
composer global require ergebnis/composer-normalize
composer normalize
- uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: normalize composer.json
-33
View File
@@ -1,33 +0,0 @@
name: Fix Code Style
on:
push:
jobs:
fix-style:
name: Fix Code Style
timeout-minutes: 15
runs-on: ubuntu-22.04
env:
COMPOSER_NO_INTERACTION: 1
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.3
coverage: none
- name: Install dependencies
run: composer update --prefer-dist --no-progress
- run: composer fix-style
continue-on-error: true
- uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: composer fix-style
commit_author: laravel-ide-helper <[email protected]>
@@ -1,75 +0,0 @@
name: Integration Tests
on:
push:
branches:
- master
pull_request:
branches:
- "*"
schedule:
- cron: '0 0 * * *'
jobs:
php-laravel-integration-tests:
runs-on: ubuntu-22.04
timeout-minutes: 15
env:
COMPOSER_NO_INTERACTION: 1
strategy:
fail-fast: false
matrix:
php: [8.4, 8.3, 8.2]
laravel: [^11.15]
name: P${{ matrix.php }} - Laravel${{ matrix.laravel }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
path: src
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: none
- name: Install dependencies
run: |
composer create-project --prefer-dist laravel/laravel:${{ matrix.laravel }} --stability=dev --no-progress sample
cd sample
composer config minimum-stability dev
composer update --prefer-stable --prefer-dist --no-progress
- name: Add package from source
run: |
cd sample
sed -e 's|"type": "project",|&\n"repositories": [ { "type": "path", "url": "../src" } ],|' -i composer.json
composer require --dev "barryvdh/laravel-ide-helper:*" --with-all-dependencies
- name: Execute generate run
run: |
cd sample
php artisan ide-helper:generate
- name: Execute meta run
run: |
cd sample
php artisan ide-helper:meta -v
- name: Check file existence
run: |
ls sample/_ide_helper.php
ls sample/.phpstorm.meta.php
- name: Check logs
run: |
if [ `ls -1q "sample/storage/logs/" | wc -l` -gt 0 ]; then
for logfile in sample/storage/logs/*; do
echo "-- $logfile --"
cat $logfile
done
exit 1
fi
-28
View File
@@ -1,28 +0,0 @@
name: Run Static Analysis
on:
push:
pull_request:
schedule:
- cron: '0 0 * * *'
jobs:
build:
timeout-minutes: 15
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.3
coverage: none
extensions: pdo_sqlite
- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-suggest
- name: Analyze
run: composer analyze
-52
View File
@@ -1,52 +0,0 @@
name: Tests
on:
push:
branches:
- master
pull_request:
branches:
- "*"
schedule:
- cron: '0 0 * * *'
jobs:
php-tests:
runs-on: ${{ matrix.os }}
timeout-minutes: 15
env:
COMPOSER_NO_INTERACTION: 1
strategy:
fail-fast: false
matrix:
os: [ubuntu-22.04, windows-2019]
php: [8.4, 8.3, 8.2]
laravel: [^11.15]
stability: [prefer-lowest, prefer-stable]
steps:
- name: Set git to use LF
if: ${{ matrix.os == 'windows-2019' }}
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- name: Checkout code
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: none
extensions: pdo_sqlite, fileinfo
- name: Install dependencies
run: |
composer remove vimeo/psalm --no-update --dev
composer remove friendsofphp/php-cs-fixer --no-update --dev
composer require "laravel/framework:${{ matrix.laravel }}" --no-update --no-progress
composer update --prefer-dist --no-progress --${{ matrix.stability }}
- name: Execute Unit Tests
run: composer test-ci
+2 -7
View File
@@ -1,8 +1,3 @@
.phpunit.result.cache
/.idea
/.php-cs-fixer.cache
/.php-cs-fixer.php
/.php-cs-fixer.tests.cache
/composer.lock
/vendor
composer.lock
.idea
-62
View File
@@ -1,62 +0,0 @@
<?php
// Share common rules between non-test and test files
return [
'@PSR12' => true,
'blank_line_after_opening_tag' => true,
'braces' => [
'allow_single_line_anonymous_class_with_empty_body' => true,
],
'compact_nullable_typehint' => true,
'declare_equal_normalize' => true,
'lowercase_cast' => true,
'lowercase_static_reference' => true,
'new_with_braces' => true,
'no_blank_lines_after_class_opening' => true,
'no_leading_import_slash' => true,
'no_whitespace_in_blank_line' => true,
'ordered_class_elements' => [
'order' => [
'use_trait',
],
],
'ordered_imports' => [
'imports_order' => [
'class',
'function',
'const',
],
'sort_algorithm' => 'alpha',
],
'return_type_declaration' => true,
'short_scalar_cast' => true,
'single_trait_insert_per_statement' => true,
'ternary_operator_spaces' => true,
'visibility_required' => [
'elements' => [
'const',
'method',
'property',
],
],
// Further quality-of-life improvements
'array_syntax' => [
'syntax' => 'short',
],
'concat_space' => [
'spacing' => 'one',
],
'fully_qualified_strict_types' => true,
'native_function_invocation' => [
'include' => [],
'strict' => true,
],
'no_unused_imports' => true,
'single_quote' => true,
'space_after_semicolon' => true,
'trailing_comma_in_multiline' => true,
'trim_array_spaces' => true,
'unary_operator_spaces' => true,
'whitespace_after_comma_in_array' => true,
];
-14
View File
@@ -1,14 +0,0 @@
<?php
require __DIR__ . '/vendor/autoload.php';
$finder = PhpCsFixer\Finder::create()
->in(__DIR__)
->exclude('tests');
$config = require __DIR__ . '/.php-cs-fixer.common.php';
return (new PhpCsFixer\Config())
->setFinder($finder)
->setRules($config)
->setRiskyAllowed(true)
->setCacheFile(__DIR__ . '/.php-cs-fixer.cache');
-22
View File
@@ -1,22 +0,0 @@
<?php
require __DIR__ . '/vendor/autoload.php';
$finder = PhpCsFixer\Finder::create()
->in(__DIR__ . '/tests')
->exclude('__snapshots__');
$config = require __DIR__ . '/.php-cs-fixer.common.php';
// Additional rules for tests
$config = array_merge(
$config,
[
'declare_strict_types' => true,
]
);
return (new PhpCsFixer\Config())
->setFinder($finder)
->setRules($config)
->setRiskyAllowed(true)
->setCacheFile(__DIR__ . '/.php-cs-fixer.tests.cache');
-21
View File
@@ -1,21 +0,0 @@
# The MIT License (MIT)
Copyright (c) Barry vd. Heuvel <barryvdh@gmail.com>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in
> all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> THE SOFTWARE.
-394
View File
@@ -1,394 +0,0 @@
# IDE Helper Generator for Laravel
[![Tests](https://github.com/barryvdh/laravel-ide-helper/actions/workflows/run-tests.yml/badge.svg)](https://github.com/barryvdh/laravel-ide-helper/actions)
[![Packagist License](https://img.shields.io/badge/Licence-MIT-blue)](http://choosealicense.com/licenses/mit/)
[![Latest Stable Version](https://img.shields.io/packagist/v/barryvdh/laravel-ide-helper?label=Stable)](https://packagist.org/packages/barryvdh/laravel-ide-helper)
[![Total Downloads](https://img.shields.io/packagist/dt/barryvdh/laravel-ide-helper?label=Downloads)](https://packagist.org/packages/barryvdh/laravel-ide-helper)
[![Fruitcake](https://img.shields.io/badge/Powered%20By-Fruitcake-b2bc35.svg)](https://fruitcake.nl/)
**Complete PHPDocs, directly from the source**
This package generates helper files that enable your IDE to provide accurate autocompletion.
Generation is done based on the files in your project, so they are always up-to-date.
The 3.x branch supports Laravel 10 and 11. For older version, use the 2.x releases.
- [Installation](#installation)
- [Usage](#usage)
- [Automatic PHPDoc generation for Laravel Facades](#automatic-phpdoc-generation-for-laravel-facades)
- [Automatic PHPDocs for models](#automatic-phpdocs-for-models)
- [Model Directories](#model-directories)
- [Ignore Models](#ignore-models)
- [Model Hooks](#model-hooks)
- [Automatic PHPDocs generation for Laravel Fluent methods](#automatic-phpdocs-generation-for-laravel-fluent-methods)
- [Auto-completion for factory builders](#auto-completion-for-factory-builders)
- [PhpStorm Meta for Container instances](#phpstorm-meta-for-container-instances)
- [License](#license)
## Installation
Require this package with composer using the following command:
```bash
composer require --dev barryvdh/laravel-ide-helper
```
> [!NOTE]
> If you encounter version conflicts with doctrine/dbal, please try:
> `composer require --dev barryvdh/laravel-ide-helper --with-all-dependencies`
This package makes use of [Laravels package auto-discovery mechanism](https://medium.com/@taylorotwell/package-auto-discovery-in-laravel-5-5-ea9e3ab20518), which means if you don't install dev dependencies in production, it also won't be loaded.
If for some reason you want manually control this:
- add the package to the `extra.laravel.dont-discover` key in `composer.json`, e.g.
```json
"extra": {
"laravel": {
"dont-discover": [
"barryvdh/laravel-ide-helper"
]
}
}
```
- Add the following class to the `providers` array in `config/app.php`:
```php
Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class,
```
If you want to manually load it only in non-production environments, instead you can add this to your `AppServiceProvider` with the `register()` method:
```php
public function register()
{
if ($this->app->isLocal()) {
$this->app->register(\Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class);
}
// ...
}
```
> Note: Avoid caching the configuration in your development environment, it may cause issues after installing this package; respectively clear the cache beforehand via `php artisan cache:clear` if you encounter problems when running the commands
## Usage
_Check out [this Laracasts video](https://laracasts.com/series/how-to-be-awesome-in-phpstorm/episodes/15) for a quick introduction/explanation!_
- `php artisan ide-helper:generate` - [PHPDoc generation for Laravel Facades ](#automatic-phpdoc-generation-for-laravel-facades)
- `php artisan ide-helper:models` - [PHPDocs for models](#automatic-phpdocs-for-models)
- `php artisan ide-helper:meta` - [PhpStorm Meta file](#phpstorm-meta-for-container-instances)
Note: You do need CodeComplice for Sublime Text: https://github.com/spectacles/CodeComplice
### Automatic PHPDoc generation for Laravel Facades
You can now re-generate the docs yourself (for future updates)
```bash
php artisan ide-helper:generate
```
Note: `bootstrap/compiled.php` has to be cleared first, so run `php artisan clear-compiled` before generating.
This will generate the file `_ide_helper.php` which is expected to be additionally parsed by your IDE for autocomplete. You can use the config `filename` to change its name.
You can configure your `composer.json` to do this each time you update your dependencies:
```js
"scripts": {
"post-update-cmd": [
"Illuminate\\Foundation\\ComposerScripts::postUpdate",
"@php artisan ide-helper:generate",
"@php artisan ide-helper:meta"
]
},
```
You can also publish the config file to change implementations (ie. interface to specific class) or set defaults for `--helpers`.
```bash
php artisan vendor:publish --provider="Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider" --tag=config
```
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.
If you use [real-time facades](https://laravel.com/docs/master/facades#real-time-facades) in your app, those will also be included in the generated file using a `@mixin` annotation and extending the original class underneath the facade.
**Note**: this feature uses the generated real-time facades files in the `storage/framework/cache` folder. Those files are generated on-demand as you use the real-time facade, so if the framework has not generated that first, it will not be included in the helper file. Run the route/command/code first and then regenerate the helper file and this time the real-time facade will be included in it.
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.
### Automatic PHPDoc generation for macros and mixins
This package can generate PHPDocs for macros and mixins which will be added to the `_ide_helper.php` file.
But this only works if you use type hinting when declaring a macro.
```php
Str::macro('concat', function(string $str1, string $str2) : string {
return $str1 . $str2;
});
```
### Automatic PHPDocs for models
If you don't want to write your properties yourself, you can use the command `php artisan ide-helper:models` to generate
PHPDocs, based on table columns, relations and getters/setters.
> Note: this command requires a working database connection to introspect the table of each model
By default, you are asked to overwrite or write to a separate file (`_ide_helper_models.php`).
You can write the comments directly to your Model file, using the `--write (-W)` option, or
force to not write with `--nowrite (-N)`.
Alternatively using the `--write-mixin (-M)` option will only add a mixin tag to your Model file,
writing the rest in (`_ide_helper_models.php`).
The class name will be different from the model, avoiding the IDE duplicate annoyance.
> Please make sure to back up your models, before writing the info.
Writing to the models should keep the existing comments and only append new properties/methods. It will not update changed properties/methods.
With the `--reset (-R)` option, the whole existing PHPDoc is replaced, including any comments that have been made.
```bash
php artisan ide-helper:models "App\Models\Post"
```
```php
/**
* App\Models\Post
*
* @property integer $id
* @property integer $author_id
* @property string $title
* @property string $text
* @property \Illuminate\Support\Carbon $created_at
* @property \Illuminate\Support\Carbon $updated_at
* @property-read \User $author
* @property-read \Illuminate\Database\Eloquent\Collection|\Comment[] $comments
* @method static \Illuminate\Database\Eloquent\Builder<static>|\App\Models\Post newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|\App\Models\Post newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|\App\Models\Post query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|\App\Models\Post whereTitle($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|\App\Models\Post forAuthors(\User ...$authors)
* …
*/
```
With the `--write-mixin (-M)` option
```php
/**
* …
* @mixin IdeHelperPost
*/
```
#### Model Directories
By default, models in `app/models` are scanned. The optional argument tells what models to use (also outside app/models).
```bash
php artisan ide-helper:models "App\Models\Post" "App\Models\User"
```
You can also scan a different directory, using the `--dir` option (relative from the base path):
```bash
php artisan ide-helper:models --dir="path/to/models" --dir="app/src/Model"
```
You can publish the config file (`php artisan vendor:publish`) and set the default directories.
#### Ignore Models
Models can be ignored using the `--ignore (-I)` option
```bash
php artisan ide-helper:models --ignore="App\Models\Post,App\Models\User"
```
Or can be ignored by setting the `ignored_models` config
```php
'ignored_models' => [
App\Post::class,
Api\User::class
],
```
#### Magic `where*` methods
Eloquent allows calling `where<Attribute>` on your models, e.g. `Post::whereTitle(…)` and automatically translates this to e.g. `Post::where('title', '=', '…')`.
If for some reason it's undesired to have them generated (one for each column), you can disable this via config `write_model_magic_where` and setting it to `false`.
#### Magic `*_count` properties
You may use the [`::withCount`](https://laravel.com/docs/master/eloquent-relationships#counting-related-models) method to count the number results from a relationship without actually loading them. Those results are then placed in attributes following the `<columname>_count` convention.
By default, these attributes are generated in the phpdoc. You can turn them off by setting the config `write_model_relation_count_properties` to `false`.
#### Generics annotations
Laravel 9 introduced generics annotations in DocBlocks for collections. PhpStorm 2022.3 and above support the use of generics annotations within `@property` and `@property-read` declarations in DocBlocks, e.g. `Collection<User>` instead of `Collection|User[]`.
These can be disabled by setting the config `use_generics_annotations` to `false`.
#### Support `@comment` based on DocBlock
In order to better support IDEs, relations and getters/setters can also add a comment to a property like table columns. Therefore a custom docblock `@comment` is used:
```php
class Users extends Model
{
/**
* @comment Get User's full name
*
* @return string
*/
public function getFullNameAttribute(): string
{
return $this->first_name . ' ' .$this->last_name ;
}
}
// => after generate models
/**
* App\Models\Users
*
* @property-read string $full_name Get User's full name
* …
*/
```
#### Dedicated Eloquent Builder methods
A new method to the eloquent models was added called `newEloquentBuilder` [Reference](https://timacdonald.me/dedicated-eloquent-model-query-builders/) where we can
add support for creating a new dedicated class instead of using local scopes in the model itself.
If for some reason it's undesired to have them generated (one for each column), you can disable this via config `write_model_external_builder_methods` and setting it to `false`.
#### Custom Relationship Types
If you are using relationships not built into Laravel you will need to specify the name and returning class in the config to get proper generation.
```php
'additional_relation_types' => [
'externalHasMany' => \My\Package\externalHasMany::class
],
```
Found relationships will typically generate a return value based on the name of the relationship.
If your custom relationships don't follow this traditional naming scheme you can define its return type manually. The available options are `many` and `morphTo`.
```php
'additional_relation_return_types' => [
'externalHasMultiple' => 'many'
],
```
#### Model Hooks
If you need additional information on your model from sources that are not handled by default, you can hook in to the
generation process with model hooks to add extra information on the fly.
Simply create a class that implements `ModelHookInterface` and add it to the `model_hooks` array in the config:
```php
'model_hooks' => [
MyCustomHook::class,
],
```
The `run` method will be called during generation for every model and receives the current running `ModelsCommand` and the current `Model`, e.g.:
```php
class MyCustomHook implements ModelHookInterface
{
public function run(ModelsCommand $command, Model $model): void
{
if (! $model instanceof MyModel) {
return;
}
$command->setProperty('custom', 'string', true, false, 'My custom property');
$command->unsetMethod('method');
$command->setMethod('method', $command->getMethodType($model, '\Some\Class'), ['$param']);
}
}
```
```php
/**
* MyModel
*
* @property integer $id
* @property-read string $custom
```
### 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();
```
After publishing vendor, simply change the `include_fluent` line in your `config/ide-helper.php` file into:
```php
'include_fluent' => true,
```
Then run `php artisan ide-helper:generate`, you will now see all Fluent methods recognized by your IDE.
### Auto-completion for factory builders
If you would like the `factory()->create()` and `factory()->make()` methods to return the correct model class,
you can enable custom factory builders with the `include_factory_builders` line in your `config/ide-helper.php` file.
Deprecated for Laravel 8 or latest.
```php
'include_factory_builders' => true,
```
For this to work, you must also publish the PhpStorm Meta file (see below).
## PhpStorm Meta for Container instances
It's possible to generate a PhpStorm meta file to [add support for factory design pattern](https://www.jetbrains.com/help/phpstorm/ide-advanced-metadata.html).
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 an `Illuminate\Events\Dispatcher` object,
so with the meta file you can call `app('events')` and it will autocomplete the Dispatcher methods.
```bash
php artisan ide-helper:meta
```
```php
app('events')->fire();
\App::make('events')->fire();
/** @var \Illuminate\Foundation\Application $app */
$app->make('events')->fire();
// When the key is not found, it uses the argument as class name
app('App\SomeClass');
// Also works with
app(App\SomeClass::class);
```
> Note: You might need to restart PhpStorm and make sure `.phpstorm.meta.php` is indexed.
>
> Note: When you receive a FatalException: class not found, check your config
> (for example, remove S3 as cloud driver when you don't have S3 configured. Remove Redis ServiceProvider when you don't use it).
You can change the generated filename via the config `meta_filename`. This can be useful for cases where you want to take advantage of PhpStorm's support of the _directory_ `.phpstorm.meta.php/`: all files placed there are parsed, should you want to provide additional files to PhpStorm.
## License
The Laravel IDE Helper Generator is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
+10 -75
View File
@@ -1,18 +1,8 @@
{
"name": "barryvdh/laravel-ide-helper",
"description": "Laravel IDE Helper, generates correct PHPDocs for all Facade classes, to improve auto-completion.",
"keywords": ["laravel", "autocomplete", "phpstorm", "netbeans", "sublime", "codeintel", "phpdoc"],
"license": "MIT",
"keywords": [
"laravel",
"autocomplete",
"ide",
"helper",
"phpstorm",
"netbeans",
"sublime",
"codeintel",
"phpdoc"
],
"authors": [
{
"name": "Barry vd. Heuvel",
@@ -20,72 +10,17 @@
}
],
"require": {
"php": "^8.2",
"ext-json": "*",
"barryvdh/reflection-docblock": "^2.1.2",
"composer/class-map-generator": "^1.0",
"illuminate/console": "^11.15",
"illuminate/database": "^11.15",
"illuminate/filesystem": "^11.15",
"illuminate/support": "^11.15",
"nikic/php-parser": "^4.18 || ^5",
"phpdocumentor/type-resolver": "^1.1.0"
"php": ">=5.3.0",
"illuminate/support": "4.x",
"illuminate/console": "4.x",
"illuminate/filesystem": "4.x",
"barryvdh/reflection-docblock": ">=2.0.1",
"symfony/class-loader": "~2.3"
},
"require-dev": {
"ext-pdo_sqlite": "*",
"friendsofphp/php-cs-fixer": "^3",
"illuminate/config": "^11.15",
"illuminate/view": "^11.15",
"mockery/mockery": "^1.4",
"orchestra/testbench": "^9.2",
"phpunit/phpunit": "^10.5",
"spatie/phpunit-snapshot-assertions": "^4 || ^5",
"vimeo/psalm": "^5.4"
},
"suggest": {
"illuminate/events": "Required for automatic helper generation (^6|^7|^8|^9|^10|^11)."
},
"minimum-stability": "dev",
"prefer-stable": true,
"autoload": {
"psr-4": {
"Barryvdh\\LaravelIdeHelper\\": "src"
"psr-0": {
"Barryvdh\\LaravelIdeHelper": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Barryvdh\\LaravelIdeHelper\\Tests\\": "tests"
}
},
"config": {
"allow-plugins": {
"composer/package-versions-deprecated": true
},
"sort-packages": true
},
"extra": {
"branch-alias": {
"dev-master": "3.2-dev"
},
"laravel": {
"providers": [
"Barryvdh\\LaravelIdeHelper\\IdeHelperServiceProvider"
]
}
},
"scripts": {
"analyze": "psalm",
"check-style": [
"php-cs-fixer fix --diff --diff-format=udiff --dry-run",
"php-cs-fixer fix --diff --diff-format=udiff --dry-run --config=.php_cs.tests.php"
],
"fix-style": [
"php-cs-fixer fix",
"php-cs-fixer fix --config=.php-cs-fixer.tests.php"
],
"psalm-set-baseline": "psalm --set-baseline=psalm-baseline.xml",
"test": "phpunit",
"test-ci": "phpunit -d --without-creating-snapshots",
"test-regenerate": "phpunit -d --update-snapshots"
}
"minimum-stability": "dev"
}
-314
View File
@@ -1,314 +0,0 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Filename
|--------------------------------------------------------------------------
|
| The default filename.
|
*/
'filename' => '_ide_helper.php',
/*
|--------------------------------------------------------------------------
| Models filename
|--------------------------------------------------------------------------
|
| The default filename for the models helper file.
|
*/
'models_filename' => '_ide_helper_models.php',
/*
|--------------------------------------------------------------------------
| PhpStorm meta filename
|--------------------------------------------------------------------------
|
| PhpStorm also supports the directory `.phpstorm.meta.php/` with arbitrary
| files in it, should you need additional files for your project; e.g.
| `.phpstorm.meta.php/laravel_ide_Helper.php'.
|
*/
'meta_filename' => '.phpstorm.meta.php',
/*
|--------------------------------------------------------------------------
| Fluent helpers
|--------------------------------------------------------------------------
|
| Set to true to generate commonly used Fluent methods.
|
*/
'include_fluent' => false,
/*
|--------------------------------------------------------------------------
| Factory builders
|--------------------------------------------------------------------------
|
| Set to true to generate factory generators for better factory()
| method auto-completion.
|
| Deprecated for Laravel 8 or latest.
|
*/
'include_factory_builders' => false,
/*
|--------------------------------------------------------------------------
| Write model magic methods
|--------------------------------------------------------------------------
|
| Set to false to disable write magic methods of model.
|
*/
'write_model_magic_where' => true,
/*
|--------------------------------------------------------------------------
| Write model external Eloquent builder methods
|--------------------------------------------------------------------------
|
| Set to false to disable write external Eloquent builder methods.
|
*/
'write_model_external_builder_methods' => true,
/*
|--------------------------------------------------------------------------
| Write model relation count properties
|--------------------------------------------------------------------------
|
| Set to false to disable writing of relation count properties to model DocBlocks.
|
*/
'write_model_relation_count_properties' => true,
/*
|--------------------------------------------------------------------------
| Write Eloquent model mixins
|--------------------------------------------------------------------------
|
| This will add the necessary DocBlock mixins to the model class
| contained in the Laravel framework. This helps the IDE with
| auto-completion.
|
| Please be aware that this setting changes a file within the /vendor directory.
|
*/
'write_eloquent_model_mixins' => false,
/*
|--------------------------------------------------------------------------
| Helper files to include
|--------------------------------------------------------------------------
|
| Include helper files. By default not included, but can be toggled with the
| -- helpers (-H) option. Extra helper files can be included.
|
*/
'include_helpers' => false,
'helper_files' => [
base_path() . '/vendor/laravel/framework/src/Illuminate/Support/helpers.php',
],
/*
|--------------------------------------------------------------------------
| Model locations to include
|--------------------------------------------------------------------------
|
| Define in which directories the ide-helper:models command should look
| for models.
|
| glob patterns are supported to easier reach models in sub-directories,
| e.g. `app/Services/* /Models` (without the space).
|
*/
'model_locations' => [
'app',
],
/*
|--------------------------------------------------------------------------
| Models to ignore
|--------------------------------------------------------------------------
|
| Define which models should be ignored.
|
*/
'ignored_models' => [
// App\MyModel::class,
],
/*
|--------------------------------------------------------------------------
| Models hooks
|--------------------------------------------------------------------------
|
| Define which hook classes you want to run for models to add custom information.
|
| Hooks should implement Barryvdh\LaravelIdeHelper\Contracts\ModelHookInterface.
|
*/
'model_hooks' => [
// App\Support\IdeHelper\MyModelHook::class
],
/*
|--------------------------------------------------------------------------
| Extra classes
|--------------------------------------------------------------------------
|
| These implementations are not really extended, but called with magic functions.
|
*/
'extra' => [
'Eloquent' => ['Illuminate\Database\Eloquent\Builder', 'Illuminate\Database\Query\Builder'],
'Session' => ['Illuminate\Session\Store'],
],
'magic' => [],
/*
|--------------------------------------------------------------------------
| Interface implementations
|--------------------------------------------------------------------------
|
| These interfaces will be replaced with the implementing class. Some interfaces
| are detected by the helpers, others can be listed below.
|
*/
'interfaces' => [
// App\MyInterface::class => App\MyImplementation::class,
],
/*
|--------------------------------------------------------------------------
| Support for camel cased models
|--------------------------------------------------------------------------
|
| There are some Laravel packages (such as Eloquence) that allow for accessing
| Eloquent model properties via camel case, instead of snake case.
|
| Enabling this option will support these packages by saving all model
| properties as camel case, instead of snake case.
|
| For example, normally you would see this:
|
| * @property \Illuminate\Support\Carbon $created_at
| * @property \Illuminate\Support\Carbon $updated_at
|
| With this enabled, the properties will be this:
|
| * @property \Illuminate\Support\Carbon $createdAt
| * @property \Illuminate\Support\Carbon $updatedAt
|
| Note, it is currently an all-or-nothing option.
|
*/
'model_camel_case_properties' => false,
/*
|--------------------------------------------------------------------------
| Property casts
|--------------------------------------------------------------------------
|
| Cast the given "real type" to the given "type".
|
*/
'type_overrides' => [
'integer' => 'int',
'boolean' => 'bool',
],
/*
|--------------------------------------------------------------------------
| Include DocBlocks from classes
|--------------------------------------------------------------------------
|
| Include DocBlocks from classes to allow additional code inspection for
| magic methods and properties.
|
*/
'include_class_docblocks' => false,
/*
|--------------------------------------------------------------------------
| Force FQN usage
|--------------------------------------------------------------------------
|
| Use the fully qualified (class) name in DocBlocks,
| even if the class exists in the same namespace
| or there is an import (use className) of the class.
|
*/
'force_fqn' => false,
/*
|--------------------------------------------------------------------------
| Use generics syntax
|--------------------------------------------------------------------------
|
| Use generics syntax within DocBlocks,
| e.g. `Collection<User>` instead of `Collection|User[]`.
|
*/
'use_generics_annotations' => true,
/*
|--------------------------------------------------------------------------
| Additional relation types
|--------------------------------------------------------------------------
|
| Sometimes it's needed to create custom relation types. The key of the array
| is the relationship method name. The value of the array is the fully-qualified
| class name of the relationship, e.g. `'relationName' => RelationShipClass::class`.
|
*/
'additional_relation_types' => [],
/*
|--------------------------------------------------------------------------
| Additional relation return types
|--------------------------------------------------------------------------
|
| When using custom relation types its possible for the class name to not contain
| the proper return type of the relation. The key of the array is the relationship
| method name. The value of the array is the return type of the relation ('many'
| or 'morphTo').
| e.g. `'relationName' => 'many'`.
|
*/
'additional_relation_return_types' => [],
/*
|--------------------------------------------------------------------------
| Run artisan commands after migrations to generate model helpers
|--------------------------------------------------------------------------
|
| The specified commands should run after migrations are finished running.
|
*/
'post_migrate' => [
// 'ide-helper:models --nowrite',
],
];
-17
View File
@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
cacheDirectory=".phpunit.result.cache"
>
<testsuites>
<testsuite name="Unit Tests">
<directory>tests</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory suffix=".php">src/</directory>
</include>
</source>
</phpunit>
-24
View File
@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="5.4.0@62db5d4f6a7ae0a20f7cc5a4952d730272fc0863">
<file src="src/Factories.php">
<UndefinedClass occurrences="2">
<code>Factory</code>
<code>Factory</code>
</UndefinedClass>
</file>
<file src="src/Generator.php">
<UndefinedClass occurrences="6">
<code>\Auth</code>
<code>\Cache</code>
<code>\Cache</code>
<code>\DB</code>
<code>\Queue</code>
<code>\Storage</code>
</UndefinedClass>
</file>
<file src="src/Console/ModelsCommand.php">
<UndefinedClass occurrences="1">
<code>\UnitEnum</code>
</UndefinedClass>
</file>
</files>
-16
View File
@@ -1,16 +0,0 @@
<?xml version="1.0"?>
<psalm
errorLevel="7"
resolveFromConfigFile="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
errorBaseline="psalm-baseline.xml"
>
<projectFiles>
<directory name="src" />
<ignoreFiles>
<directory name="vendor" />
</ignoreFiles>
</projectFiles>
</psalm>
+84
View File
@@ -0,0 +1,84 @@
## Laravel IDE Helper Generator
[![Latest Stable Version](https://poser.pugx.org/barryvdh/laravel-ide-helper/version.png)](https://packagist.org/packages/barryvdh/laravel-ide-helper) [![Total Downloads](https://poser.pugx.org/barryvdh/laravel-ide-helper/d/total.png)](https://packagist.org/packages/barryvdh/laravel-ide-helper)
### Complete phpDocs, directly from the source
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.
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
Note: You do need CodeIntel for Sublime Text: https://github.com/SublimeCodeIntel/SublimeCodeIntel
### Automatic phpDoc generation for Laravel Facades
Require this package in your composer.json and run composer update (or run `composer require barryvdh/laravel-ide-helper:1.*` directly):
"barryvdh/laravel-ide-helper": "1.*"
After updating composer, add the ServiceProvider to the providers array in app/config/app.php
'Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider',
You can now re-generate the docs yourself (for future updates) in artisan
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 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
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 working default connection, some facades will not be included.
You can use a in-memory sqlite driver, using the -M option.
You can choose to include helper files. This is not enabled by default, but you can override this 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.
### Automatic phpDocs for Models
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. Still in beta, so please provide feedback if you want.
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.
You can now also write the comments directly to your Model file, using the `--write (-W)` option. 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
*/
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
Note: With namespaces, uses `\\` instead of `\`: `php artisan ide-helper:models API\\User`
### License
The Laravel IDE Helper Generator is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
-123
View File
@@ -1,123 +0,0 @@
<?= '<?php' ?>
<?php
/**
* @var \Barryvdh\LaravelIdeHelper\Alias[][] $namespaces_by_alias_ns
* @var \Barryvdh\LaravelIdeHelper\Alias[][] $namespaces_by_extends_ns
* @var bool $include_fluent
* @var string $helpers
*/
?>
/* @noinspection ALL */
// @formatter:off
// phpcs:ignoreFile
/**
* A helper file for Laravel, to provide autocomplete information to your IDE
* Generated for Laravel <?= $version ?>.
*
* 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
*/
<?php foreach ($namespaces_by_extends_ns as $namespace => $aliases) : ?>
namespace <?= $namespace == '__root' ? '' : trim($namespace, '\\') ?> {
<?php foreach ($aliases as $alias) : ?>
<?= trim($alias->getDocComment(' ')) ?>
<?= $alias->getClassType() ?> <?= $alias->getExtendsClass() ?> {
<?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; ?>
<?php if ($method->isInstanceCall()) : ?>
/** @var <?=$method->getRoot()?> $instance */
<?php endif?>
<?= $method->shouldReturn() ? 'return ' : '' ?><?= $method->getRootMethodCall() ?>;
}
<?php endforeach; ?>
}
<?php endforeach; ?>
}
<?php endforeach; ?>
<?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 ($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; ?>
<?php if ($method->isInstanceCall()) : ?>
/** @var <?=$method->getRoot()?> $instance */
<?php endif?>
<?= $method->shouldReturn() ? 'return ' : '' ?><?= $method->getRootMethodCall() ?>;
}
<?php endforeach; ?>
<?php endif; ?>}
<?php endforeach; ?>
}
<?php endforeach; ?>
<?php foreach($real_time_facades as $name): ?>
<?php $nested = explode('\\', str_replace('\\' . class_basename($name), '', $name)); ?>
namespace <?php echo implode('\\', $nested); ?> {
/**
* @mixin <?= str_replace('Facades', '', $name) ?>
*/
class <?= class_basename($name) ?> extends <?= str_replace('Facades', '', $name) ?> {}
}
<?php endforeach; ?>
<?php if ($helpers) : ?>
namespace {
<?= $helpers ?>
}
<?php endif; ?>
<?php if ($include_fluent) : ?>
namespace Illuminate\Support {
/**
* Methods commonly used in migrations
*
* @method Fluent after(string $column) Add the after modifier
* @method Fluent charset(string $charset) Add the character set modifier
* @method Fluent collation(string $collation) Add the collation modifier
* @method Fluent comment(string $comment) Add comment
* @method Fluent default($value) Add the default modifier
* @method Fluent first() Select first row
* @method Fluent index(string $name = null) Add the in dex clause
* @method Fluent on(string $table) `on` of a foreign key
* @method Fluent onDelete(string $action) `on delete` of a foreign key
* @method Fluent onUpdate(string $action) `on update` of a foreign key
* @method Fluent primary() Add the primary key modifier
* @method Fluent references(string $column) `references` of a foreign key
* @method Fluent nullable(bool $value = true) Add the nullable modifier
* @method Fluent unique(string $name = null) Add unique index clause
* @method Fluent unsigned() Add the unsigned modifier
* @method Fluent useCurrent() Add the default timestamp value
* @method Fluent change() Add the change modifier
*/
class Fluent {}
}
<?php endif ?>
<?php foreach ($factories as $factory) : ?>
namespace <?=$factory->getNamespaceName()?> {
/**
* @method \Illuminate\Database\Eloquent\Collection|<?=$factory->getShortName()?>[]|<?=$factory->getShortName()?> create($attributes = [])
* @method \Illuminate\Database\Eloquent\Collection|<?=$factory->getShortName()?>[]|<?=$factory->getShortName()?> make($attributes = [])
*/
class <?=$factory->getShortName()?>FactoryBuilder extends \Illuminate\Database\Eloquent\FactoryBuilder {}
}
<?php endforeach; ?>
-68
View File
@@ -1,68 +0,0 @@
<?= '<?php' ?>
/* @noinspection ALL */
// @formatter:off
// phpcs:ignoreFile
namespace PHPSTORM_META {
/**
* PhpStorm Meta file, to provide autocomplete information for PhpStorm
*
* @author Barry vd. Heuvel <[email protected]>
* @see https://github.com/barryvdh/laravel-ide-helper
*/
<?php foreach ($methods as $method) : ?>
override(<?= $method ?>, map([
'' => '@',
<?php foreach ($bindings as $abstract => $class) : ?>
'<?= $abstract ?>' => \<?= $class ?>::class,
<?php endforeach; ?>
]));
<?php endforeach; ?>
<?php if (count($factories)) : ?>
override(\factory(0), map([
'' => '@FactoryBuilder',
<?php foreach ($factories as $factory) : ?>
'<?= $factory->getName() ?>' => \<?= $factory->getName() ?>FactoryBuilder::class,
<?php endforeach; ?>
]));
<?php endif; ?>
override(\Illuminate\Foundation\Testing\Concerns\InteractsWithContainer::mock(0), map(["" => "@&\Mockery\MockInterface"]));
override(\Illuminate\Foundation\Testing\Concerns\InteractsWithContainer::partialMock(0), map(["" => "@&\Mockery\MockInterface"]));
override(\Illuminate\Foundation\Testing\Concerns\InteractsWithContainer::instance(0), type(1));
override(\Illuminate\Foundation\Testing\Concerns\InteractsWithContainer::spy(0), map(["" => "@&\Mockery\MockInterface"]));
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));
override(\optional(0), type(0));
}
-474
View File
@@ -1,474 +0,0 @@
<?php
/**
* Laravel IDE Helper Generator
*
* @author Barry vd. Heuvel <[email protected]>
* @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\Serializer as DocBlockSerializer;
use Barryvdh\Reflection\DocBlock\Tag\MethodTag;
use Closure;
use Illuminate\Config\Repository as ConfigRepository;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Support\Facades\Facade;
use ReflectionClass;
use Throwable;
class Alias
{
protected $alias;
/** @psalm-var class-string $facade */
protected $facade;
protected $extends = null;
protected $extendsClass = null;
protected $extendsNamespace = null;
protected $classType = 'class';
protected $short;
protected $namespace = '__root';
protected $root = null;
protected $classes = [];
protected $methods = [];
protected $usedMethods = [];
protected $valid = false;
protected $magicMethods = [];
protected $interfaces = [];
protected $phpdoc = null;
protected $classAliases = [];
/** @var ConfigRepository */
protected $config;
/**
* @param ConfigRepository $config
* @param string $alias
* @psalm-param class-string $facade
* @param string $facade
* @param array $magicMethods
* @param array $interfaces
*/
public function __construct($config, $alias, $facade, $magicMethods = [], $interfaces = [])
{
$this->alias = $alias;
$this->magicMethods = $magicMethods;
$this->interfaces = $interfaces;
$this->config = $config;
// Make the class absolute
$facade = '\\' . ltrim($facade, '\\');
$this->facade = $facade;
$this->detectRoot();
if (!$this->root || $this->isTrait()) {
return;
}
$this->valid = true;
$this->addClass($this->root);
$this->detectFake();
$this->detectNamespace();
$this->detectClassType();
$this->detectExtendsNamespace();
if (!empty($this->namespace)) {
$this->classAliases = (new UsesResolver())->loadFromClass($this->root);
//Create a DocBlock and serializer instance
$this->phpdoc = new DocBlock(new ReflectionClass($alias), new Context($this->namespace, $this->classAliases));
}
if ($facade === '\Illuminate\Database\Eloquent\Model') {
$this->usedMethods = ['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 class short name which this alias extends
*
* @return null|string
*/
public function getExtendsClass()
{
return $this->extendsClass;
}
/**
* Get the namespace of the class which this alias extends
*
* @return null|string
*/
public function getExtendsNamespace()
{
return $this->extendsNamespace;
}
/**
* 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|Method[]
*/
public function getMethods()
{
if (count($this->methods) > 0) {
return $this->methods;
}
$this->addMagicMethods();
$this->detectMethods();
return $this->methods;
}
/**
* Detect class returned by ::fake()
*/
protected function detectFake()
{
$facade = $this->facade;
if (!is_subclass_of($facade, Facade::class)) {
return;
}
if (!method_exists($facade, 'fake')) {
return;
}
$real = $facade::getFacadeRoot();
try {
$facade::fake();
$fake = $facade::getFacadeRoot();
if ($fake !== $real) {
$this->addClass(get_class($fake));
}
} finally {
$facade::swap($real);
}
}
/**
* Detect the namespace
*/
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 extends namespace
*/
protected function detectExtendsNamespace()
{
if (strpos($this->extends, '\\') !== false) {
$nsParts = explode('\\', $this->extends);
$this->extendsClass = array_pop($nsParts);
$this->extendsNamespace = implode('\\', $nsParts);
}
}
/**
* 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 (Throwable $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
return trait_exists($this->facade);
}
/**
* Add magic methods, as defined in the configuration files
*/
protected function addMagicMethods()
{
foreach ($this->magicMethods as $magic => $real) {
[$className, $name] = explode('::', $real);
if ((!class_exists($className) && !interface_exists($className)) || !method_exists($className, $name)) {
continue;
}
$method = new \ReflectionMethod($className, $name);
$class = new ReflectionClass($className);
if (!in_array($magic, $this->usedMethods)) {
if ($class !== $this->root) {
$this->methods[] = new Method($method, $this->alias, $class, $magic, $this->interfaces, $this->classAliases);
}
$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->classAliases
);
}
$this->usedMethods[] = $method->name;
}
}
}
// Check if the class is macroable
// (Eloquent\Builder is also macroable but doesn't use Macroable trait)
$traits = collect($reflection->getTraitNames());
if ($traits->contains('Illuminate\Support\Traits\Macroable') || $class === EloquentBuilder::class) {
$properties = $reflection->getStaticProperties();
$macros = isset($properties['macros']) ? $properties['macros'] : [];
foreach ($macros as $macro_name => $macro_func) {
if (!in_array($macro_name, $this->usedMethods)) {
// Add macros
$this->methods[] = new Macro(
$this->getMacroFunction($macro_func),
$this->alias,
$reflection,
$macro_name,
$this->interfaces,
$this->classAliases
);
$this->usedMethods[] = $macro_name;
}
}
}
}
}
/**
* @param $macro_func
*
* @return \ReflectionFunctionAbstract
* @throws \ReflectionException
*/
protected function getMacroFunction($macro_func)
{
if (is_array($macro_func) && is_callable($macro_func)) {
return new \ReflectionMethod($macro_func[0], $macro_func[1]);
}
if (is_object($macro_func) && is_callable($macro_func) && !$macro_func instanceof Closure) {
return new \ReflectionMethod($macro_func, '__invoke');
}
return new \ReflectionFunction($macro_func);
}
/*
* Get the docblock for this alias
*
* @param string $prefix
* @return mixed
*/
public function getDocComment($prefix = "\t\t")
{
$serializer = new DocBlockSerializer(1, $prefix);
if (!$this->phpdoc) {
return '';
}
if ($this->config->get('ide-helper.include_class_docblocks')) {
// if a class doesn't expose any DocBlock tags
// we can perform reflection on the class and
// add in the original class DocBlock
if (count($this->phpdoc->getTags()) === 0) {
$class = new ReflectionClass($this->root);
$this->phpdoc = new DocBlock($class->getDocComment());
}
}
$this->removeDuplicateMethodsFromPhpDoc();
return $serializer->getDocComment($this->phpdoc);
}
/**
* Removes method tags from the doc comment that already appear as functions inside the class.
* This prevents duplicate function errors in the IDE.
*
* @return void
*/
protected function removeDuplicateMethodsFromPhpDoc()
{
$methodNames = array_map(function (Method $method) {
return $method->getName();
}, $this->getMethods());
foreach ($this->phpdoc->getTags() as $tag) {
if ($tag instanceof MethodTag && in_array($tag->getMethodName(), $methodNames)) {
$this->phpdoc->deleteTag($tag);
}
}
}
/**
* Output an error.
*
* @param string $string
* @return void
*/
protected function error($string)
{
echo $string . "\r\n";
}
}
+454
View File
@@ -0,0 +1,454 @@
<?php
/**
* Laravel IDE Helper Generator
*
* @author Barry vd. Heuvel <[email protected]>
* @copyright 2013 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\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Illuminate\Foundation\AliasLoader;
use Barryvdh\Reflection\DocBlock;
use Barryvdh\Reflection\DocBlock\Context;
use Barryvdh\Reflection\DocBlock\Tag;
use Barryvdh\Reflection\DocBlock\Serializer as DocBlockSerializer;
/**
* A command to generate autocomplete information for your IDE
*
* @author Barry vd. Heuvel <[email protected]>
*/
class GeneratorCommand extends Command {
/**
* The console command name.
*
* @var string
*/
protected $name = 'ide-helper:generate';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Generate a new IDE Helper file.';
protected $extra;
protected $onlyExtend;
protected $helpers;
/**
* Execute the console command.
*
* @return void
*/
public function fire()
{
if (file_exists($compiled = base_path().'/bootstrap/compiled.php')){
$this->error('Error generating IDE Helper: first delete bootstrap/compiled.php (php artisan clear-compiled)');
}else{
$filename = $this->argument('filename');
if($this->option('memory')){
$this->useMemoryDriver();
}
$this->extra = \Config::get('laravel-ide-helper::extra');
if( $this->option('helpers') || (\Config::get('laravel-ide-helper::include_helpers') )){
$this->helpers = \Config::get('laravel-ide-helper::helper_files');
}else{
$this->helpers = array();
}
$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(){
//Use a sqlite database in memory, to avoid connection errors on Database facades
\Config::set('database.connections.sqlite',array(
'driver' => 'sqlite',
'database' => ':memory:',
));
\Config::set('database.default', 'sqlite');
}
/**
* Get the console command arguments.
*
* @return array
*/
protected function getArguments()
{
return array(
array('filename', InputArgument::OPTIONAL, 'The path to the helper file', \Config::get('laravel-ide-helper::filename')),
);
}
/**
* Get the console command options.
*
* @return array
*/
protected function getOptions()
{
return array(
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'),
);
}
/**
* Generate the docs for all facades in the AliasLoader
*
* @return string
*/
protected function generateDocs(){
$aliasLoader = AliasLoader::getInstance();
$output = "<?php
/**
* An helper file for Laravel 4, to provide autocomplete information to your IDE
* Generated with https://github.com/barryvdh/laravel-ide-helper
*
* @author Barry vd. Heuvel <[email protected]>
*/
exit('Only to be used as an helper for your IDE');\n\n";
//Get all aliases
$aliases = $aliasLoader->getAliases();
foreach($aliases as $alias => $facade){
$root = $this->getRoot($facade);
if(!$root){
continue;
}
try{
//Some classes extend the facade
if(class_exists($facade)){
$output .= "class $alias extends $facade{\n";
}else{
$output .= "class $alias{\n";
}
$usedMethods = array();
//Only add the methods to the output when the root is not the same as the facade.
$addOutput = ($root !== $facade);
$output .= $this->getMethods($root, $alias, $usedMethods, $addOutput);
$driver = $this->getDriver($alias);
if($driver){
$output .= $this->getMethods($driver, $alias, $usedMethods);
}
//Add extra methods, from other classes (magic static calls)
if(array_key_exists($alias, $this->extra)){
$output .= $this->getMethods($this->extra[$alias], $alias, $usedMethods);
}
$output .= "}\n\n";
}catch(\Exception $e){
$this->error("Exception: ".$e->getMessage()."\nCould not analyze $root.");
}
}
//Include the helper file, if requested
if(!empty($helpers)){
foreach($helpers as $helper){
if (file_exists($helper)){
$output .= str_replace(array('<?php', '?>'), '', \File::get($helper));
}
}
}
return $output;
}
/**
* Get the real root of a facade
*
* @param $facade
* @return bool|string
*/
protected function getRoot($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)){
$this->error("Class $root is not found.");
return false;
}
return $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.");
return false;
}catch(\Exception $e){
$this->error("Exception: ".$e->getMessage()."\nSkipping $facade.");
return false;
}
}
public function getDriver($alias){
try{
if($alias == "Auth"){
$driver = \Auth::driver();
}elseif($alias == "DB"){
$driver = \DB::connection();
}elseif($alias == "Cache"){
$driver = \Cache::driver();
}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;
}
}
/**
* Get the methods for one or multiple classes.
*
* @param $classes
* @param $alias
* @param $usedMethods
* @param bool $addOutput
* @return string
*/
protected function getMethods($classes, $alias, &$usedMethods, $addOutput = true){
if(!is_array($classes)){
$classes = array($classes);
}
$output = '';
foreach($classes as $class){
if(!class_exists($class) && !interface_exists($class)){
continue;
}
$reflection = new \ReflectionClass($class);
$methods = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC);
if($methods)
{
foreach ($methods as $method)
{
if(!in_array($method->name, $usedMethods)){
if( $addOutput){
$output .= $this->parseMethod($method, $alias, $reflection);
}
$usedMethods[] = $method->name;
}
}
}
}
return $output;
}
/**
* @param \ReflectionMethod $method
* @param string $alias
* @return string
*/
protected function parseMethod($method, $alias, $class){
$output = '';
// Don't add the __clone() functions
if($method->name === '__clone'){
return $output;
}
$namespace = $method->getDeclaringClass()->getNamespaceName();
//Create a DocBlock and serializer instance
$phpdoc = new DocBlock($method, new Context($namespace));
$serializer = new DocBlockSerializer(1, "\t");
//Normalize the description and inherit the docs from parents/interfaces
$this->normalizeDescription($phpdoc, $method);
//Correct the return values
$returnValue = $this->normalizeReturn($phpdoc, $method, $alias);
//Get the parameters, including formatted default values
list($params, $paramsWithDefault) = $this->getParameters($method);
//Make the method static
$phpdoc->appendTag(Tag::createInstance('@static', $phpdoc));
//Write the output, using the DocBlock serializer
$output .= $serializer->getDocComment($phpdoc) ."\n\t public static function ".$method->name."(";
$output .= implode($paramsWithDefault, ", ");
$output .= "){\r\n";
//Only return when not a constructor and not void.
$return = ($returnValue && $returnValue !== "void" && $method->name !== "__construct") ? 'return' : '';
//Reference the 'real' function in the declaringclass
$declaringClass = $method->getDeclaringClass();
$root = $class->getName();
if($declaringClass->name != $root){
$output .= "\t\t//Method inherited from $declaringClass->name\r\n";
}
$output .= "\t\t$return $root::";
//Write the default parameters in the function call
$output .= $method->name."(".implode($params, ", ").");\r\n";
$output .= "\t }\n\n";
return $output;
}
/**
* Get the description and get the inherited docs.
*
* @param $phpdoc
* @param $method
*/
protected function normalizeDescription(&$phpdoc, $method){
//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($method);
$inheritDescription = $inheritdoc->getText();
$description = str_replace('{@inheritdoc}', $inheritDescription, $description);
$phpdoc->setText($description);
//Add the tags that are inherited
$inheritTags = $inheritdoc->getTags();
if($inheritTags){
foreach($inheritTags as $tag){
$tag->setDocBlock();
$phpdoc->appendTag($tag);
}
}
}
}
/**
* Make some changes to the return types, if needed.
*
* @param $phpdoc
* @param $method
* @param $alias
* @return null
*/
protected function normalizeReturn(&$phpdoc, $method, $alias){
//Get the return type and adjust them for beter autocomplete
$returnTags = $phpdoc->getTagsByName('return');
if($returnTags){
/** @var $tag */
$tag = reset($returnTags);
$returnValue = $tag->getType();
if($method->name == "__construct"){
$tag->setType('self');
}elseif($alias == 'Eloquent' and in_array($method->name, array('hasOne', 'hasMany', 'belongsTo', 'belongsToMany', 'morphOne', 'morphTo', 'morphMany'))){
$tag->addType('\Eloquent');
}
}else{
$returnValue = null;
}
return $returnValue;
}
/**
* 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->getDefaultValue();
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;
}
return array($params, $paramsWithDefault);
}
/**
* @param \ReflectionMethod $reflectionMethod
* @return string
*/
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){
$phpdoc = new DocBlock($method);
if(strpos($phpdoc->getText(), '{@inheritdoc}') !== false ){
//Not at the end yet, try another parent/interface..
return $this->getInheritDoc($method);
}else{
return $phpdoc;
}
}
}
}
@@ -0,0 +1,65 @@
<?php
/**
* Laravel IDE Helper Generator
*
* @author Barry vd. Heuvel <[email protected]>
* @copyright 2013 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\Support\ServiceProvider;
class IdeHelperServiceProvider extends ServiceProvider {
/**
* Indicates if loading of the provider is deferred.
*
* @var bool
*/
protected $defer = false;
/**
* Bootstrap the application events.
*
* @return void
*/
public function boot()
{
$this->package('barryvdh/laravel-ide-helper');
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->app['command.ide-helper.generate'] = $this->app->share(function($app)
{
return new GeneratorCommand;
});
$this->commands('command.ide-helper.generate');
$this->app['command.ide-helper.models'] = $this->app->share(function($app)
{
return new ModelsCommand();
});
$this->commands('command.ide-helper.models');
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return array('command.ide-helper.generate', 'command.ide-helper.models');
}
}
@@ -0,0 +1,390 @@
<?php
/**
* Laravel IDE Helper Generator
*
* @author Barry vd. Heuvel <[email protected]>
* @copyright 2013 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\Console\Command;
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;
/**
* A command to generate autocomplete information for your IDE
*
* @author Barry vd. Heuvel <[email protected]>
*/
class ModelsCommand extends Command {
/**
* The console command name.
*
* @var string
*/
protected $name = 'ide-helper:models';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Generate autocompletion for models';
protected $properties = array();
protected $methods = array();
protected $write = false;
protected $dir;
protected $reset;
/**
* Execute the console command.
*
* @return void
*/
public function fire()
{
$filename = $this->option('filename');
$this->write = $this->option('write');
$this->dir = $this->option('dir');
$model = $this->argument('model');
$this->reset = $this->option('reset');
$content = $this->generateDocs($model);
if(!$this->write){
$written = \File::put($filename, $content);
if($written !== false){
$this->info("Model information was written to $filename");
}else{
$this->error("Failed to write model information to $filename");
}
}
}
/**
* Get the console command arguments.
*
* @return array
*/
protected function getArguments()
{
return array(
array('model', InputArgument::OPTIONAL, 'Which models to include', '*'),
);
}
/**
* Get the console command options.
*
* @return array
*/
protected function getOptions()
{
return array(
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'),
array('reset', 'R', InputOption::VALUE_NONE, 'Remove the original phpdocs instead of appending'),
);
}
protected function generateDocs($model){
$output = "<?php
/**
* An helper file for your Eloquent Models
* Copy the phpDocs from this file to the correct Model,
* And remove them from this file, to prevent double declarations.
*
* @author Barry vd. Heuvel <[email protected]>
*/
\n\n";
if($model === '*'){
$models = $this->loadModels();
}else{
$models = explode(',', $model);
}
foreach($models as $name){
$this->properties = array();
$this->methods = array();
if(class_exists($name)){
try{
$model = new $name();
$this->getPropertiesFromTable($model);
$this->getPropertiesFromMethods($model);
$output .= $this->createPhpDocs($name);
}catch(\Exception $e){
$this->error("Exception: ".$e->getMessage()."\nCould not analyze class $name.");
}
}else{
$this->error("Class $name does not exist");
}
}
return $output;
}
protected function loadModels(){
$dir = base_path().'/'.$this->dir;
$models = array();
if(file_exists($dir)){
foreach(ClassMapGenerator::createMap($dir) as $model=> $path){
$models[] = $model;
}
}
return $models;
}
/**
* Load the properties from the database table.
*
* @param \Illuminate\Database\Eloquent\Model $model
*/
protected function getPropertiesFromTable($model){
$table = $model->getTable();
$schema = $model->getConnection()->getDoctrineSchemaManager($table);
$schema->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string');
$columns = $schema->listTableColumns($table);
if($columns){
foreach ($columns as $column) {
$name = $column->getName();
$type = $column->getType()->getName();
switch($type){
case 'string':
case 'text':
case 'date':
case 'time':
case 'guid':
$type = 'string';
break;
case 'integer':
case 'bigint':
case 'smallint':
$type = 'integer';
break;
case 'decimal':
case 'float':
$type = 'float';
break;
case 'boolean':
$type = 'boolean';
break;
case 'datetimetz': //String or DateTime, depending on $dates
case 'datetime':
$type = '\Carbon\Carbon';
break;
default:
$type = 'mixed';
break;
}
$this->setProperty($name, $type, true, true);
}
}
}
/**
* @param \Illuminate\Database\Eloquent\Model $model
*/
protected function getPropertiesFromMethods($model){
$methods = get_class_methods($model);
if($methods){
foreach($methods as $method){
if(\Str::startsWith($method, 'get') && \Str::endsWith($method, 'Attribute') && $method !== 'setAttribute'){
//Magic get<name>Attribute
$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'){
//Magic set<name>Attribute
$name = \Str::snake(substr($method, 3, -9));
if(!empty($name)){
$this->setProperty($name, null, null, true);
}
}elseif(\Str::startsWith($method, 'scope') && $method !== 'scopeQuery'){
//Magic set<name>Attribute
$name = \Str::snake(substr($method, 5));
if(!empty($name)){
$this->setMethod($name, 'static');
}
}elseif(!method_exists('Eloquent', $method) && !\Str::startsWith($method, 'get')){
//Use reflection to inspect the code, based on Illuminate/Support/SerializableClosure.php
$reflection = new \ReflectionMethod($model, $method);
$file = new \SplFileObject($reflection->getFileName());
$file->seek($reflection->getStartLine() - 1);
$code = '';
while ($file->key() < $reflection->getEndLine())
{
$code .= $file->current(); $file->next();
}
$begin = strpos($code, 'function(');
$code = substr($code, $begin, strrpos($code, '}') - $begin + 1);
$begin = stripos($code, 'return $this->');
$parts = explode("'", substr($code, $begin+14),3); //"return $this->" is 14 chars
if (isset($parts[2]))
{
list($relation, $returnModel, $rest) = $parts;
$returnModel = "\\".ltrim($returnModel, "\\");
$relation = trim($relation, ' (');
if($relation === "belongsTo" or $relation === 'hasOne'){
//Single model is returned
$this->setProperty($method, $returnModel, true, null);
}elseif($relation === "belongsToMany" or $relation === 'hasMany'){
//Collection or array of models (because Collection is Arrayable)
$this->setProperty($method, '\Illuminate\Database\Eloquent\Collection|'.$returnModel.'[]', true, null);
}
}else{
//Not a relation
}
}
}
}
}
/**
* @param string $name
* @param string|null $type
* @param bool|null $read
* @param bool|null $write
*/
protected function setProperty($name, $type = null, $read = null, $write = null){
if(!isset($this->properties[$name])){
$this->properties[$name] = array();
$this->properties[$name]['type'] = 'mixed';
$this->properties[$name]['read'] = false;
$this->properties[$name]['write'] = false;
}
if($type !== null){
$this->properties[$name]['type'] = $type;
}
if($read !== null){
$this->properties[$name]['read'] = $read;
}
if($write !== null){
$this->properties[$name]['write'] = $write;
}
}
protected function setMethod($name, $type = null){
if(!isset($this->methods[$name])){
$this->methods[$name] = array();
$this->methods[$name]['type'] = 'static';
}
if($type !== null){
$this->methods[$name]['type'] = $type;
}
}
/**
* @param string $class
* @return string
*/
protected function createPhpDocs($class){
$reflection = new \ReflectionClass($class);
$namespace = $reflection->getNamespaceName();
$classname = $reflection->getShortName();
$originalDoc = $reflection->getDocComment();
if($this->reset){
$phpdoc = new DocBlock('', new Context($namespace));
}else{
$phpdoc = new DocBlock($reflection, new Context($namespace));
}
if(!$phpdoc->getText()){
$phpdoc->setText("An Eloquent Model: '$class'");
}
$properties = array();
$methods = array();
foreach($phpdoc->getTags() as $tag){
$name = $tag->getName();
if($name == "property" || $name == "property-read" || $name == "property-write"){
$properties[] =$tag->getVariableName();
}elseif($name == "method"){
$methods[] = $tag->getMethodName();
}
}
foreach($this->properties as $name => $property){
$name = "\$$name";
if(in_array($name, $properties)){
continue;
}
if($property['read'] && $property['write']){
$attr = 'property';
}elseif($property['write']){
$attr = 'property-write';
}else{
$attr = 'property-read';
}
$tag = Tag::createInstance("@{$attr} {$property['type']} {$name}", $phpdoc);
$phpdoc->appendTag($tag);
}
foreach($this->methods as $name => $method){
if(in_array($name, $methods)){
continue;
}
$name = "$name()";
$tag = Tag::createInstance("@method {$method['type']} {$name}", $phpdoc);
$phpdoc->appendTag($tag);
}
$serializer = new DocBlockSerializer();
$serializer->getDocComment($phpdoc);
$docComment = $serializer->getDocComment($phpdoc);
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;
}
}
-62
View File
@@ -1,62 +0,0 @@
<?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);
}
}
-174
View File
@@ -1,174 +0,0 @@
<?php
/**
* Laravel IDE Helper Generator
*
* @author Barry vd. Heuvel <[email protected]>
* @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\Console;
use Barryvdh\LaravelIdeHelper\Eloquent;
use Barryvdh\LaravelIdeHelper\Generator;
use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
/**
* A command to generate autocomplete information for your IDE
*
* @author Barry vd. Heuvel <[email protected]>
*/
class GeneratorCommand extends Command
{
/**
* The console command name.
*
* @var string
*/
protected $name = 'ide-helper:generate';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Generate a new IDE Helper file.';
/** @var \Illuminate\Config\Repository */
protected $config;
/** @var Filesystem */
protected $files;
/** @var \Illuminate\View\Factory */
protected $view;
protected $onlyExtend;
/**
*
* @param \Illuminate\Config\Repository $config
* @param Filesystem $files
* @param \Illuminate\View\Factory $view
*/
public function __construct(
/*ConfigRepository */
$config,
Filesystem $files,
/* Illuminate\View\Factory */
$view
) {
$this->config = $config;
$this->files = $files;
$this->view = $view;
parent::__construct();
}
/**
* Execute the console command.
*
* @return void
*/
public function handle()
{
if (
file_exists(base_path() . '/vendor/compiled.php') ||
file_exists(base_path() . '/bootstrap/cache/compiled.php') ||
file_exists(base_path() . '/storage/framework/compiled.php')
) {
$this->error(
'Error generating IDE Helper: first delete your compiled file (php artisan clear-compiled)'
);
return;
}
$filename = $this->argument('filename');
// Add the php extension if missing
// This is a backwards-compatible shim and can be removed in the future
if (substr($filename, -4, 4) !== '.php') {
$filename .= '.php';
}
if ($this->option('memory')) {
$this->useMemoryDriver();
}
$helpers = '';
if ($this->option('helpers') || ($this->config->get('ide-helper.include_helpers'))) {
foreach ($this->config->get('ide-helper.helper_files', []) as $helper) {
if (file_exists($helper)) {
$helpers .= str_replace(['<?php', '?>'], '', $this->files->get($helper));
}
}
} else {
$helpers = '';
}
$generator = new Generator($this->config, $this->view, $this->getOutput(), $helpers);
$content = $generator->generate();
$written = $this->files->put($filename, $content);
if ($written !== false) {
$this->info("A new helper file was written to $filename");
if ($this->option('write_mixins')) {
Eloquent::writeEloquentModelHelper($this, $this->files);
}
} else {
$this->error("The helper file could not be created at $filename");
}
}
protected function useMemoryDriver()
{
//Use a sqlite database in memory, to avoid connection errors on Database facades
$this->config->set(
'database.connections.sqlite',
[
'driver' => 'sqlite',
'database' => ':memory:',
]
);
$this->config->set('database.default', 'sqlite');
}
/**
* Get the console command arguments.
*
* @return array
*/
protected function getArguments()
{
$filename = $this->config->get('ide-helper.filename');
return [
[
'filename', InputArgument::OPTIONAL, 'The path to the helper file', $filename,
],
];
}
/**
* Get the console command options.
*
* @return array
*/
protected function getOptions()
{
$writeMixins = $this->config->get('ide-helper.write_eloquent_model_mixins');
return [
['write_mixins', 'W', InputOption::VALUE_OPTIONAL, 'Write mixins to Laravel Model?', $writeMixins],
['helpers', 'H', InputOption::VALUE_NONE, 'Include the helper files'],
['memory', 'M', InputOption::VALUE_NONE, 'Use sqlite memory driver'],
];
}
}
-187
View File
@@ -1,187 +0,0 @@
<?php
/**
* Laravel IDE Helper Generator
*
* @author Barry vd. Heuvel <[email protected]>
* @copyright 2015 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\Console;
use Barryvdh\LaravelIdeHelper\Factories;
use Illuminate\Console\Command;
use RuntimeException;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* A command to generate phpstorm meta data
*
* @author Barry vd. Heuvel <[email protected]>
*/
class MetaCommand extends Command
{
/**
* The console command name.
*
* @var string
*/
protected $name = 'ide-helper:meta';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Generate metadata for PhpStorm';
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
protected $files;
/** @var \Illuminate\Contracts\View\Factory */
protected $view;
/** @var \Illuminate\Contracts\Config\Repository */
protected $config;
protected $methods = [
'new \Illuminate\Contracts\Container\Container',
'\Illuminate\Container\Container::makeWith(0)',
'\Illuminate\Contracts\Container\Container::get(0)',
'\Illuminate\Contracts\Container\Container::make(0)',
'\Illuminate\Contracts\Container\Container::makeWith(0)',
'\App::get(0)',
'\App::make(0)',
'\App::makeWith(0)',
'\app(0)',
'\resolve(0)',
'\Psr\Container\ContainerInterface::get(0)',
];
/**
*
* @param \Illuminate\Contracts\Filesystem\Filesystem $files
* @param \Illuminate\Contracts\View\Factory $view
* @param \Illuminate\Contracts\Config\Repository $config
*/
public function __construct($files, $view, $config)
{
$this->files = $files;
$this->view = $view;
$this->config = $config;
parent::__construct();
}
/**
* Execute the console command.
*
* @return void
*/
public function handle()
{
// Needs to run before exception handler is registered
$factories = $this->config->get('ide-helper.include_factory_builders') ? Factories::all() : [];
$ourAutoloader = $this->registerClassAutoloadExceptions();
$bindings = [];
foreach ($this->getAbstracts() as $abstract) {
// Validator and seeder cause problems
if (in_array($abstract, ['validator', 'seeder'])) {
continue;
}
try {
$concrete = $this->laravel->make($abstract);
if ($concrete === null) {
throw new RuntimeException("Cannot create instance for '$abstract', received 'null'");
}
$reflectionClass = new \ReflectionClass($concrete);
if (is_object($concrete) && !$reflectionClass->isAnonymous()) {
$bindings[$abstract] = get_class($concrete);
}
} catch (\Throwable $e) {
if ($this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
$this->comment("Cannot make '$abstract': " . $e->getMessage());
}
}
}
$this->unregisterClassAutoloadExceptions($ourAutoloader);
$content = $this->view->make('meta', [
'bindings' => $bindings,
'methods' => $this->methods,
'factories' => $factories,
])->render();
$filename = $this->option('filename');
$written = $this->files->put($filename, $content);
if ($written !== false) {
$this->info("A new meta file was written to $filename");
} else {
$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()
{
$abstracts = $this->laravel->getBindings();
// Return the abstract names only
$keys = array_keys($abstracts);
sort($keys);
return $keys;
}
/**
* Register an autoloader the throws exceptions when a class is not found.
*
* @return callable
*/
protected function registerClassAutoloadExceptions(): callable
{
$autoloader = function ($class) {
throw new \ReflectionException("Class '$class' not found.");
};
spl_autoload_register($autoloader);
return $autoloader;
}
/**
* Get the console command options.
*
* @return array
*/
protected function getOptions()
{
$filename = $this->config->get('ide-helper.meta_filename');
return [
['filename', 'F', InputOption::VALUE_OPTIONAL, 'The path to the meta file', $filename],
];
}
/**
* Remove our custom autoloader that we pushed onto the autoload stack
*
* @param callable $ourAutoloader
*/
private function unregisterClassAutoloadExceptions(callable $ourAutoloader): void
{
spl_autoload_unregister($ourAutoloader);
}
}
File diff suppressed because it is too large Load Diff
-11
View File
@@ -1,11 +0,0 @@
<?php
namespace Barryvdh\LaravelIdeHelper\Contracts;
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
use Illuminate\Database\Eloquent\Model;
interface ModelHookInterface
{
public function run(ModelsCommand $command, Model $model): void;
}
-113
View File
@@ -1,113 +0,0 @@
<?php
/**
* Laravel IDE Helper to add \Eloquent mixin to Eloquent\Model
*
* @author Charles A. Peterson <[email protected]>
*/
namespace Barryvdh\LaravelIdeHelper;
use Barryvdh\Reflection\DocBlock;
use Barryvdh\Reflection\DocBlock\Context;
use Barryvdh\Reflection\DocBlock\Serializer as DocBlockSerializer;
use Barryvdh\Reflection\DocBlock\Tag;
use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
class Eloquent
{
/**
* Write mixin helper to the Eloquent\Model
* This is needed since laravel/framework v5.4.29
*
* @param Command $command
* @param Filesystem $files
*
* @return void
*/
public static function writeEloquentModelHelper(Command $command, Filesystem $files)
{
$class = 'Illuminate\Database\Eloquent\Model';
$reflection = new \ReflectionClass($class);
$namespace = $reflection->getNamespaceName();
$originalDoc = $reflection->getDocComment();
if (!$originalDoc) {
$command->info('Unexpected no document on ' . $class);
}
$phpdoc = new DocBlock($reflection, new Context($namespace));
$mixins = $phpdoc->getTagsByName('mixin');
$expectedMixins = [
'\Eloquent' => false,
'\Illuminate\Database\Eloquent\Builder' => false,
'\Illuminate\Database\Query\Builder' => false,
];
foreach ($mixins as $m) {
$mixin = $m->getContent();
if (isset($expectedMixins[$mixin])) {
$command->info('Tag Exists: @mixin ' . $mixin . ' in ' . $class);
$expectedMixins[$mixin] = true;
}
}
$changed = false;
foreach ($expectedMixins as $expectedMixin => $present) {
if ($present === false) {
$phpdoc->appendTag(Tag::createInstance('@mixin ' . $expectedMixin, $phpdoc));
$changed = true;
}
}
// If nothing's changed, stop here.
if (!$changed) {
return;
}
$serializer = new DocBlockSerializer();
$serializer->getDocComment($phpdoc);
$docComment = $serializer->getDocComment($phpdoc);
/*
The new DocBlock is appended to the beginning of the class declaration.
Since there is no DocBlock, the declaration is used as a guide.
*/
if (!$originalDoc) {
$originalDoc = 'abstract class Model implements';
$docComment .= "\nabstract class Model implements";
}
$filename = $reflection->getFileName();
if (!$filename) {
$command->error('Filename not found ' . $class);
return;
}
$contents = $files->get($filename);
if (!$contents) {
$command->error('No file contents found ' . $filename);
return;
}
$count = 0;
$contents = str_replace($originalDoc, $docComment, $contents, $count);
if ($count <= 0) {
$command->error('Content did not change ' . $contents);
return;
}
if (!$files->put($filename, $contents)) {
$command->error('File write failed to ' . $filename);
return;
}
$command->info('Wrote expected docblock to ' . $filename);
}
}
-36
View File
@@ -1,36 +0,0 @@
<?php
namespace Barryvdh\LaravelIdeHelper;
use Exception;
use Illuminate\Database\Eloquent\Factory;
use ReflectionClass;
class Factories
{
public static function all()
{
$factories = [];
if (static::isLaravelSevenOrLower()) {
$factory = app(Factory::class);
$definitions = (new ReflectionClass(Factory::class))->getProperty('definitions');
$definitions->setAccessible(true);
foreach ($definitions->getValue($factory) as $factory_target => $config) {
try {
$factories[] = new ReflectionClass($factory_target);
} catch (Exception $exception) {
}
}
}
return $factories;
}
protected static function isLaravelSevenOrLower()
{
return class_exists('Illuminate\Database\Eloquent\Factory');
}
}
-362
View File
@@ -1,362 +0,0 @@
<?php
/**
* Laravel IDE Helper Generator
*
* @author Barry vd. Heuvel <[email protected]>
* @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\Support\Collection;
use Illuminate\Support\Facades\Facade;
use Illuminate\Support\Str;
use Illuminate\Support\Traits\Macroable;
use PhpParser\Lexer\Emulative;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Namespace_;
use PhpParser\Parser\Php7;
use ReflectionClass;
use Symfony\Component\Console\Output\OutputInterface;
class Generator
{
/** @var \Illuminate\Config\Repository */
protected $config;
/** @var \Illuminate\View\Factory */
protected $view;
/** @var OutputInterface */
protected $output;
protected $extra = [];
protected $magic = [];
protected $interfaces = [];
protected $helpers;
/**
* @param \Illuminate\Config\Repository $config
* @param \Illuminate\View\Factory $view
* @param 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('ide-helper.extra'), []);
$this->magic = array_merge($this->magic, $this->config->get('ide-helper.magic'), []);
$this->interfaces = array_merge($this->interfaces, $this->config->get('ide-helper.interfaces'), []);
// Make all interface classes absolute
foreach ($this->interfaces as &$interface) {
$interface = '\\' . ltrim($interface, '\\');
}
$this->helpers = $helpers;
}
/**
* Generate the helper file contents;
*
* @return string;
*/
public function generate()
{
$app = app();
return $this->view->make('helper')
->with('namespaces_by_extends_ns', $this->getAliasesByExtendsNamespace())
->with('namespaces_by_alias_ns', $this->getAliasesByAliasNamespace())
->with('real_time_facades', $this->getRealTimeFacades())
->with('helpers', $this->helpers)
->with('version', $app->version())
->with('include_fluent', $this->config->get('ide-helper.include_fluent', true))
->with('factories', $this->config->get('ide-helper.include_factory_builders') ? Factories::all() : [])
->render();
}
protected function detectDrivers()
{
$defaultUserModel = config('auth.providers.users.model', config('auth.model', 'App\User'));
$this->interfaces['\Illuminate\Contracts\Auth\Authenticatable'] = $defaultUserModel;
try {
if (
class_exists('Auth') && is_a('Auth', '\Illuminate\Support\Facades\Auth', true)
&& app()->bound('auth')
) {
$class = get_class(\Auth::guard());
$this->extra['Auth'] = [$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'] = [$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'] = [$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'] = [$class];
$this->interfaces['\Illuminate\Queue\QueueInterface'] = $class;
}
} catch (\Exception $e) {
}
try {
if (class_exists('Storage') && is_a('Storage', '\Illuminate\Support\Facades\Storage', true)) {
$class = get_class(\Storage::disk());
$this->extra['Storage'] = [$class];
$this->interfaces['\Illuminate\Contracts\Filesystem\Filesystem'] = $class;
}
} catch (\Exception $e) {
}
}
/**
* Find all aliases that are valid for us to render
*
* @return Collection
*/
protected function getValidAliases()
{
$aliases = new Collection();
// Get all aliases
foreach ($this->getAliases() as $name => $facade) {
// Skip the Redis facade, if not available (otherwise Fatal PHP Error)
if ($facade == 'Illuminate\Support\Facades\Redis' && $name == 'Redis' && !class_exists('Predis\Client')) {
continue;
}
// Skip the swoole
if ($facade == 'SwooleTW\Http\Server\Facades\Server' && $name == 'Server' && !class_exists('Swoole\Http\Server')) {
continue;
}
$magicMethods = array_key_exists($name, $this->magic) ? $this->magic[$name] : [];
$alias = new Alias($this->config, $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]);
}
$aliases[] = $alias;
}
}
return $aliases;
}
protected function getRealTimeFacades()
{
$facades = [];
$realTimeFacadeFiles = glob(storage_path('framework/cache/facade-*.php'));
foreach ($realTimeFacadeFiles as $file) {
try {
$name = $this->getFullyQualifiedClassNameInFile($file);
$facades[$name] = $name;
} catch (\Exception $e) {
continue;
}
}
return $facades;
}
protected function getFullyQualifiedClassNameInFile(string $path)
{
$contents = file_get_contents($path);
$parsers = new Php7(new Emulative());
$parsed = collect($parsers->parse($contents) ?: []);
$namespace = $parsed->first(function ($node) {
return $node instanceof Namespace_;
});
if ($namespace) {
$name = $namespace->name->toString();
$class = collect($namespace->stmts)->first(function ($node) {
return $node instanceof Class_;
});
if ($class) {
$name .= '\\' . $class->name->toString();
}
return $name;
}
}
/**
* Regroup aliases by namespace of extended classes
*
* @return Collection
*/
protected function getAliasesByExtendsNamespace()
{
$aliases = $this->getValidAliases()->filter(static function (Alias $alias) {
return is_subclass_of($alias->getExtends(), Facade::class);
});
$this->addMacroableClasses($aliases);
return $aliases->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()
{
// For Laravel, use the AliasLoader
if (class_exists('Illuminate\Foundation\AliasLoader')) {
return AliasLoader::getInstance()->getAliases();
}
$facades = [
'App' => 'Illuminate\Support\Facades\App',
'Auth' => 'Illuminate\Support\Facades\Auth',
'Bus' => 'Illuminate\Support\Facades\Bus',
'DB' => 'Illuminate\Support\Facades\DB',
'Cache' => 'Illuminate\Support\Facades\Cache',
'Cookie' => 'Illuminate\Support\Facades\Cookie',
'Crypt' => 'Illuminate\Support\Facades\Crypt',
'Event' => 'Illuminate\Support\Facades\Event',
'Hash' => 'Illuminate\Support\Facades\Hash',
'Log' => 'Illuminate\Support\Facades\Log',
'Mail' => 'Illuminate\Support\Facades\Mail',
'Queue' => 'Illuminate\Support\Facades\Queue',
'Request' => 'Illuminate\Support\Facades\Request',
'Schema' => 'Illuminate\Support\Facades\Schema',
'Session' => 'Illuminate\Support\Facades\Session',
'Storage' => 'Illuminate\Support\Facades\Storage',
'Validator' => 'Illuminate\Support\Facades\Validator',
'Gate' => 'Illuminate\Support\Facades\Gate',
];
$facades = array_merge($facades, $this->config->get('app.aliases', []));
// Only return the ones that actually exist
return array_filter(
$facades,
function ($alias) {
return class_exists($alias);
},
ARRAY_FILTER_USE_KEY
);
}
/**
* Write a string as error output.
*
* @param string $string
* @return void
*/
protected function error($string)
{
if ($this->output) {
$this->output->writeln("<error>$string</error>");
} else {
echo $string . "\r\n";
}
}
/**
* Add all macroable classes which are not already loaded as an alias and have defined macros.
*
* @param Collection $aliases
*/
protected function addMacroableClasses(Collection $aliases)
{
$macroable = $this->getMacroableClasses($aliases);
foreach ($macroable as $class) {
$reflection = new ReflectionClass($class);
if (!$reflection->getStaticProperties()['macros']) {
continue;
}
$aliases[] = new Alias($this->config, $class, $class, [], $this->interfaces);
}
}
/**
* Get all loaded macroable classes which are not loaded as an alias.
*
* @param Collection $aliases
* @return Collection
*/
protected function getMacroableClasses(Collection $aliases)
{
return (new Collection(get_declared_classes()))
->filter(function ($class) {
$reflection = new ReflectionClass($class);
// Filter out internal classes and class aliases
return !$reflection->isInternal() && $reflection->getName() === $class;
})
->filter(function ($class) {
$traits = class_uses_recursive($class);
// Filter only classes with the macroable trait
return isset($traits[Macroable::class]);
})
->filter(function ($class) use ($aliases) {
$class = Str::start($class, '\\');
// Filter out aliases
return !$aliases->first(function (Alias $alias) use ($class) {
return $alias->getExtends() === $class;
});
});
}
}
-130
View File
@@ -1,130 +0,0 @@
<?php
/**
* Laravel IDE Helper Generator
*
* @author Barry vd. Heuvel <barryvdh@gmail.com>
* @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\LaravelIdeHelper\Console\EloquentCommand;
use Barryvdh\LaravelIdeHelper\Console\GeneratorCommand;
use Barryvdh\LaravelIdeHelper\Console\MetaCommand;
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
use Barryvdh\LaravelIdeHelper\Listeners\GenerateModelHelper;
use Illuminate\Console\Events\CommandFinished;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Database\Events\MigrationsEnded;
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 implements DeferrableProvider
{
/**
* Bootstrap the application events.
*
* @return void
*/
public function boot()
{
if (!$this->app->runningUnitTests() && $this->app['config']->get('ide-helper.post_migrate', [])) {
$this->app['events']->listen(CommandFinished::class, GenerateModelHelper::class);
$this->app['events']->listen(MigrationsEnded::class, function () {
GenerateModelHelper::$shouldRun = true;
});
}
if ($this->app->has('view')) {
$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');
} else {
$publishPath = base_path('config/ide-helper.php');
}
$this->publishes([$configPath => $publishPath], 'config');
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$configPath = __DIR__ . '/../config/ide-helper.php';
$this->mergeConfigFrom($configPath, 'ide-helper');
$localViewFactory = $this->createLocalViewFactory();
$this->app->singleton(
'command.ide-helper.generate',
function ($app) use ($localViewFactory) {
return new GeneratorCommand($app['config'], $app['files'], $localViewFactory);
}
);
$this->app->singleton(
'command.ide-helper.models',
function ($app) {
return new ModelsCommand($app['files']);
}
);
$this->app->singleton(
'command.ide-helper.meta',
function ($app) use ($localViewFactory) {
return new MetaCommand($app['files'], $localViewFactory, $app['config']);
}
);
$this->app->singleton(
'command.ide-helper.eloquent',
function ($app) {
return new EloquentCommand($app['files']);
}
);
$this->commands(
'command.ide-helper.generate',
'command.ide-helper.models',
'command.ide-helper.meta',
'command.ide-helper.eloquent'
);
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return ['command.ide-helper.generate', 'command.ide-helper.models'];
}
/**
* @return Factory
*/
private function createLocalViewFactory()
{
$resolver = new EngineResolver();
$resolver->register('php', function () {
return new PhpEngine($this->app['files']);
});
$finder = new FileViewFinder($this->app['files'], [__DIR__ . '/../resources/views']);
$factory = new Factory($resolver, $finder, $this->app['events']);
$factory->addExtension('php', 'php');
return $factory;
}
}
-52
View File
@@ -1,52 +0,0 @@
<?php
namespace Barryvdh\LaravelIdeHelper\Listeners;
use Illuminate\Console\Events\CommandFinished;
use Illuminate\Contracts\Config\Repository as Config;
use Illuminate\Contracts\Console\Kernel as Artisan;
class GenerateModelHelper
{
/**
* Tracks whether we should run the models command on the CommandFinished event or not.
* Set to true by the MigrationsEnded event, needs to be cleared before artisan call to prevent infinite loop.
*
* @var bool
*/
public static $shouldRun = false;
/** @var Artisan */
protected $artisan;
/** @var Config */
protected $config;
/**
* @param Artisan $artisan
* @param Config $config
*/
public function __construct(Artisan $artisan, Config $config)
{
$this->artisan = $artisan;
$this->config = $config;
}
/**
* Handle the event.
*
* @param CommandFinished $event
*/
public function handle(CommandFinished $event)
{
if (!self::$shouldRun) {
return;
}
self::$shouldRun = false;
foreach ($this->config->get('ide-helper.post_migrate', []) as $command) {
$this->artisan->call($command, [], $event->output);
}
}
}
-127
View File
@@ -1,127 +0,0 @@
<?php
namespace Barryvdh\LaravelIdeHelper;
use Barryvdh\Reflection\DocBlock;
use Barryvdh\Reflection\DocBlock\Tag;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Support\Collection;
class Macro extends Method
{
/**
* Macro constructor.
*
* @param \ReflectionFunctionAbstract $method
* @param string $alias
* @param \ReflectionClass $class
* @param null $methodName
* @param array $interfaces
* @param array $classAliases
*/
public function __construct(
$method,
$alias,
$class,
$methodName = null,
$interfaces = [],
$classAliases = []
) {
parent::__construct($method, $alias, $class, $methodName, $interfaces, $classAliases);
}
/**
* @param \ReflectionFunctionAbstract $method
*/
protected function initPhpDoc($method)
{
$this->phpdoc = new DocBlock($method);
$this->addLocationToPhpDoc();
// Add macro parameters if they are missed in original docblock
if (!$this->phpdoc->hasTag('param')) {
foreach ($method->getParameters() as $parameter) {
$reflectionType = $parameter->getType();
$type = $this->concatReflectionTypes($reflectionType);
/** @psalm-suppress UndefinedClass */
if ($reflectionType && !$reflectionType instanceof \ReflectionUnionType && $reflectionType->allowsNull()) {
$type .= '|null';
}
$type = $type ?: 'mixed';
$name = $parameter->isVariadic() ? '...' : '';
$name .= '$' . $parameter->getName();
$this->phpdoc->appendTag(Tag::createInstance("@param {$type} {$name}"));
}
}
// Add macro return type if it missed in original docblock
if ($method->hasReturnType() && !$this->phpdoc->hasTag('return')) {
$builder = EloquentBuilder::class;
$return = $method->getReturnType();
$type = $this->concatReflectionTypes($return);
/** @psalm-suppress UndefinedClass */
if (!$return instanceof \ReflectionUnionType) {
$type .= $this->root === "\\{$builder}" && $return->getName() === $builder ? '|static' : '';
$type .= $return->allowsNull() ? '|null' : '';
}
$this->phpdoc->appendTag(Tag::createInstance("@return {$type}"));
}
}
protected function concatReflectionTypes(?\ReflectionType $type): string
{
/** @psalm-suppress UndefinedClass */
$returnTypes = $type instanceof \ReflectionUnionType
? $type->getTypes()
: [$type];
return Collection::make($returnTypes)
->filter()
->map->getName()
->implode('|');
}
protected function addLocationToPhpDoc()
{
if ($this->method->name === '__invoke') {
$enclosingClass = $this->method->getDeclaringClass();
} else {
$enclosingClass = $this->method->getClosureScopeClass();
}
if (!$enclosingClass) {
return;
}
/** @var \ReflectionMethod $enclosingMethod */
$enclosingMethod = Collection::make($enclosingClass->getMethods())
->first(function (\ReflectionMethod $method) {
return $method->getStartLine() <= $this->method->getStartLine()
&& $method->getEndLine() >= $this->method->getEndLine();
});
if ($enclosingMethod) {
$this->phpdoc->appendTag(Tag::createInstance(
'@see \\' . $enclosingClass->getName() . '::' . $enclosingMethod->getName() . '()'
));
}
}
/**
* @param \ReflectionFunctionAbstract $method
* @param \ReflectionClass $class
*/
protected function initClassDefinedProperties($method, \ReflectionClass $class)
{
$this->namespace = $class->getNamespaceName();
$this->declaringClassName = '\\' . ltrim($class->name, '\\');
}
}
-379
View File
@@ -1,379 +0,0 @@
<?php
/**
* Laravel IDE Helper Generator
*
* @author Barry vd. Heuvel <barryvdh@gmail.com>
* @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\Serializer as DocBlockSerializer;
use Barryvdh\Reflection\DocBlock\Tag;
use Barryvdh\Reflection\DocBlock\Tag\ParamTag;
use Barryvdh\Reflection\DocBlock\Tag\ReturnTag;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Str;
class Method
{
/** @var DocBlock */
protected $phpdoc;
/** @var \ReflectionMethod */
protected $method;
protected $output = '';
protected $declaringClassName;
protected $name;
protected $namespace;
protected $params = [];
protected $params_with_default = [];
protected $interfaces = [];
protected $real_name;
protected $return = null;
protected $root;
protected $classAliases;
/**
* @param \ReflectionMethod|\ReflectionFunctionAbstract $method
* @param string $alias
* @param \ReflectionClass $class
* @param string|null $methodName
* @param array $interfaces
* @param array $classAliases
*/
public function __construct($method, $alias, $class, $methodName = null, $interfaces = [], array $classAliases = [])
{
$this->method = $method;
$this->interfaces = $interfaces;
$this->classAliases = $classAliases;
$this->name = $methodName ?: $method->name;
$this->real_name = $method->isClosure() ? $this->name : $method->name;
$this->initClassDefinedProperties($method, $class);
//Reference the 'real' function in the declaring class
$this->root = '\\' . ltrim($method->name === '__invoke' ? $method->getDeclaringClass()->getName() : $class->getName(), '\\');
//Create a DocBlock and serializer instance
$this->initPhpDoc($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));
}
/**
* @param \ReflectionMethod $method
*/
protected function initPhpDoc($method)
{
$this->phpdoc = new DocBlock($method, new Context($this->namespace, $this->classAliases));
}
/**
* @param \ReflectionMethod $method
* @param \ReflectionClass $class
*/
protected function initClassDefinedProperties($method, \ReflectionClass $class)
{
$declaringClass = $method->getDeclaringClass();
$this->namespace = $declaringClass->getNamespaceName();
$this->declaringClassName = '\\' . ltrim($declaringClass->name, '\\');
}
/**
* 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;
}
/**
* @return bool
*/
public function isInstanceCall()
{
return !($this->method->isClosure() || $this->method->isStatic());
}
/**
* @return string
*/
public function getRootMethodCall()
{
if ($this->isInstanceCall()) {
return "\$instance->{$this->getRealName()}({$this->getParams()})";
} else {
return "{$this->getRoot()}::{$this->getRealName()}({$this->getParams()})";
}
}
/**
* Get the docblock for this method
*
* @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 real method name
*
* @return string
*/
public function getRealName()
{
return $this->real_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 better autocomplete
$returnTags = $phpdoc->getTagsByName('return');
if (count($returnTags) === 0) {
$this->return = null;
return;
}
/** @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;
if ($tag->getType() === '$this') {
Str::contains($this->root, Builder::class)
? $tag->setType($this->root . '|static')
: $tag->setType($this->root);
}
}
/**
* Convert keywords 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 \ReflectionMethod $method
* @return void
*/
public function getParameters($method)
{
//Loop through the default values for parameters, and make the correct output string
$params = [];
$paramsWithDefault = [];
foreach ($method->getParameters() as $param) {
$paramStr = $param->isVariadic() ? '...$' . $param->getName() : '$' . $param->getName();
$params[] = $paramStr;
if ($param->isOptional() && !$param->isVariadic()) {
$default = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null;
if (is_bool($default)) {
$default = $default ? 'true' : 'false';
} elseif (is_array($default)) {
$default = '[]';
} elseif (is_null($default)) {
$default = 'null';
} elseif (is_int($default)) {
//$default = $default;
} elseif (is_resource($default)) {
//skip to not fail
} else {
$default = var_export($default, true);
}
$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, $this->classAliases));
if (strpos($phpdoc->getText(), '{@inheritdoc}') !== false) {
//Not at the end yet, try another parent/interface..
return $this->getInheritDoc($method);
}
return $phpdoc;
}
}
}
-79
View File
@@ -1,79 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Parsers;
class PhpDocReturnTypeParser
{
/**
* @var string
*/
private string $typeAlias;
/**
* @var array
*/
private array $namespaceAliases;
/**
* @param string $typeAlias
* @param array $namespaceAliases
*/
public function __construct(string $typeAlias, array $namespaceAliases)
{
$this->typeAlias = $typeAlias;
$this->namespaceAliases = $namespaceAliases;
}
/**
* @return string|null
*/
public function parse(): string|null
{
$matches = [];
preg_match('/(\w+)(<.*>)/', $this->typeAlias, $matches);
$matchCount = count($matches);
if ($matchCount === 0 || $matchCount === 1) {
return null;
}
if (empty($this->namespaceAliases[$matches[1]])) {
return null;
}
return $this->namespaceAliases[$matches[1]] . $this->parseTemplate($matches[2] ?? null);
}
/**
* @param string|null $template
* @return string
*/
private function parseTemplate(string|null $template): string
{
if ($template === null || $template === '') {
return '';
}
$type = '';
$result = '';
foreach (str_split($template) as $char) {
$match = preg_match('/[A-z]/', $char);
if (!$match) {
$type = $this->namespaceAliases[$type] ?? $type;
$result .= $type;
$result .= $char;
$type = '';
continue;
}
$type .= $char;
}
return $result;
}
}
-124
View File
@@ -1,124 +0,0 @@
<?php
/**
* Laravel IDE Helper Generator
*
* @author Barry vd. Heuvel <barryvdh@gmail.com>
* @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 PhpParser\Node\Stmt\GroupUse;
use PhpParser\Node\Stmt\Namespace_;
use PhpParser\Node\Stmt\Use_;
use PhpParser\Node\Stmt\UseUse;
use PhpParser\ParserFactory;
class UsesResolver
{
/**
* @param string $classFQN
* @return array
*/
public function loadFromClass(string $classFQN): array
{
return $this->loadFromFile(
$classFQN,
(new \ReflectionClass($classFQN))->getFileName()
);
}
/**
* @param string $classFQN
* @param string $filename
* @return array
*/
public function loadFromFile(string $classFQN, string $filename): array
{
return $this->loadFromCode(
$classFQN,
file_get_contents(
$filename
)
);
}
/**
* @param string $classFQN
* @param string $code
* @return array
*/
public function loadFromCode(string $classFQN, string $code): array
{
$classFQN = ltrim($classFQN, '\\');
$namespace = rtrim(
preg_replace(
'/([^\\\\]+)$/',
'',
$classFQN
),
'\\'
);
$parser = (new ParserFactory())->createForHostVersion();
$namespaceData = null;
foreach ($parser->parse($code) as $node) {
if ($node instanceof Namespace_ && $node->name->toCodeString() === $namespace) {
$namespaceData = $node;
break;
}
}
if ($namespaceData === null) {
return [];
}
/** @var Namespace_ $namespaceData */
$aliases = [];
foreach ($namespaceData->stmts as $stmt) {
if ($stmt instanceof Use_) {
if ($stmt->type !== Use_::TYPE_NORMAL) {
continue;
}
foreach ($stmt->uses as $use) {
/** @var UseUse $use */
$alias = $use->alias ?
$use->alias->name :
self::classBasename($use->name->toCodeString());
$aliases[$alias] = '\\' . $use->name->toCodeString();
}
} elseif ($stmt instanceof GroupUse) {
foreach ($stmt->uses as $use) {
/** @var UseUse $use */
$alias = $use->alias ?
$use->alias->name :
self::classBasename($use->name->toCodeString());
$aliases[$alias] = '\\' . $stmt->prefix->toCodeString() . '\\' . $use->name->toCodeString();
}
}
}
return $aliases;
}
/**
* @param string $classFQN
* @return string
*/
protected static function classBasename(string $classFQN): string
{
return preg_replace('/^.*\\\\([^\\\\]+)$/', '$1', $classFQN);
}
}
+46
View File
@@ -0,0 +1,46 @@
<?php
return array(
/*
|--------------------------------------------------------------------------
| Filename
|--------------------------------------------------------------------------
|
| The default path to the helper file
|
*/
'filename' => '_ide_helper.php',
/*
|--------------------------------------------------------------------------
| Helper files to include
|--------------------------------------------------------------------------
|
| Include helper files. By default not included, but can be toggled with the
| -- helpers (-H) option. Extra helper files can be included.
|
*/
'include_helpers' => false,
'helper_files' => array(
base_path().'/vendor/laravel/framework/src/Illuminate/Support/helpers.php',
),
/*
|--------------------------------------------------------------------------
| Extra classes
|--------------------------------------------------------------------------
|
| These implementations are not really extended, but called with magic functions
|
*/
'extra' => array(
'Eloquent' => array('Illuminate\Database\Eloquent\Builder', 'Illuminate\Database\Query\Builder'),
),
);
-105
View File
@@ -1,105 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests;
use Barryvdh\LaravelIdeHelper\Alias;
use Barryvdh\LaravelIdeHelper\Macro;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Arr;
/**
* @internal
* @coversDefaultClass \Barryvdh\LaravelIdeHelper\Alias
*/
class AliasTest extends TestCase
{
/**
* @covers ::detectMethods
*/
public function testDetectMethodsMacroableMacros(): void
{
// Mock
$macro = __FUNCTION__;
$alias = new AliasMock();
// Macros
Builder::macro(
$macro,
function () {
// empty
}
);
// Prepare
$alias->setClasses([Builder::class]);
$alias->detectMethods();
// Test
$this->assertNotNull($this->getAliasMacro($alias, Builder::class, $macro));
}
/**
* @covers ::detectMethods
*/
public function testDetectMethodsEloquentBuilderMacros(): void
{
// Mock
$macro = __FUNCTION__;
$alias = new AliasMock();
// Macros
EloquentBuilder::macro(
$macro,
function () {
// empty
}
);
// Prepare
$alias->setClasses([EloquentBuilder::class]);
$alias->detectMethods();
// Test
$this->assertNotNull($this->getAliasMacro($alias, EloquentBuilder::class, $macro));
}
protected function getAliasMacro(Alias $alias, string $class, string $method): ?Macro
{
return Arr::first(
$alias->getMethods(),
function ($macro) use ($class, $method) {
return $macro instanceof Macro
&& $macro->getDeclaringClass() === "\\{$class}"
&& $macro->getName() === $method;
}
);
}
}
/**
* @internal
* @noinspection PhpMultipleClassesDeclarationsInOneFile
*/
class AliasMock extends Alias
{
public function __construct()
{
// no need to call parent
}
/**
* @param string[] $classes
*/
public function setClasses(array $classes)
{
$this->classes = $classes;
}
public function detectMethods()
{
parent::detectMethods();
}
}
-68
View File
@@ -1,68 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console;
use Barryvdh\LaravelIdeHelper\Console\EloquentCommand;
use Barryvdh\LaravelIdeHelper\Tests\TestCase;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Filesystem\Filesystem;
use Mockery;
use ReflectionClass;
class EloquentCommandTest extends TestCase
{
public function testCommand()
{
$modelFilename = $this->getVendorModelFilename();
$modelSource = file_get_contents($modelFilename);
if (false !== strpos($modelSource, '* @mixin')) {
$msg = sprintf('Class %s already contains the @mixin markers', Model::class);
$this->markTestSkipped($msg);
}
$actualContent = null;
$mockFilesystem = Mockery::mock(Filesystem::class);
$mockFilesystem
->shouldReceive('get')
// We don't care about actual args (filename)
->andReturn('abstract class Model implements'); // This is enough to trigger the replacement logic
$mockFilesystem
->shouldReceive('put')
->with(
Mockery::any(), // First arg is path, we don't care
Mockery::capture($actualContent)
)
->andReturn(1) // Simulate we wrote _something_ to the file
->once();
$this->instance(Filesystem::class, $mockFilesystem);
$command = $this->app->make(EloquentCommand::class);
$tester = $this->runCommand($command);
$this->assertMatchesTxtSnapshot($actualContent);
$display = $tester->getDisplay();
$this->assertMatchesRegularExpression(
';Unexpected no document on Illuminate\\\Database\\\Eloquent\\\Model;',
$display
);
$modelClassFilePath = preg_quote(
str_replace('/', DIRECTORY_SEPARATOR, '/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php')
);
$this->assertMatchesRegularExpression(
';Wrote expected docblock to .*' . $modelClassFilePath . ';',
$display
);
}
private function getVendorModelFilename(): string
{
$class = Model::class;
$reflectedClass = new ReflectionClass($class);
return $reflectedClass->getFileName();
}
}
@@ -1,84 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\MetaCommand;
use Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider;
use Barryvdh\LaravelIdeHelper\Tests\TestCase;
use Illuminate\Filesystem\Filesystem;
use Mockery\MockInterface;
use stdClass;
class MetaCommandTest extends TestCase
{
public function testCommand(): void
{
$this->mockFilesystem();
/** @var Filesystem|MockInterface $mockFileSystem */
$mockFileSystem = $this->app->make(Filesystem::class);
$this->instance('files', $mockFileSystem);
$mockFileSystem
->shouldReceive('getRequire')
->andReturnUsing(function ($__path, $__data) {
return (static function () use ($__path, $__data) {
extract($__data, EXTR_SKIP);
return require $__path;
})();
});
$this->artisan('ide-helper:meta');
// We're not testing the whole file, just some basic structure elements
self::assertStringContainsString("namespace PHPSTORM_META {\n", $this->mockFilesystemOutput);
self::assertStringContainsString("PhpStorm Meta file, to provide autocomplete information for PhpStorm\n", $this->mockFilesystemOutput);
self::assertStringContainsString('override(', $this->mockFilesystemOutput);
}
public function testUnregisterAutoloader(): void
{
$current = spl_autoload_functions();
$appended = function () {
};
$this->app->bind('registers-autoloader', function () use ($appended) {
spl_autoload_register($appended);
return new stdClass();
});
$this->mockFilesystem();
/** @var Filesystem|MockInterface $mockFileSystem */
$mockFileSystem = $this->app->make(Filesystem::class);
$this->instance('files', $mockFileSystem);
$mockFileSystem
->shouldReceive('getRequire')
->andReturnUsing(function ($__path, $__data) {
return (static function () use ($__path, $__data) {
extract($__data, EXTR_SKIP);
return require $__path;
})();
});
$this->artisan('ide-helper:meta');
self::assertSame(array_merge($current, [$appended]), spl_autoload_functions());
}
/**
* Get package providers.
*
* @param \Illuminate\Foundation\Application $app
*
* @return array
*/
protected function getPackageProviders($app)
{
return [IdeHelperServiceProvider::class];
}
}
@@ -1,60 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand;
use Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider;
use Barryvdh\LaravelIdeHelper\Tests\SnapshotPhpDriver;
use Barryvdh\LaravelIdeHelper\Tests\TestCase;
abstract class AbstractModelsCommand extends TestCase
{
protected function setUp(): void
{
parent::setUp();
$this->loadMigrationsFrom(__DIR__ . '/migrations');
$this->artisan('migrate');
$this->mockFilesystem();
}
/**
* Get package providers.
*
* @param \Illuminate\Foundation\Application $app
*
* @return array
*/
protected function getPackageProviders($app)
{
return [IdeHelperServiceProvider::class];
}
protected function getEnvironmentSetUp($app)
{
parent::getEnvironmentSetUp($app);
$config = $app['config'];
$config->set('database.default', 'sqlite');
$config->set('database.connections.sqlite', [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
]);
// Load the Models from the Test dir
$config->set('ide-helper.model_locations', [
dirname((new \ReflectionClass(static::class))->getFileName()) . '/Models',
]);
// Don't override integer -> int for tests
$config->set('ide-helper.type_overrides', []);
}
protected function assertMatchesMockedSnapshot()
{
$this->assertMatchesSnapshot($this->mockFilesystemOutput, new SnapshotPhpDriver());
}
}
@@ -1,11 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Collections;
use Illuminate\Support\Collection;
class AdvancedCastCollection extends Collection
{
}
@@ -1,12 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Enums;
enum AdvancedCastEnum
{
case apple;
case banana;
case orange;
}
@@ -1,38 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Models;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Collections\AdvancedCastCollection;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Enums\AdvancedCastEnum;
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
use Illuminate\Database\Eloquent\Casts\AsCollection;
use Illuminate\Database\Eloquent\Casts\AsEnumCollection;
use Illuminate\Database\Eloquent\Model;
class AdvancedCast extends Model
{
protected function casts(): array
{
return [
'cast_to_date_serialization' => 'date:Y-m-d',
'cast_to_datetime_serialization' => 'datetime:Y-m-d H:i:s',
'cast_to_custom_datetime' => 'custom_datetime:Y-m-d H:i:s',
'cast_to_immutable_date' => 'immutable_date',
'cast_to_immutable_custom_datetime' => 'immutable_custom_datetime:Y-m-d H:i:s',
'cast_to_immutable_datetime' => 'immutable_datetime',
'cast_to_timestamp' => 'timestamp',
'cast_to_encrypted' => 'encrypted',
'cast_to_encrypted_array' => 'encrypted:array',
'cast_to_encrypted_collection' => 'encrypted:collection',
'cast_to_encrypted_json' => 'encrypted:json',
'cast_to_encrypted_object' => 'encrypted:object',
'cast_to_as_collection' => AsCollection::class,
'cast_to_as_collection_using' => AsCollection::using(AdvancedCastCollection::class),
'cast_to_as_enum_collection' => AsEnumCollection::class,
'cast_to_as_enum_collection_of' => AsEnumCollection::of(AdvancedCastEnum::class),
'cast_to_as_array_object' => AsArrayObject::class,
];
}
}
@@ -1,24 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts;
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AbstractModelsCommand;
class Test extends AbstractModelsCommand
{
public function test(): void
{
$command = $this->app->make(ModelsCommand::class);
$tester = $this->runCommand($command, [
'--write' => true,
]);
$this->assertSame(0, $tester->getStatusCode());
$this->assertStringContainsString('Written new phpDocBlock to', $tester->getDisplay());
$this->assertMatchesMockedSnapshot();
}
}
@@ -1,78 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Models;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Collections\AdvancedCastCollection;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AdvancedCasts\Enums\AdvancedCastEnum;
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
use Illuminate\Database\Eloquent\Casts\AsCollection;
use Illuminate\Database\Eloquent\Casts\AsEnumCollection;
use Illuminate\Database\Eloquent\Model;
/**
*
*
* @property \Illuminate\Support\Carbon $cast_to_date_serialization
* @property \Illuminate\Support\Carbon $cast_to_datetime_serialization
* @property \Illuminate\Support\Carbon $cast_to_custom_datetime
* @property \Carbon\CarbonImmutable $cast_to_immutable_date
* @property \Carbon\CarbonImmutable $cast_to_immutable_custom_datetime
* @property \Carbon\CarbonImmutable $cast_to_immutable_datetime
* @property int $cast_to_timestamp
* @property mixed $cast_to_encrypted
* @property array $cast_to_encrypted_array
* @property \Illuminate\Support\Collection $cast_to_encrypted_collection
* @property array $cast_to_encrypted_json
* @property object $cast_to_encrypted_object
* @property \Illuminate\Support\Collection $cast_to_as_collection
* @property \Illuminate\Support\Collection $cast_to_as_enum_collection
* @property \ArrayObject $cast_to_as_array_object
* @property AdvancedCastCollection $cast_to_as_collection_using
* @property \Illuminate\Support\Collection<int, AdvancedCastEnum> $cast_to_as_enum_collection_of
* @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast whereCastToAsArrayObject($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast whereCastToAsCollection($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast whereCastToAsEnumCollection($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast whereCastToCustomDatetime($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast whereCastToDateSerialization($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast whereCastToDatetimeSerialization($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast whereCastToEncrypted($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast whereCastToEncryptedArray($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast whereCastToEncryptedCollection($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast whereCastToEncryptedJson($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast whereCastToEncryptedObject($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast whereCastToImmutableCustomDatetime($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast whereCastToImmutableDate($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast whereCastToImmutableDatetime($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|AdvancedCast whereCastToTimestamp($value)
* @mixin \Eloquent
*/
class AdvancedCast extends Model
{
protected function casts(): array
{
return [
'cast_to_date_serialization' => 'date:Y-m-d',
'cast_to_datetime_serialization' => 'datetime:Y-m-d H:i:s',
'cast_to_custom_datetime' => 'custom_datetime:Y-m-d H:i:s',
'cast_to_immutable_date' => 'immutable_date',
'cast_to_immutable_custom_datetime' => 'immutable_custom_datetime:Y-m-d H:i:s',
'cast_to_immutable_datetime' => 'immutable_datetime',
'cast_to_timestamp' => 'timestamp',
'cast_to_encrypted' => 'encrypted',
'cast_to_encrypted_array' => 'encrypted:array',
'cast_to_encrypted_collection' => 'encrypted:collection',
'cast_to_encrypted_json' => 'encrypted:json',
'cast_to_encrypted_object' => 'encrypted:object',
'cast_to_as_collection' => AsCollection::class,
'cast_to_as_collection_using' => AsCollection::using(AdvancedCastCollection::class),
'cast_to_as_enum_collection' => AsEnumCollection::class,
'cast_to_as_enum_collection_of' => AsEnumCollection::of(AdvancedCastEnum::class),
'cast_to_as_array_object' => AsArrayObject::class,
];
}
}
@@ -1,11 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AllowGlobDirectory\Services\Post\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
}
@@ -1,44 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AllowGlobDirectory;
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AbstractModelsCommand;
final class Test extends AbstractModelsCommand
{
/** @var string */
private $cwd;
protected function setUp(): void
{
parent::setUp();
$this->cwd = getcwd();
}
protected function tearDown(): void
{
chdir($this->cwd);
parent::tearDown();
}
public function test(): void
{
$command = $this->app->make(ModelsCommand::class);
chdir(__DIR__);
$tester = $this->runCommand($command, [
'--dir' => ['Services/*/Models'],
'--write' => true,
]);
$this->assertSame(0, $tester->getStatusCode());
$this->assertStringContainsString('Written new phpDocBlock to', $tester->getDisplay());
$this->assertMatchesMockedSnapshot();
}
}
@@ -1,161 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AllowGlobDirectory\Services\Post\Models;
use Illuminate\Database\Eloquent\Model;
/**
*
*
* @property int $id
* @property string|null $char_nullable
* @property string $char_not_nullable
* @property string|null $string_nullable
* @property string $string_not_nullable
* @property string|null $text_nullable
* @property string $text_not_nullable
* @property string|null $medium_text_nullable
* @property string $medium_text_not_nullable
* @property string|null $long_text_nullable
* @property string $long_text_not_nullable
* @property int|null $integer_nullable
* @property int $integer_not_nullable
* @property int|null $tiny_integer_nullable
* @property int $tiny_integer_not_nullable
* @property int|null $small_integer_nullable
* @property int $small_integer_not_nullable
* @property int|null $medium_integer_nullable
* @property int $medium_integer_not_nullable
* @property int|null $big_integer_nullable
* @property int $big_integer_not_nullable
* @property int|null $unsigned_integer_nullable
* @property int $unsigned_integer_not_nullable
* @property int|null $unsigned_tiny_integer_nullable
* @property int $unsigned_tiny_integer_not_nullable
* @property int|null $unsigned_small_integer_nullable
* @property int $unsigned_small_integer_not_nullable
* @property int|null $unsigned_medium_integer_nullable
* @property int $unsigned_medium_integer_not_nullable
* @property int|null $unsigned_big_integer_nullable
* @property int $unsigned_big_integer_not_nullable
* @property float|null $float_nullable
* @property float $float_not_nullable
* @property float|null $double_nullable
* @property float $double_not_nullable
* @property string|null $decimal_nullable
* @property string $decimal_not_nullable
* @property int|null $boolean_nullable
* @property int $boolean_not_nullable
* @property string|null $enum_nullable
* @property string $enum_not_nullable
* @property string|null $json_nullable
* @property string $json_not_nullable
* @property string|null $jsonb_nullable
* @property string $jsonb_not_nullable
* @property string|null $date_nullable
* @property string $date_not_nullable
* @property string|null $datetime_nullable
* @property string $datetime_not_nullable
* @property string|null $datetimetz_nullable
* @property string $datetimetz_not_nullable
* @property string|null $time_nullable
* @property string $time_not_nullable
* @property string|null $timetz_nullable
* @property string $timetz_not_nullable
* @property string|null $timestamp_nullable
* @property string $timestamp_not_nullable
* @property string|null $timestamptz_nullable
* @property string $timestamptz_not_nullable
* @property int|null $year_nullable
* @property int $year_not_nullable
* @property string|null $binary_nullable
* @property string $binary_not_nullable
* @property string|null $uuid_nullable
* @property string $uuid_not_nullable
* @property string|null $ipaddress_nullable
* @property string $ipaddress_not_nullable
* @property string|null $macaddress_nullable
* @property string $macaddress_not_nullable
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereBigIntegerNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereBigIntegerNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereBinaryNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereBinaryNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereBooleanNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereBooleanNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereCharNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereCharNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereDateNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereDateNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereDatetimeNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereDatetimeNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereDatetimetzNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereDatetimetzNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereDecimalNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereDecimalNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereDoubleNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereDoubleNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereEnumNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereEnumNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereFloatNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereFloatNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereIntegerNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereIntegerNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereIpaddressNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereIpaddressNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereJsonNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereJsonNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereJsonbNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereJsonbNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereLongTextNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereLongTextNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereMacaddressNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereMacaddressNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereMediumIntegerNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereMediumIntegerNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereMediumTextNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereMediumTextNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereSmallIntegerNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereSmallIntegerNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereStringNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereStringNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTextNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTextNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTimeNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTimeNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTimestampNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTimestampNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTimestamptzNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTimestamptzNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTimetzNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTimetzNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTinyIntegerNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTinyIntegerNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUnsignedBigIntegerNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUnsignedBigIntegerNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUnsignedIntegerNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUnsignedIntegerNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUnsignedMediumIntegerNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUnsignedMediumIntegerNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUnsignedSmallIntegerNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUnsignedSmallIntegerNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUnsignedTinyIntegerNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUnsignedTinyIntegerNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUuidNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUuidNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereYearNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereYearNullable($value)
* @mixin \Eloquent
*/
class Post extends Model
{
}
@@ -1,43 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\ArrayCastsWithComment\Models;
use Illuminate\Database\Eloquent\Model;
/**
* @property array<int, string>|null $cast_to_array -- These three should not be duplicated
* @property array<int, string> $cast_to_json some-description
* @property \Illuminate\Support\Collection<int, string> $cast_to_collection some-description
*
* @property array|null $cast_to_encrypted_array -- These three are OK (no types)
* @property array $cast_to_encrypted_json some-description
* @property \Illuminate\Support\Collection $cast_to_encrypted_collection some-description
*
* @property string $cast_to_string -- The next three are OK (no description), this not included
*
* @property array<int, string>|null $cast_to_immutable_date
* @property array<int, string> $cast_to_immutable_date_serialization
* @property \Illuminate\Support\Collection<int, string> $cast_to_immutable_custom_datetime
*/
class ArrayCastsWithComment extends Model
{
protected $table = 'simple_casts';
protected $casts = [
'cast_to_array' => 'array',
'cast_to_json' => 'json',
'cast_to_collection' => 'collection',
'cast_to_encrypted_array' => 'array',
'cast_to_encrypted_json' => 'json',
'cast_to_encrypted_collection' => 'collection',
'cast_to_string' => 'string',
'cast_to_immutable_date' => 'array',
'cast_to_immutable_date_serialization' => 'json',
'cast_to_immutable_custom_datetime' => 'collection',
];
}
@@ -1,24 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\ArrayCastsWithComment;
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AbstractModelsCommand;
class Test extends AbstractModelsCommand
{
public function test(): void
{
$command = $this->app->make(ModelsCommand::class);
$tester = $this->runCommand($command, [
'--write' => true,
]);
$this->assertSame(0, $tester->getStatusCode());
$this->assertStringContainsString('Written new phpDocBlock to', $tester->getDisplay());
$this->assertMatchesMockedSnapshot();
}
}
@@ -1,94 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\ArrayCastsWithComment\Models;
use Illuminate\Database\Eloquent\Model;
/**
*
*
* @property array<int, string>|null $cast_to_array -- These three should not be duplicated
* @property array<int, string> $cast_to_json some-description
* @property \Illuminate\Support\Collection<int, string> $cast_to_collection some-description
* @property array|null $cast_to_encrypted_array -- These three are OK (no types)
* @property array $cast_to_encrypted_json some-description
* @property \Illuminate\Support\Collection $cast_to_encrypted_collection some-description
* @property string $cast_to_string -- The next three are OK (no description), this not included
* @property array<int, string>|null $cast_to_immutable_date
* @property array<int, string> $cast_to_immutable_date_serialization
* @property \Illuminate\Support\Collection<int, string> $cast_to_immutable_custom_datetime
* @property string $cast_to_int
* @property string $cast_to_integer
* @property string $cast_to_real
* @property string $cast_to_float
* @property string $cast_to_double
* @property string $cast_to_decimal
* @property string $cast_to_bool
* @property string $cast_to_boolean
* @property string $cast_to_object
* @property string $cast_to_date
* @property string $cast_to_datetime
* @property string $cast_to_date_serialization
* @property string $cast_to_datetime_serialization
* @property string $cast_to_custom_datetime
* @property string $cast_to_immutable_datetime
* @property string $cast_to_immutable_datetime_serialization
* @property string $cast_to_timestamp
* @property string $cast_to_encrypted
* @property string $cast_to_encrypted_object
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToArray($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToBool($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToBoolean($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToCollection($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToCustomDatetime($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToDate($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToDateSerialization($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToDatetime($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToDatetimeSerialization($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToDecimal($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToDouble($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToEncrypted($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToEncryptedArray($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToEncryptedCollection($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToEncryptedJson($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToEncryptedObject($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToFloat($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToImmutableCustomDatetime($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToImmutableDate($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToImmutableDateSerialization($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToImmutableDatetime($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToImmutableDatetimeSerialization($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToInt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToInteger($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToJson($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToObject($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToReal($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToString($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|ArrayCastsWithComment whereCastToTimestamp($value)
* @mixin \Eloquent
*/
class ArrayCastsWithComment extends Model
{
protected $table = 'simple_casts';
protected $casts = [
'cast_to_array' => 'array',
'cast_to_json' => 'json',
'cast_to_collection' => 'collection',
'cast_to_encrypted_array' => 'array',
'cast_to_encrypted_json' => 'json',
'cast_to_encrypted_collection' => 'collection',
'cast_to_string' => 'string',
'cast_to_immutable_date' => 'array',
'cast_to_immutable_date_serialization' => 'json',
'cast_to_immutable_custom_datetime' => 'collection',
];
}
@@ -1,59 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Attributes\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
class BackedAttribute extends Model
{
protected function name(): Attribute
{
return new Attribute(
function (?string $name): ?string {
return $name;
},
function (?string $name): ?string {
return $name;
}
);
}
protected function nameRead(): Attribute
{
return new Attribute(
function (?string $name): ?string {
return $name;
},
);
}
protected function nameWrite(): Attribute
{
return new Attribute(
set: function (?string $name): ?string {
return $name;
},
);
}
protected function nonBackedSet(): Attribute
{
return new Attribute(
set: function (?string $name): ?string {
return $name;
},
);
}
protected function nonBackedGet(): Attribute
{
return new Attribute(
get: function (): ?string {
return 'test';
},
);
}
}
@@ -1,117 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Attributes\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
class Simple extends Model
{
// With a backed property
protected function name(): Attribute
{
return new Attribute(
function (?string $name): ?string {
return $name;
},
function (?string $name): ?string {
return $name;
}
);
}
// Without backed properties
protected function typeHintedGetAndSet(): Attribute
{
return new Attribute(
function (): ?string {
return $this->name;
},
function (?string $name) {
$this->name = $name;
}
);
}
protected function divergingTypeHintedGetAndSet(): Attribute
{
return new Attribute(
function (): int {
return strlen($this->name);
},
function (?string $name) {
$this->name = $name;
}
);
}
protected function typeHintedGet(): Attribute
{
return Attribute::get(function (): ?string {
return $this->name;
});
}
protected function typeHintedSet(): Attribute
{
return Attribute::set(function (?string $name) {
$this->name = $name;
});
}
protected function nonTypeHintedGetAndSet(): Attribute
{
return new Attribute(
function () {
return $this->name;
},
function ($name) {
$this->name = $name;
}
);
}
protected function nonTypeHintedGet(): Attribute
{
return Attribute::get(function () {
return $this->name;
});
}
protected function nonTypeHintedSet(): Attribute
{
return Attribute::set(function ($name) {
$this->name = $name;
});
}
protected function parameterlessSet(): Attribute
{
return Attribute::set(function () {
$this->name = null;
});
}
/**
* ide-helper does not recognize this method being an Attribute
* because the method has no actual return type;
* phpdoc is ignored here deliberately due to performance reasons and also
* isn't supported by Laravel itself.
*
* @return Attribute
*/
protected function notAnAttribute()
{
return new Attribute(
function (?string $value): ?string {
return $value;
},
function (?string $value): ?string {
return $value;
}
);
}
}
@@ -1,24 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Attributes;
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AbstractModelsCommand;
class Test extends AbstractModelsCommand
{
public function test(): void
{
$command = $this->app->make(ModelsCommand::class);
$tester = $this->runCommand($command, [
'--write' => true,
]);
$this->assertSame(0, $tester->getStatusCode());
$this->assertStringContainsString('Written new phpDocBlock to', $tester->getDisplay());
$this->assertMatchesMockedSnapshot();
}
}
@@ -1,213 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Attributes\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
/**
*
*
* @property int $id
* @property string|null $name
* @property string|null $name_read
* @property string|null $name_write
* @property-read string|null $non_backed_get
* @property-write string|null $non_backed_set
* @method static \Illuminate\Database\Eloquent\Builder<static>|BackedAttribute newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|BackedAttribute newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|BackedAttribute query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|BackedAttribute whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|BackedAttribute whereName($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|BackedAttribute whereNameRead($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|BackedAttribute whereNameWrite($value)
* @mixin \Eloquent
*/
class BackedAttribute extends Model
{
protected function name(): Attribute
{
return new Attribute(
function (?string $name): ?string {
return $name;
},
function (?string $name): ?string {
return $name;
}
);
}
protected function nameRead(): Attribute
{
return new Attribute(
function (?string $name): ?string {
return $name;
},
);
}
protected function nameWrite(): Attribute
{
return new Attribute(
set: function (?string $name): ?string {
return $name;
},
);
}
protected function nonBackedSet(): Attribute
{
return new Attribute(
set: function (?string $name): ?string {
return $name;
},
);
}
protected function nonBackedGet(): Attribute
{
return new Attribute(
get: function (): ?string {
return 'test';
},
);
}
}
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Attributes\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
/**
*
*
* @property int $id
* @property int $diverging_type_hinted_get_and_set
* @property string|null $name
* @property-read mixed $non_type_hinted_get
* @property mixed $non_type_hinted_get_and_set
* @property-write mixed $non_type_hinted_set
* @property-write mixed $parameterless_set
* @property-read string|null $type_hinted_get
* @property string|null $type_hinted_get_and_set
* @property-write string|null $type_hinted_set
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple whereId($value)
* @mixin \Eloquent
*/
class Simple extends Model
{
// With a backed property
protected function name(): Attribute
{
return new Attribute(
function (?string $name): ?string {
return $name;
},
function (?string $name): ?string {
return $name;
}
);
}
// Without backed properties
protected function typeHintedGetAndSet(): Attribute
{
return new Attribute(
function (): ?string {
return $this->name;
},
function (?string $name) {
$this->name = $name;
}
);
}
protected function divergingTypeHintedGetAndSet(): Attribute
{
return new Attribute(
function (): int {
return strlen($this->name);
},
function (?string $name) {
$this->name = $name;
}
);
}
protected function typeHintedGet(): Attribute
{
return Attribute::get(function (): ?string {
return $this->name;
});
}
protected function typeHintedSet(): Attribute
{
return Attribute::set(function (?string $name) {
$this->name = $name;
});
}
protected function nonTypeHintedGetAndSet(): Attribute
{
return new Attribute(
function () {
return $this->name;
},
function ($name) {
$this->name = $name;
}
);
}
protected function nonTypeHintedGet(): Attribute
{
return Attribute::get(function () {
return $this->name;
});
}
protected function nonTypeHintedSet(): Attribute
{
return Attribute::set(function ($name) {
$this->name = $name;
});
}
protected function parameterlessSet(): Attribute
{
return Attribute::set(function () {
$this->name = null;
});
}
/**
* ide-helper does not recognize this method being an Attribute
* because the method has no actual return type;
* phpdoc is ignored here deliberately due to performance reasons and also
* isn't supported by Laravel itself.
*
* @return Attribute
*/
protected function notAnAttribute()
{
return new Attribute(
function (?string $value): ?string {
return $value;
},
function (?string $value): ?string {
return $value;
}
);
}
}
@@ -1,136 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Comment\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\MorphTo;
class Simple extends Model
{
/**
* There is not comment.
*
* @return string
*/
public function getNotCommentAttribute(): string
{
}
/**
* comment There is not format comment, invalid.
*
* @return string
*/
public function getFakerCommentAttribute(): string
{
}
/**
* @comment There is format comment, success.
*
* @return string
*/
public function getFormatCommentAttribute(): string
{
}
/**
* @comment There is format comment, success.
* This is second line, success too.
*
* @return string
*/
public function getFormatCommentLineTwoAttribute(): string
{
}
/**
* @comment There is format comment, success.
* @comment This is others format comment, invalid.
*
* @return string
*/
public function getManyFormatCommentAttribute(): string
{
}
/**
* @comment Set the user's first name.
* @param $value
*/
public function setFirstNameAttribute($value)
{
}
/**
* @comment Scope a query to only include active users.
*
* @param $query
* @return mixed
*/
public function scopeActive($query)
{
return $query;
}
/**
* @comment HasMany relations.
*
* @return HasMany
*/
public function relationHasMany(): HasMany
{
return $this->hasMany(Simple::class);
}
/**
* @comment MorphTo relations.
* @return MorphTo
*/
public function relationMorphTo(): MorphTo
{
return $this->morphTo();
}
/**
* @comment Others relations.
* @return HasOne
*/
public function relationHasOne(): HasOne
{
return $this->hasOne(Simple::class);
}
/**
* @comment I'm a setter
*/
public function setBothSameNameAttribute(): void
{
}
/**
* @comment I'm a getter
* @return string
*/
public function getBothSameNameAttribute(): string
{
}
/**
* @comment I'm a setter
*/
public function setBothWithoutGetterCommentAttribute(): void
{
}
/**
* @return string
*/
public function getBothWithoutGetterCommentAttribute(): string
{
}
}
@@ -1,24 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Comment;
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AbstractModelsCommand;
class Test extends AbstractModelsCommand
{
public function test(): void
{
$command = $this->app->make(ModelsCommand::class);
$tester = $this->runCommand($command, [
'--write' => true,
]);
$this->assertSame(0, $tester->getStatusCode());
$this->assertStringContainsString('Written new phpDocBlock to', $tester->getDisplay());
$this->assertMatchesMockedSnapshot();
}
}
@@ -1,160 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Comment\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\MorphTo;
/**
*
*
* @property int $id
* @property string $both_same_name I'm a getter
* @property string $both_without_getter_comment
* @property-read string $faker_comment
* @property-read string $format_comment There is format comment, success.
* @property-read string $format_comment_line_two There is format comment, success.
* This is second line, success too.
* @property-read string $many_format_comment There is format comment, success.
* @property-read string $not_comment
* @property-read \Illuminate\Database\Eloquent\Collection<int, Simple> $relationHasMany HasMany relations.
* @property-read int|null $relation_has_many_count
* @property-read Simple|null $relationHasOne Others relations.
* @property-read Model|\Eloquent $relationMorphTo MorphTo relations.
* @property-write mixed $first_name Set the user's first name.
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple active() Scope a query to only include active users.
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple whereId($value)
* @mixin \Eloquent
*/
class Simple extends Model
{
/**
* There is not comment.
*
* @return string
*/
public function getNotCommentAttribute(): string
{
}
/**
* comment There is not format comment, invalid.
*
* @return string
*/
public function getFakerCommentAttribute(): string
{
}
/**
* @comment There is format comment, success.
*
* @return string
*/
public function getFormatCommentAttribute(): string
{
}
/**
* @comment There is format comment, success.
* This is second line, success too.
*
* @return string
*/
public function getFormatCommentLineTwoAttribute(): string
{
}
/**
* @comment There is format comment, success.
* @comment This is others format comment, invalid.
*
* @return string
*/
public function getManyFormatCommentAttribute(): string
{
}
/**
* @comment Set the user's first name.
* @param $value
*/
public function setFirstNameAttribute($value)
{
}
/**
* @comment Scope a query to only include active users.
*
* @param $query
* @return mixed
*/
public function scopeActive($query)
{
return $query;
}
/**
* @comment HasMany relations.
*
* @return HasMany
*/
public function relationHasMany(): HasMany
{
return $this->hasMany(Simple::class);
}
/**
* @comment MorphTo relations.
* @return MorphTo
*/
public function relationMorphTo(): MorphTo
{
return $this->morphTo();
}
/**
* @comment Others relations.
* @return HasOne
*/
public function relationHasOne(): HasOne
{
return $this->hasOne(Simple::class);
}
/**
* @comment I'm a setter
*/
public function setBothSameNameAttribute(): void
{
}
/**
* @comment I'm a getter
* @return string
*/
public function getBothSameNameAttribute(): string
{
}
/**
* @comment I'm a setter
*/
public function setBothWithoutGetterCommentAttribute(): void
{
}
/**
* @return string
*/
public function getBothWithoutGetterCommentAttribute(): string
{
}
}
@@ -1,11 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\CustomCollection\Collections;
use Illuminate\Database\Eloquent\Collection;
class SimpleCollection extends Collection
{
}
@@ -1,22 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\CustomCollection\Models;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\CustomCollection\Collections\SimpleCollection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Simple extends Model
{
public function newCollection(array $models = [])
{
return new SimpleCollection($models);
}
public function relationHasMany(): HasMany
{
return $this->hasMany(Simple::class);
}
}
@@ -1,24 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\CustomCollection;
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AbstractModelsCommand;
class Test extends AbstractModelsCommand
{
public function test(): void
{
$command = $this->app->make(ModelsCommand::class);
$tester = $this->runCommand($command, [
'--write' => true,
]);
$this->assertSame(0, $tester->getStatusCode());
$this->assertStringContainsString('Written new phpDocBlock to', $tester->getDisplay());
$this->assertMatchesMockedSnapshot();
}
}
@@ -1,36 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\CustomCollection\Models;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\CustomCollection\Collections\SimpleCollection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
/**
*
*
* @property int $id
* @property-read SimpleCollection<int, Simple> $relationHasMany
* @property-read int|null $relation_has_many_count
* @method static SimpleCollection<int, static> all($columns = ['*'])
* @method static SimpleCollection<int, static> get($columns = ['*'])
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple whereId($value)
* @mixin \Eloquent
*/
class Simple extends Model
{
public function newCollection(array $models = [])
{
return new SimpleCollection($models);
}
public function relationHasMany(): HasMany
{
return $this->hasMany(Simple::class);
}
}
@@ -1,11 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\CustomDate\Models;
use Illuminate\Database\Eloquent\Model;
class CustomDate extends Model
{
}
@@ -1,41 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\CustomDate;
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AbstractModelsCommand;
use Carbon\CarbonImmutable;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Date;
class Test extends AbstractModelsCommand
{
protected function setUp(): void
{
parent::setUp();
Date::use(CarbonImmutable::class);
}
protected function tearDown(): void
{
Date::use(Carbon::class);
parent::tearDown();
}
public function test(): void
{
$command = $this->app->make(ModelsCommand::class);
$tester = $this->runCommand($command, [
'--write' => true,
]);
$this->assertSame(0, $tester->getStatusCode());
$this->assertStringContainsString('Written new phpDocBlock to', $tester->getDisplay());
$this->assertMatchesMockedSnapshot();
}
}
@@ -1,23 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\CustomDate\Models;
use Illuminate\Database\Eloquent\Model;
/**
*
*
* @property \Carbon\CarbonImmutable|null $created_at
* @property \Carbon\CarbonImmutable|null $updated_at
* @method static \Illuminate\Database\Eloquent\Builder<static>|CustomDate newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|CustomDate newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|CustomDate query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|CustomDate whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|CustomDate whereUpdatedAt($value)
* @mixin \Eloquent
*/
class CustomDate extends Model
{
}
@@ -1,19 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\CustomPhpdocTags\Models;
use Illuminate\Database\Eloquent\Model;
/**
* The `@SuppressWarnings` tag below contains no space before the `(` but when
* the class phpdoc is written back, one is inserted.
*
* @link https://github.com/barryvdh/laravel-ide-helper/issues/666
*
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
*/
class Simple extends Model
{
}
@@ -1,30 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\CustomPhpdocTags;
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AbstractModelsCommand;
class Test extends AbstractModelsCommand
{
/**
* This test makes sure that custom phpdoc tags are not mangled, e.g.
* there are no spaces inserted etc.
*
* @link https://github.com/barryvdh/laravel-ide-helper/issues/666
*/
public function testNoSpaceAfterCustomPhpdocTag(): void
{
$command = $this->app->make(ModelsCommand::class);
$tester = $this->runCommand($command, [
'--write' => true,
]);
$this->assertSame(0, $tester->getStatusCode());
$this->assertStringContainsString('Written new phpDocBlock to', $tester->getDisplay());
$this->assertMatchesMockedSnapshot();
}
}
@@ -1,24 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\CustomPhpdocTags\Models;
use Illuminate\Database\Eloquent\Model;
/**
* The `@SuppressWarnings` tag below contains no space before the `(` but when
* the class phpdoc is written back, one is inserted.
*
* @link https://github.com/barryvdh/laravel-ide-helper/issues/666
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
* @property int $id
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Simple whereId($value)
* @mixin \Eloquent
*/
class Simple extends Model
{
}
@@ -1,20 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\DoesNotGeneratePhpdocWithExternalEloquentBuilder\Builders;
use Illuminate\Database\Eloquent\Builder;
class PostExternalQueryBuilder extends Builder
{
public function isActive(): self
{
return $this;
}
public function isStatus(string $status): self
{
return $this;
}
}
@@ -1,16 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\DoesNotGeneratePhpdocWithExternalEloquentBuilder\Models;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\DoesNotGeneratePhpdocWithExternalEloquentBuilder\Builders\PostExternalQueryBuilder;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function newEloquentBuilder($query): PostExternalQueryBuilder
{
return new PostExternalQueryBuilder($query);
}
}
@@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\DoesNotGeneratePhpdocWithExternalEloquentBuilder;
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AbstractModelsCommand;
class Test extends AbstractModelsCommand
{
protected function getEnvironmentSetUp($app)
{
parent::getEnvironmentSetUp($app);
$app['config']->set('ide-helper.write_model_external_builder_methods', false);
}
public function test(): void
{
$command = $this->app->make(ModelsCommand::class);
$tester = $this->runCommand($command, [
'--nowrite' => true,
]);
$this->assertSame(0, $tester->getStatusCode());
$this->assertStringContainsString('Model information was written to _ide_helper_models.php', $tester->getDisplay());
$this->assertMatchesMockedSnapshot();
}
}
@@ -1,166 +0,0 @@
<?php
// @formatter:off
// phpcs:ignoreFile
/**
* A helper file for your Eloquent Models
* Copy the phpDocs from this file to the correct Model,
* And remove them from this file, to prevent double declarations.
*
* @author Barry vd. Heuvel <barryvdh@gmail.com>
*/
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\DoesNotGeneratePhpdocWithExternalEloquentBuilder\Models{
/**
*
*
* @property int $id
* @property string|null $char_nullable
* @property string $char_not_nullable
* @property string|null $string_nullable
* @property string $string_not_nullable
* @property string|null $text_nullable
* @property string $text_not_nullable
* @property string|null $medium_text_nullable
* @property string $medium_text_not_nullable
* @property string|null $long_text_nullable
* @property string $long_text_not_nullable
* @property int|null $integer_nullable
* @property int $integer_not_nullable
* @property int|null $tiny_integer_nullable
* @property int $tiny_integer_not_nullable
* @property int|null $small_integer_nullable
* @property int $small_integer_not_nullable
* @property int|null $medium_integer_nullable
* @property int $medium_integer_not_nullable
* @property int|null $big_integer_nullable
* @property int $big_integer_not_nullable
* @property int|null $unsigned_integer_nullable
* @property int $unsigned_integer_not_nullable
* @property int|null $unsigned_tiny_integer_nullable
* @property int $unsigned_tiny_integer_not_nullable
* @property int|null $unsigned_small_integer_nullable
* @property int $unsigned_small_integer_not_nullable
* @property int|null $unsigned_medium_integer_nullable
* @property int $unsigned_medium_integer_not_nullable
* @property int|null $unsigned_big_integer_nullable
* @property int $unsigned_big_integer_not_nullable
* @property float|null $float_nullable
* @property float $float_not_nullable
* @property float|null $double_nullable
* @property float $double_not_nullable
* @property string|null $decimal_nullable
* @property string $decimal_not_nullable
* @property int|null $boolean_nullable
* @property int $boolean_not_nullable
* @property string|null $enum_nullable
* @property string $enum_not_nullable
* @property string|null $json_nullable
* @property string $json_not_nullable
* @property string|null $jsonb_nullable
* @property string $jsonb_not_nullable
* @property string|null $date_nullable
* @property string $date_not_nullable
* @property string|null $datetime_nullable
* @property string $datetime_not_nullable
* @property string|null $datetimetz_nullable
* @property string $datetimetz_not_nullable
* @property string|null $time_nullable
* @property string $time_not_nullable
* @property string|null $timetz_nullable
* @property string $timetz_not_nullable
* @property string|null $timestamp_nullable
* @property string $timestamp_not_nullable
* @property string|null $timestamptz_nullable
* @property string $timestamptz_not_nullable
* @property int|null $year_nullable
* @property int $year_not_nullable
* @property string|null $binary_nullable
* @property string $binary_not_nullable
* @property string|null $uuid_nullable
* @property string $uuid_not_nullable
* @property string|null $ipaddress_nullable
* @property string $ipaddress_not_nullable
* @property string|null $macaddress_nullable
* @property string $macaddress_not_nullable
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\DoesNotGeneratePhpdocWithExternalEloquentBuilder\Builders\PostExternalQueryBuilder<static>|Post newModelQuery()
* @method static \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\DoesNotGeneratePhpdocWithExternalEloquentBuilder\Builders\PostExternalQueryBuilder<static>|Post newQuery()
* @method static \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\DoesNotGeneratePhpdocWithExternalEloquentBuilder\Builders\PostExternalQueryBuilder<static>|Post query()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereBigIntegerNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereBigIntegerNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereBinaryNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereBinaryNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereBooleanNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereBooleanNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereCharNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereCharNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereDateNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereDateNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereDatetimeNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereDatetimeNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereDatetimetzNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereDatetimetzNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereDecimalNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereDecimalNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereDoubleNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereDoubleNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereEnumNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereEnumNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereFloatNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereFloatNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereIntegerNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereIntegerNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereIpaddressNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereIpaddressNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereJsonNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereJsonNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereJsonbNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereJsonbNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereLongTextNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereLongTextNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereMacaddressNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereMacaddressNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereMediumIntegerNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereMediumIntegerNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereMediumTextNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereMediumTextNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereSmallIntegerNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereSmallIntegerNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereStringNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereStringNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTextNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTextNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTimeNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTimeNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTimestampNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTimestampNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTimestamptzNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTimestamptzNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTimetzNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTimetzNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTinyIntegerNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereTinyIntegerNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUnsignedBigIntegerNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUnsignedBigIntegerNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUnsignedIntegerNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUnsignedIntegerNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUnsignedMediumIntegerNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUnsignedMediumIntegerNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUnsignedSmallIntegerNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUnsignedSmallIntegerNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUnsignedTinyIntegerNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUnsignedTinyIntegerNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUuidNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereUuidNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereYearNotNullable($value)
* @method static \Illuminate\Database\Eloquent\Builder<static>|Post whereYearNullable($value)
*/
class Post extends \Eloquent {}
}
@@ -1,38 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\DynamicRelations\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
class Dynamic extends Model
{
/** @var \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\DynamicRelations\OtherModels\Account */
protected $account;
// Regular relations
public function regularHasMany(): HasMany
{
return $this->hasMany(Dynamic::class);
}
// Dynamic relations
public function dynamicHasMany(): HasMany
{
return $this->hasMany(Dynamic::class)->where('date', '>=', $this->account->created_at);
}
public function dynamicHasOne(): HasOne
{
return $this->hasOne(Dynamic::class)->where('date', '>=', $this->account->created_at);
}
public function dynamicBelongsTo(): BelongsTo
{
return $this->belongsTo(Dynamic::class)->where('date', '>=', $this->account->created_at);
}
}
@@ -1,11 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\DynamicRelations\OtherModels;
use Illuminate\Database\Eloquent\Model;
class Account extends Model
{
}
@@ -1,33 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\DynamicRelations;
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AbstractModelsCommand;
class Test extends AbstractModelsCommand
{
public function test(): void
{
$command = $this->app->make(ModelsCommand::class);
$tester = $this->runCommand($command, [
'--write' => true,
]);
$errors = [
'Error resolving relation model of Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\DynamicRelations\Models\Dynamic:dynamicBelongsTo() : Attempt to read property "created_at" on null',
'Error resolving relation model of Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\DynamicRelations\Models\Dynamic:dynamicHasMany() : Attempt to read property "created_at" on null',
'Error resolving relation model of Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\DynamicRelations\Models\Dynamic:dynamicHasOne() : Attempt to read property "created_at" on null',
];
$this->assertSame(0, $tester->getStatusCode());
$this->assertStringContainsString('Written new phpDocBlock to', $tester->getDisplay());
foreach ($errors as $error) {
$this->assertStringContainsString($error, $tester->getDisplay());
}
$this->assertMatchesMockedSnapshot();
}
}
@@ -1,48 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\DynamicRelations\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
/**
*
*
* @property-read \Illuminate\Database\Eloquent\Collection<int, Dynamic> $regularHasMany
* @property-read int|null $regular_has_many_count
* @method static \Illuminate\Database\Eloquent\Builder<static>|Dynamic newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Dynamic newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|Dynamic query()
* @mixin \Eloquent
*/
class Dynamic extends Model
{
/** @var \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\DynamicRelations\OtherModels\Account */
protected $account;
// Regular relations
public function regularHasMany(): HasMany
{
return $this->hasMany(Dynamic::class);
}
// Dynamic relations
public function dynamicHasMany(): HasMany
{
return $this->hasMany(Dynamic::class)->where('date', '>=', $this->account->created_at);
}
public function dynamicHasOne(): HasOne
{
return $this->hasOne(Dynamic::class)->where('date', '>=', $this->account->created_at);
}
public function dynamicBelongsTo(): BelongsTo
{
return $this->belongsTo(Dynamic::class)->where('date', '>=', $this->account->created_at);
}
}
@@ -1,30 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\CustomSpace;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\Models\ModelWithCustomNamespace;
use Illuminate\Database\Eloquent\Factories\Factory;
class ModelWithCustomNamespaceFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = ModelWithCustomNamespace::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
//
];
}
}
@@ -1,30 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\Factories;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\Models\ModelWithFactory;
use Illuminate\Database\Eloquent\Factories\Factory;
class ModelWithFactoryFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = ModelWithFactory::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
//
];
}
}
@@ -1,30 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\Factories;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\Models\ModelWithNestedFactory;
use Illuminate\Database\Eloquent\Factories\Factory;
class ModelWithNestedFactoryFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = ModelWithNestedFactory::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
//
];
}
}
@@ -1,24 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\Models;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\CustomSpace\ModelWithCustomNamespaceFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ModelWithCustomNamespace extends Model
{
use HasFactory;
/**
* Create a new factory instance for the model.
*
* @return \Illuminate\Database\Eloquent\Factories\Factory
*/
protected static function newFactory()
{
return ModelWithCustomNamespaceFactory::new();
}
}
@@ -1,13 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ModelWithFactory extends Model
{
use HasFactory;
}
@@ -1,9 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\Models;
class ModelWithNestedFactory extends ModelWithFactory
{
}
@@ -1,13 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ModelWithoutFactory extends Model
{
use HasFactory;
}
@@ -1,45 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories;
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AbstractModelsCommand;
use Closure;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class Test extends AbstractModelsCommand
{
public function testFactory(): void
{
Factory::guessFactoryNamesUsing(static::getFactoryNameResolver());
$command = $this->app->make(ModelsCommand::class);
$tester = $this->runCommand($command, [
'--write' => true,
]);
$this->assertSame(0, $tester->getStatusCode());
$this->assertStringContainsString('Written new phpDocBlock to', $tester->getDisplay());
$this->assertStringNotContainsString('not found', $tester->getDisplay());
$this->assertMatchesMockedSnapshot();
}
public static function getFactoryNameResolver(): Closure
{
// This mimics the default resolver, but with adjusted test namespaces.
// Illuminate\Database\Eloquent\Factories\Factory::resolveFactoryName
return function (string $modelName): string {
$appNamespace = 'Barryvdh\\LaravelIdeHelper\\Tests\\Console\\ModelsCommand\\Factories\\';
$modelName = Str::startsWith($modelName, $appNamespace . 'Models\\')
? Str::after($modelName, $appNamespace . 'Models\\')
: Str::after($modelName, $appNamespace);
return $appNamespace . 'Factories\\' . $modelName . 'Factory';
};
}
}
@@ -1,94 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\Models;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\CustomSpace\ModelWithCustomNamespaceFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
/**
*
*
* @method static \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\CustomSpace\ModelWithCustomNamespaceFactory factory($count = null, $state = [])
* @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithCustomNamespace newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithCustomNamespace newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithCustomNamespace query()
* @mixin \Eloquent
*/
class ModelWithCustomNamespace extends Model
{
use HasFactory;
/**
* Create a new factory instance for the model.
*
* @return \Illuminate\Database\Eloquent\Factories\Factory
*/
protected static function newFactory()
{
return ModelWithCustomNamespaceFactory::new();
}
}
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
/**
*
*
* @method static \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\Factories\ModelWithFactoryFactory factory($count = null, $state = [])
* @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithFactory newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithFactory newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithFactory query()
* @mixin \Eloquent
*/
class ModelWithFactory extends Model
{
use HasFactory;
}
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\Models;
/**
*
*
* @method static \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\Factories\ModelWithNestedFactoryFactory factory($count = null, $state = [])
* @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithNestedFactory newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithNestedFactory newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithNestedFactory query()
* @mixin \Eloquent
*/
class ModelWithNestedFactory extends ModelWithFactory
{
}
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\Factories\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
/**
*
*
* @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithoutFactory newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithoutFactory newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|ModelWithoutFactory query()
* @mixin \Eloquent
*/
class ModelWithoutFactory extends Model
{
use HasFactory;
}
@@ -1,14 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhpDocWithEnumDefaults\Enums;
enum PostStatus
{
case Published;
case Unpublished;
case Archived;
}
@@ -1,17 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhpDocWithEnumDefaults\Models;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhpDocWithEnumDefaults\Enums\PostStatus;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function scopeHasStatus(Builder $query, ?PostStatus $status = PostStatus::Published)
{
//
}
}
@@ -1,24 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhpDocWithEnumDefaults;
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AbstractModelsCommand;
class Test extends AbstractModelsCommand
{
public function test(): void
{
$command = $this->app->make(ModelsCommand::class);
$tester = $this->runCommand($command, [
'--write' => true,
]);
$this->assertSame(0, $tester->getStatusCode());
$this->assertStringContainsString('Written new phpDocBlock to', $tester->getDisplay());
$this->assertMatchesMockedSnapshot();
}
}
@@ -1,168 +0,0 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhpDocWithEnumDefaults\Models;
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhpDocWithEnumDefaults\Enums\PostStatus;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
/**
*
*
* @property int $id
* @property string|null $char_nullable
* @property string $char_not_nullable
* @property string|null $string_nullable
* @property string $string_not_nullable
* @property string|null $text_nullable
* @property string $text_not_nullable
* @property string|null $medium_text_nullable
* @property string $medium_text_not_nullable
* @property string|null $long_text_nullable
* @property string $long_text_not_nullable
* @property int|null $integer_nullable
* @property int $integer_not_nullable
* @property int|null $tiny_integer_nullable
* @property int $tiny_integer_not_nullable
* @property int|null $small_integer_nullable
* @property int $small_integer_not_nullable
* @property int|null $medium_integer_nullable
* @property int $medium_integer_not_nullable
* @property int|null $big_integer_nullable
* @property int $big_integer_not_nullable
* @property int|null $unsigned_integer_nullable
* @property int $unsigned_integer_not_nullable
* @property int|null $unsigned_tiny_integer_nullable
* @property int $unsigned_tiny_integer_not_nullable
* @property int|null $unsigned_small_integer_nullable
* @property int $unsigned_small_integer_not_nullable
* @property int|null $unsigned_medium_integer_nullable
* @property int $unsigned_medium_integer_not_nullable
* @property int|null $unsigned_big_integer_nullable
* @property int $unsigned_big_integer_not_nullable
* @property float|null $float_nullable
* @property float $float_not_nullable
* @property float|null $double_nullable
* @property float $double_not_nullable
* @property string|null $decimal_nullable
* @property string $decimal_not_nullable
* @property int|null $boolean_nullable
* @property int $boolean_not_nullable
* @property string|null $enum_nullable
* @property string $enum_not_nullable
* @property string|null $json_nullable
* @property string $json_not_nullable
* @property string|null $jsonb_nullable
* @property string $jsonb_not_nullable
* @property string|null $date_nullable
* @property string $date_not_nullable
* @property string|null $datetime_nullable
* @property string $datetime_not_nullable
* @property string|null $datetimetz_nullable
* @property string $datetimetz_not_nullable
* @property string|null $time_nullable
* @property string $time_not_nullable
* @property string|null $timetz_nullable
* @property string $timetz_not_nullable
* @property string|null $timestamp_nullable
* @property string $timestamp_not_nullable
* @property string|null $timestamptz_nullable
* @property string $timestamptz_not_nullable
* @property int|null $year_nullable
* @property int $year_not_nullable
* @property string|null $binary_nullable
* @property string $binary_not_nullable
* @property string|null $uuid_nullable
* @property string $uuid_not_nullable
* @property string|null $ipaddress_nullable
* @property string $ipaddress_not_nullable
* @property string|null $macaddress_nullable
* @property string $macaddress_not_nullable
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @method static Builder<static>|Post hasStatus(?\Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhpDocWithEnumDefaults\Enums\PostStatus $status = \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenerateBasicPhpDocWithEnumDefaults\Enums\PostStatus::Published)
* @method static Builder<static>|Post newModelQuery()
* @method static Builder<static>|Post newQuery()
* @method static Builder<static>|Post query()
* @method static Builder<static>|Post whereBigIntegerNotNullable($value)
* @method static Builder<static>|Post whereBigIntegerNullable($value)
* @method static Builder<static>|Post whereBinaryNotNullable($value)
* @method static Builder<static>|Post whereBinaryNullable($value)
* @method static Builder<static>|Post whereBooleanNotNullable($value)
* @method static Builder<static>|Post whereBooleanNullable($value)
* @method static Builder<static>|Post whereCharNotNullable($value)
* @method static Builder<static>|Post whereCharNullable($value)
* @method static Builder<static>|Post whereCreatedAt($value)
* @method static Builder<static>|Post whereDateNotNullable($value)
* @method static Builder<static>|Post whereDateNullable($value)
* @method static Builder<static>|Post whereDatetimeNotNullable($value)
* @method static Builder<static>|Post whereDatetimeNullable($value)
* @method static Builder<static>|Post whereDatetimetzNotNullable($value)
* @method static Builder<static>|Post whereDatetimetzNullable($value)
* @method static Builder<static>|Post whereDecimalNotNullable($value)
* @method static Builder<static>|Post whereDecimalNullable($value)
* @method static Builder<static>|Post whereDoubleNotNullable($value)
* @method static Builder<static>|Post whereDoubleNullable($value)
* @method static Builder<static>|Post whereEnumNotNullable($value)
* @method static Builder<static>|Post whereEnumNullable($value)
* @method static Builder<static>|Post whereFloatNotNullable($value)
* @method static Builder<static>|Post whereFloatNullable($value)
* @method static Builder<static>|Post whereId($value)
* @method static Builder<static>|Post whereIntegerNotNullable($value)
* @method static Builder<static>|Post whereIntegerNullable($value)
* @method static Builder<static>|Post whereIpaddressNotNullable($value)
* @method static Builder<static>|Post whereIpaddressNullable($value)
* @method static Builder<static>|Post whereJsonNotNullable($value)
* @method static Builder<static>|Post whereJsonNullable($value)
* @method static Builder<static>|Post whereJsonbNotNullable($value)
* @method static Builder<static>|Post whereJsonbNullable($value)
* @method static Builder<static>|Post whereLongTextNotNullable($value)
* @method static Builder<static>|Post whereLongTextNullable($value)
* @method static Builder<static>|Post whereMacaddressNotNullable($value)
* @method static Builder<static>|Post whereMacaddressNullable($value)
* @method static Builder<static>|Post whereMediumIntegerNotNullable($value)
* @method static Builder<static>|Post whereMediumIntegerNullable($value)
* @method static Builder<static>|Post whereMediumTextNotNullable($value)
* @method static Builder<static>|Post whereMediumTextNullable($value)
* @method static Builder<static>|Post whereSmallIntegerNotNullable($value)
* @method static Builder<static>|Post whereSmallIntegerNullable($value)
* @method static Builder<static>|Post whereStringNotNullable($value)
* @method static Builder<static>|Post whereStringNullable($value)
* @method static Builder<static>|Post whereTextNotNullable($value)
* @method static Builder<static>|Post whereTextNullable($value)
* @method static Builder<static>|Post whereTimeNotNullable($value)
* @method static Builder<static>|Post whereTimeNullable($value)
* @method static Builder<static>|Post whereTimestampNotNullable($value)
* @method static Builder<static>|Post whereTimestampNullable($value)
* @method static Builder<static>|Post whereTimestamptzNotNullable($value)
* @method static Builder<static>|Post whereTimestamptzNullable($value)
* @method static Builder<static>|Post whereTimetzNotNullable($value)
* @method static Builder<static>|Post whereTimetzNullable($value)
* @method static Builder<static>|Post whereTinyIntegerNotNullable($value)
* @method static Builder<static>|Post whereTinyIntegerNullable($value)
* @method static Builder<static>|Post whereUnsignedBigIntegerNotNullable($value)
* @method static Builder<static>|Post whereUnsignedBigIntegerNullable($value)
* @method static Builder<static>|Post whereUnsignedIntegerNotNullable($value)
* @method static Builder<static>|Post whereUnsignedIntegerNullable($value)
* @method static Builder<static>|Post whereUnsignedMediumIntegerNotNullable($value)
* @method static Builder<static>|Post whereUnsignedMediumIntegerNullable($value)
* @method static Builder<static>|Post whereUnsignedSmallIntegerNotNullable($value)
* @method static Builder<static>|Post whereUnsignedSmallIntegerNullable($value)
* @method static Builder<static>|Post whereUnsignedTinyIntegerNotNullable($value)
* @method static Builder<static>|Post whereUnsignedTinyIntegerNullable($value)
* @method static Builder<static>|Post whereUpdatedAt($value)
* @method static Builder<static>|Post whereUuidNotNullable($value)
* @method static Builder<static>|Post whereUuidNullable($value)
* @method static Builder<static>|Post whereYearNotNullable($value)
* @method static Builder<static>|Post whereYearNullable($value)
* @mixin \Eloquent
*/
class Post extends Model
{
public function scopeHasStatus(Builder $query, ?PostStatus $status = PostStatus::Published)
{
//
}
}

Some files were not shown because too many files have changed in this diff Show More