Compare commits

...
23 Commits
Author SHA1 Message Date
Barry vd. Heuvel 485c756f6c Prepare 2.14.0 release 2024-02-05 09:16:36 +01:00
Markus Podar cf4687f98c Prepare 2.14.0 release (#1503) 2024-02-05 09:13:57 +01:00
Markus Podar e65d30b27a Remove doctrine/dbal:^4 support (#1507)
* Remove doctrine/dbal:^4 support

Tests fail with:
`PHP Fatal error:  Declaration of Illuminate\Database\PDO\Concerns\ConnectsToDatabase::connect(array $params, $username = null, $password = null, array $driverOptions = []) must be compatible with Doctrine\DBAL\Driver::connect(array $params): Doctrine\DBAL\Driver\Connection in /home/runner/work/laravel-ide-helper/laravel-ide-helper/vendor/laravel/framework/src/Illuminate/Database/PDO/Concerns/ConnectsToDatabase.php on line 22`

* gha: install with downgrading all dependencies

* Add note to readme
2024-02-05 06:54:43 +01:00
Markus Podar 416e0ab243 Merge pull request #1506 from olexoliinyk0/test/case-of-1505
test: case for the issue #1505;
2024-02-03 21:02:28 +01:00
Markus Podar 9374952402 Adapt snapshot testcase 2024-02-03 20:56:57 +01:00
Oleksandr Oliinyk 850fc5fe7f test: case for the issue #1505;
duplication of properties that have generic types specified and descriptions;
2024-02-02 18:37:44 +02:00
Markus Podar 726e595578 Add support for nikic/php-parser:^5 and (hopefully) doctrine/dbal:^4 (#1502)
* Add support for nikic/php-parser:^5

- `createForHostVersion` has been added to php-parse 4.18 so code can
  run with both versions [1]
- therefore also bumped the minimum required version to it

Note:
The dev dependency vimeo/psalm is **not** compatible with
php-parser:^5 currently. This does not impact usages of this library,
but sometimes cause friction when working on this library.
For our CI this isn't a problem, because we already remove that
dependency before running the test suite.

[1] https://github.com/nikic/PHP-Parser/blob/master/UPGRADE-5.0.md#changes-to-the-parser-factory

* gha: prevent cancelling of all jobs if one fails

* Update CHANGELOG.md

* gha: remove unsupported Laravel / PHP combinations

According to https://laravel.com/docs/10.x/releases

* Add dbal:^4 too
2024-01-28 19:33:31 +01:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 6336db0548 Bump the deps group with 1 update (#1478)
Bumps the deps group with 1 update: [stefanzweifel/git-auto-commit-action](https://github.com/stefanzweifel/git-auto-commit-action).

- [Release notes](https://github.com/stefanzweifel/git-auto-commit-action/releases)
- [Changelog](https://github.com/stefanzweifel/git-auto-commit-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stefanzweifel/git-auto-commit-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: stefanzweifel/git-auto-commit-action
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: deps
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-01 10:36:20 +01:00
Markus Podar 21352a1e48 Merge pull request #1473 from sergiy-petrov/php8.3 2023-10-05 15:58:39 +02:00
Serhii Petrov 390874207f Test against php 8.2 and 8.3
Integration tests against 8.3
Unit tests against 8.2 and 8.3
2023-10-05 16:10:38 +03:00
Markus Podar 3cdd3af631 chore: add dependabot for github actions (#1470) 2023-09-29 09:26:16 +02:00
erikn69 c751d3e176 ci: Use GitHub Actions V4 (#1469) 2023-09-29 09:25:55 +02:00
Markus Podar 1a3affd4f8 Catch error and exception (#1431) (#1465)
Credit goes to @dongm2ez
2023-09-06 12:35:33 +02:00
Markus Podar 0801d002e4 Fix tests for edc422cd2e (#1457)
I just ran `composer test-regenerate`
2023-07-31 13:26:41 +02:00
Gerardo Ibarra edc422cd2e add annotation ignore for php code sniffer (#1456) 2023-07-31 11:08:02 +02:00
Markus PodarandBarry vd. Heuvel 4dc20b028a Remove offical support for Lumen (#1425)
I'm proposing to drop official suport for Lumen for the following reasons:
- Lumen itself is dead, per [1]
  > **Note:** In the years since releasing Lumen, PHP has made a variety of wonderful performance improvements. For this reason, along with the availability of [Laravel Octane](https://laravel.com/docs/octane), we no longer recommend that you begin new projects with Lumen. Instead, we recommend always beginning new projects with [Laravel](https://laravel.com).

  Laravel Octact is just Laravel and no one using ide-helper with it
  needs anything special.
- For now, the change is mostly on the logistics side (readme, run tests,
  issues). In the past we had some special code but over time this was
  already removed.
  For now people still can use it and nothing will break out of the blue,
  but eventually it might

There are a only a few Lumen related issues open currently which would
be closed by this (#1105, #1069, #438).

[1] https://github.com/laravel/lumen/commit/69b26578d2f15595ea901278434b74df459c4329

Co-authored-by: Barry vd. Heuvel <[email protected]>
2023-02-20 13:23:52 +01:00
39885645b9 Add support for protected Attribute accessors (#1339)
* Add support for protected Attribute accessors

* Fix formatting

* Prevent accessors methods marked as private from being added

* Exclude specific accessors based on trait instead of class

* Add changelog entry

* Add clarifying comment

* Fix accessor attributes not working on PHP < 8.1

* Reintroduce method variable to reduce PR clutter

* Change variable name to reduce PR clutter

* Update CHANGELOG.md

---------

Co-authored-by: Barry vd. Heuvel <[email protected]>
Co-authored-by: Barry vd. Heuvel <[email protected]>
2023-02-20 09:44:01 +01:00
Barry vd. Heuvel aa1aa66ee6 Update CHANGELOG.md 2023-02-20 09:40:08 +01:00
b70a9f5048 add immutable_date/time:* casts (#1380)
* add immutable_date/time:* casts

* fix style

* Update CHANGELOG.md

---------

Co-authored-by: Barry vd. Heuvel <[email protected]>
Co-authored-by: Barry vd. Heuvel <[email protected]>
2023-02-20 09:36:24 +01:00
Wim Reckmanandlaravel-ide-helper 9f97f7cd5f Refactor resolving of null information for custom casted attribute types (#1330)
* Refactor resolving of null information for custom casted attribute types

* composer fix-style

---------

Co-authored-by: laravel-ide-helper <[email protected]>
2023-02-20 09:29:48 +01:00
Markus Podar 97fd0e0a2d Update changelog after new release 2.13.0 (#1418) 2023-02-04 22:04:42 +01:00
Alies Lapatsin 9f5670b7e9 Bump Psalm version (#1410)
SSH facade removed from Laravel 5:
 - https://github.com/laravel/framework/tree/v8.83.27/src/Illuminate/Support/Facades
 - https://github.com/laravel/framework/tree/v9.48.0/src/Illuminate/Support/Facades
  - https://github.com/laravel/framework/tree/10.x/src/Illuminate/Support/Facades
2023-02-04 22:04:01 +01:00
Barry vd. Heuvel 1d302435ef Update composer.json 2023-02-04 16:23:19 +01:00
34 changed files with 341 additions and 194 deletions
-1
View File
@@ -8,7 +8,6 @@ labels: bug
### Versions:
- ide-helper Version: #.#.#
- Laravel Version: #.#.# <!-- remove if not applicable -->
- Lumen Version: #.#.# <!-- remove if not applicable -->
- PHP Version: #.#.#
### Description:
@@ -8,7 +8,6 @@ labels: question
### Versions:
- ide-helper Version: #.#.#
- Laravel Version: #.#.# <!-- remove if not applicable -->
- Lumen Version: #.#.# <!-- remove if not applicable -->
- PHP Version: #.#.#
### Question:
+10
View File
@@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: monthly
groups:
deps:
patterns:
- '*'
+2 -2
View File
@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Git checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Validate Composer configuration
run: composer validate --strict
@@ -23,6 +23,6 @@ jobs:
composer global require ergebnis/composer-normalize
composer normalize
- uses: stefanzweifel/git-auto-commit-action@v4.0.0
- uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: normalize composer.json
+2 -2
View File
@@ -13,7 +13,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
@@ -27,7 +27,7 @@ jobs:
- run: composer fix-style
continue-on-error: true
- uses: stefanzweifel/git-auto-commit-action@v4
- uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: composer fix-style
commit_author: laravel-ide-helper <[email protected]>
+10 -69
View File
@@ -11,96 +11,37 @@ on:
- cron: '0 0 * * *'
jobs:
php-lumen-integration-tests:
runs-on: ubuntu-20.04
timeout-minutes: 15
env:
COMPOSER_NO_INTERACTION: 1
strategy:
matrix:
php: [8.2, 8.1, 8.0, 7.4, 7.3]
lumen: [8.*]
name: P${{ matrix.php }} - Lumen${{ matrix.lumen }}
steps:
- name: Checkout code
uses: actions/checkout@v2
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/lumen:${{ matrix.lumen }} --no-progress sample
cd sample
composer config minimum-stability dev
composer require "league/flysystem:^1" --no-update --no-progress
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:*"
- name: Insert service provider
run: sed -e 's|// \$app->register(App\\\Providers\\\EventServiceProvider::class);|&\n$app->register(\\Barryvdh\\LaravelIdeHelper\\IdeHelperServiceProvider::class);|' -i sample/bootstrap/app.php
- 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
php-laravel-integration-tests:
runs-on: ubuntu-20.04
timeout-minutes: 15
env:
COMPOSER_NO_INTERACTION: 1
strategy:
fail-fast: false
matrix:
php: [8.2, 8.1, 8.0, 7.4, 7.3]
php: [8.3, 8.2, 8.1, 8.0, 7.4, 7.3]
laravel: [10.*, 9.*, 8.*]
exclude:
- php: 8.0
laravel: 10.*
- php: 7.4
laravel: 10.*
- php: 7.4
laravel: 10.*
- php: 7.3
laravel: 10.*
- php: 8.3
laravel: 9.*
- php: 7.4
laravel: 9.*
- php: 7.3
laravel: 9.*
- php: 8.3
laravel: 8.*
- php: 8.2
laravel: 8.*
name: P${{ matrix.php }} - Laravel${{ matrix.laravel }}
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
path: src
@@ -121,7 +62,7 @@ jobs:
run: |
cd sample
sed -e 's|"type": "project",|&\n"repositories": [ { "type": "path", "url": "../src" } ],|' -i composer.json
composer require --dev "barryvdh/laravel-ide-helper:*"
composer require --dev "barryvdh/laravel-ide-helper:*" --with-all-dependencies
- name: Execute generate run
run: |
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
+2 -2
View File
@@ -20,7 +20,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-20.04, windows-2019]
php: [8.1, 8.0, 7.4, 7.3]
php: [8.3, 8.2, 8.1, 8.0, 7.4, 7.3]
laravel: [8.*, 9.*, 10.*]
dependency-version: [prefer-lowest, prefer-stable]
exclude:
@@ -48,7 +48,7 @@ jobs:
git config --global core.eol lf
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
+20 -2
View File
@@ -2,10 +2,28 @@
All notable changes to this project will be documented in this file.
[Next release](https://github.com/barryvdh/laravel-ide-helper/compare/v2.12.3...master)
[Next release](https://github.com/barryvdh/laravel-ide-helper/compare/v2.14.0...master)
--------------
### Fixes
2024-02-05, 2.14.0
------------------
### Changed
- Official support for Lumen has been dropped [#1425 / mfn](https://github.com/barryvdh/laravel-ide-helper/pull/1425)
- Refactor resolving of null information for custom casted attribute types [#1330 / wimski](https://github.com/barryvdh/laravel-ide-helper/pull/1330)
### Fixed
- Add support for attribute accessors marked as protected. [#1339 / pindab0ter](https://github.com/barryvdh/laravel-ide-helper/pull/1339)
- Catch exceptions when loading aliases [#1465 / dongm2ez](https://github.com/barryvdh/laravel-ide-helper/pull/1465)
### Added
- Add support for nikic/php-parser 5 (next to 4) [#1502 / mfn](https://github.com/barryvdh/laravel-ide-helper/pull/1502)
- Add support for `immutable_date:*` and `immutable_datetime:*` casts. [#1380 / thekonz](https://github.com/barryvdh/laravel-ide-helper/pull/1380)
2023-02-04, 2.13.0
------------------
### Fixed
- Fix return type of methods provided by `SoftDeletes` [#1345 / KentarouTakeda](https://github.com/barryvdh/laravel-ide-helper/pull/1345)
- Handle PHP 8.1 deprecation warnings when passing `null` to `new \ReflectionClass` [#1351 / mfn](https://github.com/barryvdh/laravel-ide-helper/pull/1351)
- Fix issue where \Eloquent is not included when using write_mixin [#1352 / Jefemy](https://github.com/barryvdh/laravel-ide-helper/pull/1352)
+4 -64
View File
@@ -23,10 +23,6 @@ It supports Laravel 8+ and PHP 7.3+
- [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)
- [Usage with Lumen](#usage-with-lumen)
- [Enabling Facades](#enabling-facades)
- [Adding the Service Provider](#adding-the-service-provider)
- [Adding Additional Facades](#adding-additional-facades)
- [License](#license)
## Installation
@@ -37,6 +33,10 @@ Require this package with composer using the following command:
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:
@@ -404,66 +404,6 @@ app(App\SomeClass::class);
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.
## Usage with Lumen
This package is focused on Laravel development, but it can also be used in Lumen with some workarounds.
Because Lumen works a little different, as it is like a bare bone version of Laravel and the main configuration
parameters are instead located in `bootstrap/app.php`, some alterations must be made.
### Enabling Facades
While Laravel IDE Helper can generate automatically default Facades for code hinting,
Lumen doesn't come with Facades activated. If you plan in using them, you must enable
them under the `Create The Application` section, uncommenting this line:
```php
// $app->withFacades();
```
From there, you should be able to use the `create_alias()` function to add additional Facades into your application.
### Adding the Service Provider
You can install Laravel IDE Helper in `app/Providers/AppServiceProvider.php`,
and uncommenting this line that registers the App Service Providers, so it can properly load.
```php
// $app->register(App\Providers\AppServiceProvider::class);
```
If you are not using that line, that is usually handy to manage gracefully multiple Laravel/Lumen installations,
you will have to add this line of code under the `Register Service Providers` section of your `bootstrap/app.php`.
```php
if ($app->environment() !== 'production') {
$app->register(\Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class);
}
```
After that, Laravel IDE Helper should work correctly. During the generation process,
the script may throw exceptions saying that some Class(s) doesn't exist or there are some undefined indexes.
This is normal, as Lumen has some default packages stripped away, like Cookies, Storage and Session.
If you plan to add these packages, you will have to add them manually and create additional Facades if needed.
### Adding Additional Facades
Currently, Lumen IDE Helper doesn't take into account additional Facades created under `bootstrap/app.php` using `create_alias()`,
so you need to create a `config/app.php` file and add your custom aliases under an `aliases` array again, like so:
```php
return [
'aliases' => [
'CustomAliasOne' => Example\Support\Facades\CustomAliasOne::class,
'CustomAliasTwo' => Example\Support\Facades\CustomAliasTwo::class,
//...
]
];
```
After you run `php artisan ide-helper:generate`, it's recommended (but not mandatory) to rename `config/app.php` to something else,
until you have to re-generate the docs or after passing to production environment.
Lumen 5.1+ will read this file for configuration parameters if it is present, and may overlap some configurations if it is completely populated.
## License
The Laravel IDE Helper Generator is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
+3 -3
View File
@@ -28,7 +28,7 @@
"illuminate/console": "^8 || ^9 || ^10",
"illuminate/filesystem": "^8 || ^9 || ^10",
"illuminate/support": "^8 || ^9 || ^10",
"nikic/php-parser": "^4.7",
"nikic/php-parser": "^4.18 || ^5",
"phpdocumentor/type-resolver": "^1.1.0"
},
"require-dev": {
@@ -40,7 +40,7 @@
"orchestra/testbench": "^6 || ^7 || ^8",
"phpunit/phpunit": "^8.5 || ^9",
"spatie/phpunit-snapshot-assertions": "^3 || ^4",
"vimeo/psalm": "^3.12"
"vimeo/psalm": "^5.4"
},
"suggest": {
"illuminate/events": "Required for automatic helper generation (^6|^7|^8|^9|^10)."
@@ -65,7 +65,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "2.12-dev"
"dev-master": "2.14-dev"
},
"laravel": {
"providers": [
+4 -5
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="3.15@de6e7f324f44dde540ebe7ebd4eb481b97c86f30">
<files psalm-version="5.4.0@62db5d4f6a7ae0a20f7cc5a4952d730272fc0863">
<file src="src/Factories.php">
<UndefinedClass occurrences="2">
<code>Factory</code>
@@ -7,13 +7,12 @@
</UndefinedClass>
</file>
<file src="src/Generator.php">
<UndefinedClass occurrences="7">
<UndefinedClass occurrences="6">
<code>\Auth</code>
<code>\Cache</code>
<code>\Cache</code>
<code>\DB</code>
<code>\Cache</code>
<code>\Cache</code>
<code>\Queue</code>
<code>\SSH</code>
<code>\Storage</code>
</UndefinedClass>
</file>
+3 -2
View File
@@ -20,6 +20,7 @@ use Illuminate\Config\Repository as ConfigRepository;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Support\Facades\Facade;
use ReflectionClass;
use Throwable;
class Alias
{
@@ -301,7 +302,7 @@ class Alias
"\nPlease configure your database connection correctly, or use the sqlite memory driver (-M)." .
" Skipping $facade."
);
} catch (\Exception $e) {
} catch (Throwable $e) {
$this->error('Exception: ' . $e->getMessage() . "\nSkipping $facade.");
}
}
@@ -323,7 +324,7 @@ class Alias
protected function addMagicMethods()
{
foreach ($this->magicMethods as $magic => $real) {
list($className, $name) = explode('::', $real);
[$className, $name] = explode('::', $real);
if ((!class_exists($className) && !interface_exists($className)) || !method_exists($className, $name)) {
continue;
}
+77 -24
View File
@@ -231,6 +231,7 @@ class ModelsCommand extends Command
$output = "<?php
// @formatter:off
// phpcs:ignoreFile
/**
* A helper file for your Eloquent Models
* Copy the phpDocs from this file to the correct Model,
@@ -369,6 +370,10 @@ class ModelsCommand extends Command
$type = 'date';
} elseif (Str::startsWith($type, 'immutable_custom_datetime:')) {
$type = 'immutable_date';
} elseif (Str::startsWith($type, 'immutable_date:')) {
$type = 'immutable_date';
} elseif (Str::startsWith($type, 'immutable_datetime:')) {
$type = 'immutable_datetime';
} elseif (Str::startsWith($type, 'encrypted:')) {
$type = Str::after($type, ':');
}
@@ -437,14 +442,46 @@ class ModelsCommand extends Command
$realType = $this->checkForCastableCasts($realType, $params);
$realType = $this->checkForCustomLaravelCasts($realType);
$realType = $this->getTypeOverride($realType);
$this->properties[$name]['type'] = $this->getTypeInModel($model, $realType);
$realType = $this->getTypeInModel($model, $realType);
$realType = $this->applyNullability($realType, isset($this->nullableColumns[$name]));
if (isset($this->nullableColumns[$name])) {
$this->properties[$name]['type'] .= '|null';
}
$this->properties[$name]['type'] = $realType;
}
}
protected function applyNullability(?string $type, bool $isNullable): ?string
{
if (!$type) {
return null;
}
$nullString = null;
// Find instance of:
// A) start of string or non-word character (like space or pipe) followed by 'null|'
// B) '|null' followed by end of string or non-word character (like space or pipe)
// This will find 'or null' instances at the beginning, middle or end of a type string,
// but will exclude solo/pure null instances and null being part of a type's name (e.g. class 'Benull').
if (preg_match('/(?:(?:^|\W)(null\|))|(\|null(?:$|\W))/', $type, $matches) === 1) {
$nullString = array_pop($matches);
}
// Return the current type string if:
// A) the type can be null and the type contains a null instance
// B) the type can not be null and the type does not contain a null instance
if (!($isNullable xor $nullString)) {
return $type;
}
if ($isNullable) {
$type .= '|null';
} else {
$type = str_replace($nullString, '', $type);
}
return $type;
}
/**
* Returns the override type for the give type.
*
@@ -569,13 +606,27 @@ class ModelsCommand extends Command
*/
public function getPropertiesFromMethods($model)
{
$methods = get_class_methods($model);
if ($methods) {
sort($methods);
foreach ($methods as $method) {
$reflection = new \ReflectionMethod($model, $method);
$reflectionClass = new ReflectionClass($model);
$reflections = $reflectionClass->getMethods();
if ($reflections) {
// Filter out private methods because they can't be used to generate magic properties and HasAttributes'
// methods that resemble mutators but aren't.
$reflections = array_filter($reflections, function (\ReflectionMethod $methodReflection) {
return !$methodReflection->isPrivate() && !(
in_array(
\Illuminate\Database\Eloquent\Concerns\HasAttributes::class,
$methodReflection->getDeclaringClass()->getTraitNames()
) && (
$methodReflection->getName() === 'setClassCastableAttribute' ||
$methodReflection->getName() === 'setEnumCastableAttribute'
)
);
});
sort($reflections);
foreach ($reflections as $reflection) {
$type = $this->getReturnTypeFromReflection($reflection);
$isAttribute = is_a($type, '\Illuminate\Database\Eloquent\Casts\Attribute', true);
$method = $reflection->getName();
if (
Str::startsWith($method, 'get') && Str::endsWith(
$method,
@@ -592,16 +643,15 @@ class ModelsCommand extends Command
}
} elseif ($isAttribute) {
$name = Str::snake($method);
$types = $this->getAttributeReturnType($model, $method);
$types = $this->getAttributeReturnType($model, $reflection);
$comment = $this->getCommentFromDocBlock($reflection);
if ($types->has('get')) {
$type = $this->getTypeInModel($model, $types['get']);
$comment = $this->getCommentFromDocBlock($reflection);
$this->setProperty($name, $type, true, null, $comment);
}
if ($types->has('set')) {
$comment = $this->getCommentFromDocBlock($reflection);
$this->setProperty($name, null, null, true, $comment);
}
} elseif (
@@ -677,8 +727,7 @@ class ModelsCommand extends Command
$search = '$this->' . $relation . '(';
if (stripos($code, $search) || ltrim($impl, '\\') === ltrim((string)$type, '\\')) {
//Resolve the relation's model to a Relation object.
$methodReflection = new \ReflectionMethod($model, $method);
if ($methodReflection->getNumberOfParameters()) {
if ($reflection->getNumberOfParameters()) {
continue;
}
@@ -686,11 +735,12 @@ class ModelsCommand extends Command
// Adding constraints requires reading model properties which
// can cause errors. Since we don't need constraints we can
// disable them when we fetch the relation to avoid errors.
$relationObj = Relation::noConstraints(function () use ($model, $method) {
$relationObj = Relation::noConstraints(function () use ($model, $reflection) {
try {
return $model->$method();
$methodName = $reflection->getName();
return $model->$methodName();
} catch (Throwable $e) {
$this->warn(sprintf('Error resolving relation model of %s:%s() : %s', get_class($model), $method, $e->getMessage()));
$this->warn(sprintf('Error resolving relation model of %s:%s() : %s', get_class($model), $reflection->getName(), $e->getMessage()));
return null;
}
@@ -1123,10 +1173,13 @@ class ModelsCommand extends Command
return $this->laravel['config']->get('ide-helper.model_camel_case_properties', false);
}
protected function getAttributeReturnType(Model $model, string $method): Collection
protected function getAttributeReturnType(Model $model, \ReflectionMethod $reflectionMethod): Collection
{
// Private/protected ReflectionMethods require setAccessible prior to PHP 8.1
$reflectionMethod->setAccessible(true);
/** @var Attribute $attribute */
$attribute = $model->{$method}();
$attribute = $reflectionMethod->invoke($model);
return collect([
'get' => $attribute->get ? optional(new \ReflectionFunction($attribute->get))->getReturnType() : null,
@@ -1135,7 +1188,7 @@ class ModelsCommand extends Command
->filter()
->map(function ($type) {
if ($type instanceof \ReflectionUnionType) {
$types =collect($type->getTypes())
$types = collect($type->getTypes())
/** @var ReflectionType $reflectionType */
->map(function ($reflectionType) {
return collect($this->extractReflectionTypes($reflectionType));
@@ -1223,7 +1276,7 @@ class ModelsCommand extends Command
$type = implode('|', $types);
if ($returnType->allowsNull()) {
$type .='|null';
$type .= '|null';
}
return $type;
@@ -1465,10 +1518,10 @@ class ModelsCommand extends Command
$type = implode('|', $types);
if ($paramType->allowsNull()) {
if (count($types)==1) {
if (count($types) == 1) {
$type = '?' . $type;
} else {
$type .='|null';
$type .= '|null';
}
}
@@ -1545,7 +1598,7 @@ class ModelsCommand extends Command
} else {
$types = [];
foreach ($reflection_type->getTypes() as $named_type) {
if ($named_type->getName()==='null') {
if ($named_type->getName() === 'null') {
continue;
}
-9
View File
@@ -127,15 +127,6 @@ class Generator
} catch (\Exception $e) {
}
try {
if (class_exists('SSH') && is_a('SSH', '\Illuminate\Support\Facades\SSH', true)) {
$class = get_class(\SSH::connection());
$this->extra['SSH'] = [$class];
$this->interfaces['\Illuminate\Remote\ConnectionInterface'] = $class;
}
} catch (\Exception $e) {
}
try {
if (class_exists('Storage') && is_a('Storage', '\Illuminate\Support\Facades\Storage', true)) {
$class = get_class(\Storage::disk());
+1 -1
View File
@@ -64,7 +64,7 @@ class UsesResolver
'\\'
);
$parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7);
$parser = (new ParserFactory())->createForHostVersion();
$namespaceData = null;
foreach ($parser->parse($code) as $node) {
@@ -0,0 +1,43 @@
<?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',
];
}
@@ -0,0 +1,28 @@
<?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
{
/**
* The generated snapshot is wrong until
* https://github.com/barryvdh/laravel-ide-helper/issues/1505 is fixed
*/
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();
}
}
@@ -0,0 +1,97 @@
<?php
declare(strict_types=1);
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\ArrayCastsWithComment\Models;
use Illuminate\Database\Eloquent\Model;
/**
* Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\ArrayCastsWithComment\Models\ArrayCastsWithComment
*
* @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 array $cast_to_array
* @property array $cast_to_json
* @property \Illuminate\Support\Collection $cast_to_collection
* @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|ArrayCastsWithComment newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment query()
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToArray($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToBool($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToBoolean($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToCollection($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToCustomDatetime($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToDate($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToDateSerialization($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToDatetime($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToDatetimeSerialization($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToDecimal($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToDouble($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToEncrypted($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToEncryptedArray($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToEncryptedCollection($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToEncryptedJson($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToEncryptedObject($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToFloat($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToImmutableCustomDatetime($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToImmutableDate($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToImmutableDateSerialization($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToImmutableDatetime($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToImmutableDatetimeSerialization($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToInt($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToInteger($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToJson($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToObject($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToReal($value)
* @method static \Illuminate\Database\Eloquent\Builder|ArrayCastsWithComment whereCastToString($value)
* @method static \Illuminate\Database\Eloquent\Builder|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',
];
}
@@ -9,7 +9,7 @@ use Illuminate\Database\Eloquent\Model;
class Simple extends Model
{
public function name(): Attribute
protected function name(): Attribute
{
return new Attribute(
function (?string $name): ?string {
@@ -29,7 +29,7 @@ class Simple extends Model
*
* @return \Illuminate\Database\Eloquent\Casts\Attribute
*/
public function notAnAttribute()
protected function notAnAttribute()
{
return new Attribute(
function (?string $value): ?string {
@@ -20,7 +20,7 @@ use Illuminate\Database\Eloquent\Model;
*/
class Simple extends Model
{
public function name(): Attribute
protected function name(): Attribute
{
return new Attribute(
function (?string $name): ?string {
@@ -40,7 +40,7 @@ class Simple extends Model
*
* @return \Illuminate\Database\Eloquent\Casts\Attribute
*/
public function notAnAttribute()
protected function notAnAttribute()
{
return new Attribute(
function (?string $value): ?string {
@@ -1,6 +1,7 @@
<?php
// @formatter:off
// phpcs:ignoreFile
/**
* A helper file for your Eloquent Models
* Copy the phpDocs from this file to the correct Model,
@@ -1,6 +1,7 @@
<?php
// @formatter:off
// phpcs:ignoreFile
/**
* A helper file for your Eloquent Models
* Copy the phpDocs from this file to the correct Model,
@@ -1,6 +1,7 @@
<?php
// @formatter:off
// phpcs:ignoreFile
/**
* A helper file for your Eloquent Models
* Copy the phpDocs from this file to the correct Model,
@@ -17,6 +17,7 @@ class Post extends Model
<?php
// @formatter:off
// phpcs:ignoreFile
/**
* A helper file for your Eloquent Models
* Copy the phpDocs from this file to the correct Model,
@@ -103,4 +103,8 @@ class Simple extends Model
public function getAttributeReturnsVoidAttribute(): void
{
}
private function getInvalidAccessModifierAttribute()
{
}
}
@@ -133,4 +133,8 @@ class Simple extends Model
public function getAttributeReturnsVoidAttribute(): void
{
}
private function getInvalidAccessModifierAttribute()
{
}
}
@@ -1,6 +1,7 @@
<?php
// @formatter:off
// phpcs:ignoreFile
/**
* A helper file for your Eloquent Models
* Copy the phpDocs from this file to the correct Model,
@@ -31,6 +31,7 @@ class CustomCast extends Model
'casted_property_with_return_primitive' => CustomCasterWithPrimitiveReturn::class,
'casted_property_with_return_primitive_docblock' => CustomCasterWithPrimitiveDocblockReturn::class,
'casted_property_with_return_nullable_primitive' => CustomCasterWithNullablePrimitiveReturn::class,
'casted_property_with_return_nullable_primitive_and_nullable_column' => CustomCasterWithNullablePrimitiveReturn::class,
'casted_property_without_return' => CustomCasterWithoutReturnType::class,
'casted_property_with_param' => CustomCasterWithParam::class . ':param',
'casted_property_with_static_return_docblock' => SelfCastingCasterWithStaticDocblockReturn::class,
@@ -29,8 +29,9 @@ use Illuminate\Database\Eloquent\Model;
* @property \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CastedProperty $casted_property_with_return_docblock
* @property \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CastedProperty $casted_property_with_return_docblock_fqn
* @property array $casted_property_with_return_primitive
* @property array|null $casted_property_with_return_primitive_docblock
* @property array|null $casted_property_with_return_nullable_primitive
* @property array $casted_property_with_return_primitive_docblock
* @property array $casted_property_with_return_nullable_primitive
* @property array|null $casted_property_with_return_nullable_primitive_and_nullable_column
* @property $casted_property_without_return
* @property \Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\LaravelCustomCasts\Casts\CastedProperty $casted_property_with_param
* @property SelfCastingCasterWithStaticDocblockReturn $casted_property_with_static_return_docblock
@@ -50,6 +51,7 @@ use Illuminate\Database\Eloquent\Model;
* @method static \Illuminate\Database\Eloquent\Builder|CustomCast whereCastedPropertyWithReturnDocblock($value)
* @method static \Illuminate\Database\Eloquent\Builder|CustomCast whereCastedPropertyWithReturnDocblockFqn($value)
* @method static \Illuminate\Database\Eloquent\Builder|CustomCast whereCastedPropertyWithReturnNullablePrimitive($value)
* @method static \Illuminate\Database\Eloquent\Builder|CustomCast whereCastedPropertyWithReturnNullablePrimitiveAndNullableColumn($value)
* @method static \Illuminate\Database\Eloquent\Builder|CustomCast whereCastedPropertyWithReturnPrimitive($value)
* @method static \Illuminate\Database\Eloquent\Builder|CustomCast whereCastedPropertyWithReturnPrimitiveDocblock($value)
* @method static \Illuminate\Database\Eloquent\Builder|CustomCast whereCastedPropertyWithReturnType($value)
@@ -70,6 +72,7 @@ class CustomCast extends Model
'casted_property_with_return_primitive' => CustomCasterWithPrimitiveReturn::class,
'casted_property_with_return_primitive_docblock' => CustomCasterWithPrimitiveDocblockReturn::class,
'casted_property_with_return_nullable_primitive' => CustomCasterWithNullablePrimitiveReturn::class,
'casted_property_with_return_nullable_primitive_and_nullable_column' => CustomCasterWithNullablePrimitiveReturn::class,
'casted_property_without_return' => CustomCasterWithoutReturnType::class,
'casted_property_with_param' => CustomCasterWithParam::class . ':param',
'casted_property_with_static_return_docblock' => SelfCastingCasterWithStaticDocblockReturn::class,
@@ -28,8 +28,10 @@ class SimpleCast extends Model
'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_date_serialization' => 'immutable_date:Y-m-d',
'cast_to_immutable_custom_datetime' => 'immutable_custom_datetime:Y-m-d H:i:s',
'cast_to_immutable_datetime' => 'immutable_datetime',
'cast_to_immutable_datetime_serialization' => 'immutable_datetime:Y-m-d H:i:s',
'cast_to_timestamp' => 'timestamp',
'cast_to_encrypted' => 'encrypted',
'cast_to_encrypted_array' => 'encrypted:array',
@@ -28,8 +28,10 @@ use Illuminate\Database\Eloquent\Model;
* @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_date_serialization
* @property \Carbon\CarbonImmutable $cast_to_immutable_custom_datetime
* @property \Carbon\CarbonImmutable $cast_to_immutable_datetime
* @property \Carbon\CarbonImmutable $cast_to_immutable_datetime_serialization
* @property integer $cast_to_timestamp
* @property mixed $cast_to_encrypted
* @property array $cast_to_encrypted_array
@@ -58,7 +60,9 @@ use Illuminate\Database\Eloquent\Model;
* @method static \Illuminate\Database\Eloquent\Builder|SimpleCast whereCastToFloat($value)
* @method static \Illuminate\Database\Eloquent\Builder|SimpleCast whereCastToImmutableCustomDatetime($value)
* @method static \Illuminate\Database\Eloquent\Builder|SimpleCast whereCastToImmutableDate($value)
* @method static \Illuminate\Database\Eloquent\Builder|SimpleCast whereCastToImmutableDateSerialization($value)
* @method static \Illuminate\Database\Eloquent\Builder|SimpleCast whereCastToImmutableDatetime($value)
* @method static \Illuminate\Database\Eloquent\Builder|SimpleCast whereCastToImmutableDatetimeSerialization($value)
* @method static \Illuminate\Database\Eloquent\Builder|SimpleCast whereCastToInt($value)
* @method static \Illuminate\Database\Eloquent\Builder|SimpleCast whereCastToInteger($value)
* @method static \Illuminate\Database\Eloquent\Builder|SimpleCast whereCastToJson($value)
@@ -90,8 +94,10 @@ class SimpleCast extends Model
'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_date_serialization' => 'immutable_date:Y-m-d',
'cast_to_immutable_custom_datetime' => 'immutable_custom_datetime:Y-m-d H:i:s',
'cast_to_immutable_datetime' => 'immutable_datetime',
'cast_to_immutable_datetime_serialization' => 'immutable_datetime:Y-m-d H:i:s',
'cast_to_timestamp' => 'timestamp',
'cast_to_encrypted' => 'encrypted',
'cast_to_encrypted_array' => 'encrypted:array',
@@ -17,6 +17,7 @@ class CustomCastsTable extends Migration
$table->string('casted_property_with_return_primitive');
$table->string('casted_property_with_return_primitive_docblock');
$table->string('casted_property_with_return_nullable_primitive');
$table->string('casted_property_with_return_nullable_primitive_and_nullable_column')->nullable();
$table->string('casted_property_without_return');
$table->string('casted_property_with_param');
$table->string('casted_property_with_static_return_docblock');
@@ -30,8 +30,10 @@ class SimpleCastsTable extends Migration
$table->string('cast_to_datetime_serialization');
$table->string('cast_to_custom_datetime');
$table->string('cast_to_immutable_date');
$table->string('cast_to_immutable_date_serialization');
$table->string('cast_to_immutable_custom_datetime');
$table->string('cast_to_immutable_datetime');
$table->string('cast_to_immutable_datetime_serialization');
$table->string('cast_to_timestamp');
$table->string('cast_to_encrypted');
$table->string('cast_to_encrypted_array');