From ab51e6b7a78ad7cec07e1dd55bf75a77b75afcb0 Mon Sep 17 00:00:00 2001 From: Marcin Michalski Date: Mon, 6 May 2019 15:55:17 +0200 Subject: [PATCH] Update phpstan to 0.11 (#13) --- CHANGELOG.md | 13 +- README.md | 1 + composer.json | 7 +- composer.lock | 1029 ++++++++++++----- extension.neon | 30 +- phpstan.neon | 11 + ...tionPropertiesClassReflectionExtension.php | 76 ++ .../ComponentPropertyReflection.php | 63 + ...RequestMethodsClassReflectionExtension.php | 8 +- ...uestPropertiesClassReflectionExtension.php | 23 +- ...onsePropertiesClassReflectionExtension.php | 39 + ...UserPropertiesClassReflectionExtension.php | 48 + src/ServiceMap.php | 25 + ...eQueryDynamicMethodReturnTypeExtension.php | 77 ++ src/Type/ActiveQueryObjectType.php | 44 + ...RecordDynamicMethodReturnTypeExtension.php | 38 + ...DynamicStaticMethodReturnTypeExtension.php | 19 +- ...DynamicStaticMethodReturnTypeExtension.php | 84 ++ tests/ServiceMapTest.php | 5 +- tests/Yii/MyActiveRecord.php | 29 + tests/Yii/MyController.php | 53 + tests/assets/yii-config-valid.php | 25 +- 22 files changed, 1417 insertions(+), 330 deletions(-) create mode 100644 src/Reflection/ApplicationPropertiesClassReflectionExtension.php create mode 100644 src/Reflection/ComponentPropertyReflection.php create mode 100644 src/Reflection/ResponsePropertiesClassReflectionExtension.php create mode 100644 src/Reflection/UserPropertiesClassReflectionExtension.php create mode 100644 src/Type/ActiveQueryDynamicMethodReturnTypeExtension.php create mode 100644 src/Type/ActiveQueryObjectType.php create mode 100644 src/Type/ActiveRecordDynamicMethodReturnTypeExtension.php create mode 100644 src/Type/YiiDynamicStaticMethodReturnTypeExtension.php create mode 100644 tests/Yii/MyActiveRecord.php create mode 100644 tests/Yii/MyController.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ee3683..9f25972 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. * **Removed** for now removed features. * **Fixed** for any bug fixes. * **Security** in case of vulnerabilities. - + +## [0.5.0] 2019-05-06 +### Added + * Add support for phpstan 0.11 + * Extension tests (Yii2 is now a dev dependency) + ## [0.4.2] 2018-12-18 ### Fixed * Allow configuration without singletons (#10) @@ -27,15 +32,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [0.4.0] 2018-08-21 ### Added * Add support for phpstan 0.10.3 - + ## [0.3.0] 2018-06-16 ### Added * Add support for phpstan 0.10 - + ## [0.2.0] 2018-03-09 ### Added * Provides correct methods and properties for Yii::$app->request - + ## [0.1.0] 2018-03-07 ### Added * first initial release diff --git a/README.md b/README.md index afca9b5..7f5c24c 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ | PHPStan version | Yii2 extension version | | --------------- | ---------------------- | +| 0.11 | 0.5.x | | 0.10.3 | 0.4.x | | 0.10 | 0.3.0 | | 0.9.2 | 0.2.0 | diff --git a/composer.json b/composer.json index 82639ef..31e5675 100644 --- a/composer.json +++ b/composer.json @@ -12,12 +12,13 @@ "require": { "php": "^7.1", "nikic/php-parser": "^4.1.0", - "phpstan/phpstan": "^0.10.3" + "phpstan/phpstan": "^0.11" }, "require-dev": { "friendsofphp/php-cs-fixer": "^2.13", - "phpstan/phpstan-phpunit": "^0.10", - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^7.0", + "yiisoft/yii2": "^2.0.15", + "phpstan/phpstan-phpunit": "^0.11" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index b9c5e68..454bba5 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "35878478fb4c1c28ac9152ad6c7d3ed4", + "content-hash": "96b37193596021ec6cb838b8711453db", "packages": [ { "name": "composer/xdebug-handler", - "version": "1.3.1", + "version": "1.3.2", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "dc523135366eb68f22268d069ea7749486458562" + "reference": "d17708133b6c276d6e42ef887a877866b909d892" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/dc523135366eb68f22268d069ea7749486458562", - "reference": "dc523135366eb68f22268d069ea7749486458562", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/d17708133b6c276d6e42ef887a877866b909d892", + "reference": "d17708133b6c276d6e42ef887a877866b909d892", "shasum": "" }, "require": { @@ -48,7 +48,7 @@ "Xdebug", "performance" ], - "time": "2018-11-29T10:59:02+00:00" + "time": "2019-01-28T20:25:53+00:00" }, { "name": "jean85/pretty-package-versions", @@ -103,39 +103,36 @@ }, { "name": "nette/bootstrap", - "version": "v2.4.6", + "version": "v3.0.0", "source": { "type": "git", "url": "https://github.com/nette/bootstrap.git", - "reference": "268816e3f1bb7426c3a4ceec2bd38a036b532543" + "reference": "e1075af05c211915e03e0c86542f3ba5433df4a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/bootstrap/zipball/268816e3f1bb7426c3a4ceec2bd38a036b532543", - "reference": "268816e3f1bb7426c3a4ceec2bd38a036b532543", + "url": "https://api.github.com/repos/nette/bootstrap/zipball/e1075af05c211915e03e0c86542f3ba5433df4a3", + "reference": "e1075af05c211915e03e0c86542f3ba5433df4a3", "shasum": "" }, "require": { - "nette/di": "~2.4.7", - "nette/utils": "~2.4", - "php": ">=5.6.0" - }, - "conflict": { - "nette/nette": "<2.2" + "nette/di": "^3.0", + "nette/utils": "^3.0", + "php": ">=7.1" }, "require-dev": { - "latte/latte": "~2.2", - "nette/application": "~2.3", - "nette/caching": "~2.3", - "nette/database": "~2.3", - "nette/forms": "~2.3", - "nette/http": "~2.4.0", - "nette/mail": "~2.3", - "nette/robot-loader": "^2.4.2 || ^3.0", - "nette/safe-stream": "~2.2", - "nette/security": "~2.3", - "nette/tester": "~2.0", - "tracy/tracy": "^2.4.1" + "latte/latte": "^2.2", + "nette/application": "^3.0", + "nette/caching": "^3.0", + "nette/database": "^3.0", + "nette/forms": "^3.0", + "nette/http": "^3.0", + "nette/mail": "^3.0", + "nette/robot-loader": "^3.0", + "nette/safe-stream": "^2.2", + "nette/security": "^3.0", + "nette/tester": "^2.0", + "tracy/tracy": "^2.6" }, "suggest": { "nette/robot-loader": "to use Configurator::createRobotLoader()", @@ -144,7 +141,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -175,46 +172,50 @@ "configurator", "nette" ], - "time": "2018-05-17T12:52:20+00:00" + "time": "2019-03-26T12:59:07+00:00" }, { "name": "nette/di", - "version": "v2.4.14", + "version": "v3.0.0", "source": { "type": "git", "url": "https://github.com/nette/di.git", - "reference": "923da3e2c0aa53162ef455472c0ac7787b096c5a" + "reference": "19d83539245aaacb59470828919182411061841f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/di/zipball/923da3e2c0aa53162ef455472c0ac7787b096c5a", - "reference": "923da3e2c0aa53162ef455472c0ac7787b096c5a", + "url": "https://api.github.com/repos/nette/di/zipball/19d83539245aaacb59470828919182411061841f", + "reference": "19d83539245aaacb59470828919182411061841f", "shasum": "" }, "require": { "ext-tokenizer": "*", - "nette/neon": "^2.3.3 || ~3.0.0", - "nette/php-generator": "^2.6.1 || ~3.0.0", - "nette/utils": "^2.4.3 || ~3.0.0", - "php": ">=5.6.0" + "nette/neon": "^3.0", + "nette/php-generator": "^3.2.2", + "nette/robot-loader": "^3.2", + "nette/schema": "^1.0", + "nette/utils": "^3.0", + "php": ">=7.1" }, "conflict": { - "nette/bootstrap": "<2.4", - "nette/nette": "<2.2" + "nette/bootstrap": "<3.0" }, "require-dev": { - "nette/tester": "^2.0", + "nette/tester": "^2.2", "tracy/tracy": "^2.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "3.0-dev" } }, "autoload": { "classmap": [ "src/" + ], + "files": [ + "src/compatibility.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -244,37 +245,37 @@ "nette", "static" ], - "time": "2018-09-17T15:47:40+00:00" + "time": "2019-04-03T19:35:46+00:00" }, { "name": "nette/finder", - "version": "v2.4.2", + "version": "v2.5.0", "source": { "type": "git", "url": "https://github.com/nette/finder.git", - "reference": "ee951a656cb8ac622e5dd33474a01fd2470505a0" + "reference": "6be1b83ea68ac558aff189d640abe242e0306fe2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/finder/zipball/ee951a656cb8ac622e5dd33474a01fd2470505a0", - "reference": "ee951a656cb8ac622e5dd33474a01fd2470505a0", + "url": "https://api.github.com/repos/nette/finder/zipball/6be1b83ea68ac558aff189d640abe242e0306fe2", + "reference": "6be1b83ea68ac558aff189d640abe242e0306fe2", "shasum": "" }, "require": { - "nette/utils": "~2.4", - "php": ">=5.6.0" + "nette/utils": "^2.4 || ~3.0.0", + "php": ">=7.1" }, "conflict": { "nette/nette": "<2.2" }, "require-dev": { - "nette/tester": "~2.0", + "nette/tester": "^2.0", "tracy/tracy": "^2.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -306,35 +307,35 @@ "iterator", "nette" ], - "time": "2018-06-28T11:49:23+00:00" + "time": "2019-02-28T18:13:25+00:00" }, { "name": "nette/neon", - "version": "v2.4.3", + "version": "v3.0.0", "source": { "type": "git", "url": "https://github.com/nette/neon.git", - "reference": "5e72b1dd3e2d34f0863c5561139a19df6a1ef398" + "reference": "cbff32059cbdd8720deccf9e9eace6ee516f02eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/neon/zipball/5e72b1dd3e2d34f0863c5561139a19df6a1ef398", - "reference": "5e72b1dd3e2d34f0863c5561139a19df6a1ef398", + "url": "https://api.github.com/repos/nette/neon/zipball/cbff32059cbdd8720deccf9e9eace6ee516f02eb", + "reference": "cbff32059cbdd8720deccf9e9eace6ee516f02eb", "shasum": "" }, "require": { "ext-iconv": "*", "ext-json": "*", - "php": ">=5.6.0" + "php": ">=7.0" }, "require-dev": { - "nette/tester": "~2.0", + "nette/tester": "^2.0", "tracy/tracy": "^2.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -367,28 +368,25 @@ "nette", "yaml" ], - "time": "2018-03-21T12:12:21+00:00" + "time": "2019-02-05T21:30:40+00:00" }, { "name": "nette/php-generator", - "version": "v3.0.5", + "version": "v3.2.2", "source": { "type": "git", "url": "https://github.com/nette/php-generator.git", - "reference": "ea90209c2e8a7cd087b2742ca553c047a8df5eff" + "reference": "acff8b136fad84b860a626d133e791f95781f9f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/php-generator/zipball/ea90209c2e8a7cd087b2742ca553c047a8df5eff", - "reference": "ea90209c2e8a7cd087b2742ca553c047a8df5eff", + "url": "https://api.github.com/repos/nette/php-generator/zipball/acff8b136fad84b860a626d133e791f95781f9f5", + "reference": "acff8b136fad84b860a626d133e791f95781f9f5", "shasum": "" }, "require": { "nette/utils": "^2.4.2 || ~3.0.0", - "php": ">=7.0" - }, - "conflict": { - "nette/nette": "<2.2" + "php": ">=7.1" }, "require-dev": { "nette/tester": "^2.0", @@ -397,7 +395,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -421,7 +419,7 @@ "homepage": "https://nette.org/contributors" } ], - "description": "🐘 Nette PHP Generator: generates neat PHP code for you. Supports new PHP 7.2 features.", + "description": "🐘 Nette PHP Generator: generates neat PHP code for you. Supports new PHP 7.3 features.", "homepage": "https://nette.org", "keywords": [ "code", @@ -429,30 +427,27 @@ "php", "scaffolding" ], - "time": "2018-08-09T14:32:27+00:00" + "time": "2019-03-15T03:41:13+00:00" }, { "name": "nette/robot-loader", - "version": "v3.1.0", + "version": "v3.2.0", "source": { "type": "git", "url": "https://github.com/nette/robot-loader.git", - "reference": "fc76c70e740b10f091e502b2e393d0be912f38d4" + "reference": "0712a0e39ae7956d6a94c0ab6ad41aa842544b5c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/robot-loader/zipball/fc76c70e740b10f091e502b2e393d0be912f38d4", - "reference": "fc76c70e740b10f091e502b2e393d0be912f38d4", + "url": "https://api.github.com/repos/nette/robot-loader/zipball/0712a0e39ae7956d6a94c0ab6ad41aa842544b5c", + "reference": "0712a0e39ae7956d6a94c0ab6ad41aa842544b5c", "shasum": "" }, "require": { "ext-tokenizer": "*", - "nette/finder": "^2.3 || ^3.0", - "nette/utils": "^2.4 || ^3.0", - "php": ">=5.6.0" - }, - "conflict": { - "nette/nette": "<2.2" + "nette/finder": "^2.5", + "nette/utils": "^3.0", + "php": ">=7.1" }, "require-dev": { "nette/tester": "^2.0", @@ -461,7 +456,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -485,7 +480,7 @@ "homepage": "https://nette.org/contributors" } ], - "description": "🍀 Nette RobotLoader: high performance and comfortable autoloader that will search and autoload classes within your application.", + "description": "? Nette RobotLoader: high performance and comfortable autoloader that will search and autoload classes within your application.", "homepage": "https://nette.org", "keywords": [ "autoload", @@ -494,27 +489,81 @@ "nette", "trait" ], - "time": "2018-08-13T14:19:06+00:00" + "time": "2019-03-08T21:57:24+00:00" + }, + { + "name": "nette/schema", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/nette/schema.git", + "reference": "6241d8d4da39e825dd6cb5bfbe4242912f4d7e4d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/schema/zipball/6241d8d4da39e825dd6cb5bfbe4242912f4d7e4d", + "reference": "6241d8d4da39e825dd6cb5bfbe4242912f4d7e4d", + "shasum": "" + }, + "require": { + "nette/utils": "^3.0.1", + "php": ">=7.1" + }, + "require-dev": { + "nette/tester": "^2.2", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "📐 Nette Schema: validating data structures against a given Schema.", + "homepage": "https://nette.org", + "keywords": [ + "config", + "nette" + ], + "time": "2019-04-03T15:53:25+00:00" }, { "name": "nette/utils", - "version": "v2.5.3", + "version": "v3.0.1", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "17b9f76f2abd0c943adfb556e56f2165460b15ce" + "reference": "bd961f49b211997202bda1d0fbc410905be370d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/17b9f76f2abd0c943adfb556e56f2165460b15ce", - "reference": "17b9f76f2abd0c943adfb556e56f2165460b15ce", + "url": "https://api.github.com/repos/nette/utils/zipball/bd961f49b211997202bda1d0fbc410905be370d4", + "reference": "bd961f49b211997202bda1d0fbc410905be370d4", "shasum": "" }, "require": { - "php": ">=5.6.0" - }, - "conflict": { - "nette/nette": "<2.2" + "php": ">=7.1" }, "require-dev": { "nette/tester": "~2.0", @@ -523,7 +572,7 @@ "suggest": { "ext-gd": "to use Image", "ext-iconv": "to use Strings::webalize() and toAscii()", - "ext-intl": "for script transliteration in Strings::webalize() and toAscii()", + "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", "ext-json": "to use Nette\\Utils\\Json", "ext-mbstring": "to use Strings::lower() etc...", "ext-xml": "to use Strings::length() etc. when mbstring is not available" @@ -531,15 +580,12 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.5-dev" + "dev-master": "3.0-dev" } }, "autoload": { "classmap": [ "src/" - ], - "files": [ - "src/loader.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -576,20 +622,20 @@ "utility", "validation" ], - "time": "2018-09-18T10:22:16+00:00" + "time": "2019-03-22T01:00:30+00:00" }, { "name": "nikic/php-parser", - "version": "v4.1.0", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "d0230c5c77a7e3cfa69446febf340978540958c0" + "reference": "5221f49a608808c1e4d436df32884cbc1b821ac0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/d0230c5c77a7e3cfa69446febf340978540958c0", - "reference": "d0230c5c77a7e3cfa69446febf340978540958c0", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/5221f49a608808c1e4d436df32884cbc1b821ac0", + "reference": "5221f49a608808c1e4d436df32884cbc1b821ac0", "shasum": "" }, "require": { @@ -605,7 +651,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -627,20 +673,20 @@ "parser", "php" ], - "time": "2018-10-10T09:24:14+00:00" + "time": "2019-02-16T20:54:15+00:00" }, { "name": "ocramius/package-versions", - "version": "1.3.0", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/Ocramius/PackageVersions.git", - "reference": "4489d5002c49d55576fa0ba786f42dbb009be46f" + "reference": "a4d4b60d0e60da2487bd21a2c6ac089f85570dbb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/4489d5002c49d55576fa0ba786f42dbb009be46f", - "reference": "4489d5002c49d55576fa0ba786f42dbb009be46f", + "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/a4d4b60d0e60da2487bd21a2c6ac089f85570dbb", + "reference": "a4d4b60d0e60da2487bd21a2c6ac089f85570dbb", "shasum": "" }, "require": { @@ -649,6 +695,7 @@ }, "require-dev": { "composer/composer": "^1.6.3", + "doctrine/coding-standard": "^5.0.1", "ext-zip": "*", "infection/infection": "^0.7.1", "phpunit/phpunit": "^7.0.0" @@ -676,32 +723,33 @@ } ], "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", - "time": "2018-02-05T13:05:30+00:00" + "time": "2019-02-21T12:16:21+00:00" }, { "name": "phpstan/phpdoc-parser", - "version": "0.3", + "version": "0.3.3", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "ed3223362174b8067729930439e139794e9e514a" + "reference": "472d3161d289f652713a5e353532fa4592663a57" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/ed3223362174b8067729930439e139794e9e514a", - "reference": "ed3223362174b8067729930439e139794e9e514a", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/472d3161d289f652713a5e353532fa4592663a57", + "reference": "472d3161d289f652713a5e353532fa4592663a57", "shasum": "" }, "require": { "php": "~7.1" }, "require-dev": { - "consistence/coding-standard": "^2.0.0", + "consistence/coding-standard": "^3.5", "jakub-onderka/php-parallel-lint": "^0.9.2", "phing/phing": "^2.16.0", - "phpstan/phpstan": "^0.10@dev", + "phpstan/phpstan": "^0.10", "phpunit/phpunit": "^6.3", - "slevomat/coding-standard": "^3.3.0", + "slevomat/coding-standard": "^4.7.2", + "squizlabs/php_codesniffer": "^3.3.2", "symfony/process": "^3.4 || ^4.0" }, "type": "library", @@ -722,20 +770,20 @@ "MIT" ], "description": "PHPDoc parser with support for nullable, intersection and generic types", - "time": "2018-06-20T17:48:01+00:00" + "time": "2019-04-23T20:26:19+00:00" }, { "name": "phpstan/phpstan", - "version": "0.10.6", + "version": "0.11.5", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "f0252a5ab6b4a293fb25f218d9c64386f272280f" + "reference": "24ce5a566a798b81343138ed5d41d6877554cf9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/f0252a5ab6b4a293fb25f218d9c64386f272280f", - "reference": "f0252a5ab6b4a293fb25f218d9c64386f272280f", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/24ce5a566a798b81343138ed5d41d6877554cf9a", + "reference": "24ce5a566a798b81343138ed5d41d6877554cf9a", "shasum": "" }, "require": { @@ -758,17 +806,17 @@ "brianium/paratest": "^2.0", "consistence/coding-standard": "^3.5", "dealerdirect/phpcodesniffer-composer-installer": "^0.4.4", - "ext-gd": "*", "ext-intl": "*", "ext-mysqli": "*", + "ext-soap": "*", "ext-zip": "*", "jakub-onderka/php-parallel-lint": "^1.0", - "localheinz/composer-normalize": "~0.9.0", + "localheinz/composer-normalize": "^1.1.0", "phing/phing": "^2.16.0", - "phpstan/phpstan-deprecation-rules": "^0.10.2", - "phpstan/phpstan-php-parser": "^0.10", - "phpstan/phpstan-phpunit": "^0.10", - "phpstan/phpstan-strict-rules": "^0.10", + "phpstan/phpstan-deprecation-rules": "^0.11", + "phpstan/phpstan-php-parser": "^0.11", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-strict-rules": "^0.11", "phpunit/phpunit": "^7.0", "slevomat/coding-standard": "^4.7.2", "squizlabs/php_codesniffer": "^3.3.2" @@ -779,7 +827,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "0.10-dev" + "dev-master": "0.11-dev" } }, "autoload": { @@ -795,7 +843,7 @@ "MIT" ], "description": "PHPStan - PHP Static Analysis Tool", - "time": "2018-12-04T07:28:04+00:00" + "time": "2019-03-25T16:40:09+00:00" }, { "name": "psr/log", @@ -846,16 +894,16 @@ }, { "name": "symfony/console", - "version": "v4.2.1", + "version": "v4.2.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "4dff24e5d01e713818805c1862d2e3f901ee7dd0" + "reference": "e2840bb38bddad7a0feaf85931e38fdcffdb2f81" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/4dff24e5d01e713818805c1862d2e3f901ee7dd0", - "reference": "4dff24e5d01e713818805c1862d2e3f901ee7dd0", + "url": "https://api.github.com/repos/symfony/console/zipball/e2840bb38bddad7a0feaf85931e38fdcffdb2f81", + "reference": "e2840bb38bddad7a0feaf85931e38fdcffdb2f81", "shasum": "" }, "require": { @@ -867,6 +915,9 @@ "symfony/dependency-injection": "<3.4", "symfony/process": "<3.3" }, + "provide": { + "psr/log-implementation": "1.0" + }, "require-dev": { "psr/log": "~1.0", "symfony/config": "~3.4|~4.0", @@ -876,7 +927,7 @@ "symfony/process": "~3.4|~4.0" }, "suggest": { - "psr/log-implementation": "For using the console logger", + "psr/log": "For using the console logger", "symfony/event-dispatcher": "", "symfony/lock": "", "symfony/process": "" @@ -911,7 +962,7 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2018-11-27T07:40:44+00:00" + "time": "2019-04-08T14:23:48+00:00" }, { "name": "symfony/contracts", @@ -983,16 +1034,16 @@ }, { "name": "symfony/finder", - "version": "v4.2.1", + "version": "v4.2.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "e53d477d7b5c4982d0e1bfd2298dbee63d01441d" + "reference": "e45135658bd6c14b61850bf131c4f09a55133f69" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/e53d477d7b5c4982d0e1bfd2298dbee63d01441d", - "reference": "e53d477d7b5c4982d0e1bfd2298dbee63d01441d", + "url": "https://api.github.com/repos/symfony/finder/zipball/e45135658bd6c14b61850bf131c4f09a55133f69", + "reference": "e45135658bd6c14b61850bf131c4f09a55133f69", "shasum": "" }, "require": { @@ -1028,20 +1079,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2018-11-11T19:52:12+00:00" + "time": "2019-04-06T13:51:08+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.10.0", + "version": "v1.11.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "c79c051f5b3a46be09205c73b80b346e4153e494" + "reference": "fe5e94c604826c35a32fa832f35bd036b6799609" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494", - "reference": "c79c051f5b3a46be09205c73b80b346e4153e494", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609", + "reference": "fe5e94c604826c35a32fa832f35bd036b6799609", "shasum": "" }, "require": { @@ -1053,7 +1104,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.9-dev" + "dev-master": "1.11-dev" } }, "autoload": { @@ -1087,22 +1138,238 @@ "portable", "shim" ], - "time": "2018-09-21T13:07:52+00:00" + "time": "2019-02-06T07:57:58+00:00" } ], "packages-dev": [ + { + "name": "bower-asset/inputmask", + "version": "3.3.11", + "source": { + "type": "git", + "url": "https://github.com/RobinHerbots/Inputmask.git", + "reference": "5e670ad62f50c738388d4dcec78d2888505ad77b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/RobinHerbots/Inputmask/zipball/5e670ad62f50c738388d4dcec78d2888505ad77b", + "reference": "5e670ad62f50c738388d4dcec78d2888505ad77b", + "shasum": "" + }, + "require": { + "bower-asset/jquery": ">=1.7" + }, + "type": "bower-asset-library", + "extra": { + "bower-asset-main": [ + "./dist/inputmask/inputmask.js", + "./dist/inputmask/inputmask.extensions.js", + "./dist/inputmask/inputmask.date.extensions.js", + "./dist/inputmask/inputmask.numeric.extensions.js", + "./dist/inputmask/inputmask.phone.extensions.js", + "./dist/inputmask/jquery.inputmask.js", + "./dist/inputmask/global/document.js", + "./dist/inputmask/global/window.js", + "./dist/inputmask/phone-codes/phone.js", + "./dist/inputmask/phone-codes/phone-be.js", + "./dist/inputmask/phone-codes/phone-nl.js", + "./dist/inputmask/phone-codes/phone-ru.js", + "./dist/inputmask/phone-codes/phone-uk.js", + "./dist/inputmask/dependencyLibs/inputmask.dependencyLib.jqlite.js", + "./dist/inputmask/dependencyLibs/inputmask.dependencyLib.jquery.js", + "./dist/inputmask/dependencyLibs/inputmask.dependencyLib.js", + "./dist/inputmask/bindings/inputmask.binding.js" + ], + "bower-asset-ignore": [ + "**/*", + "!dist/*", + "!dist/inputmask/*", + "!dist/min/*", + "!dist/min/inputmask/*" + ] + }, + "license": [ + "http://opensource.org/licenses/mit-license.php" + ], + "description": "Inputmask is a javascript library which creates an input mask. Inputmask can run against vanilla javascript, jQuery and jqlite.", + "keywords": [ + "form", + "input", + "inputmask", + "jquery", + "mask", + "plugins" + ], + "time": "2017-11-21T11:46:23+00:00" + }, + { + "name": "bower-asset/jquery", + "version": "3.3.1", + "source": { + "type": "git", + "url": "https://github.com/jquery/jquery-dist.git", + "reference": "9e8ec3d10fad04748176144f108d7355662ae75e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jquery/jquery-dist/zipball/9e8ec3d10fad04748176144f108d7355662ae75e", + "reference": "9e8ec3d10fad04748176144f108d7355662ae75e", + "shasum": "" + }, + "type": "bower-asset-library", + "extra": { + "bower-asset-main": "dist/jquery.js", + "bower-asset-ignore": [ + "package.json" + ] + }, + "license": [ + "MIT" + ], + "keywords": [ + "browser", + "javascript", + "jquery", + "library" + ], + "time": "2018-01-20T17:26:57+00:00" + }, + { + "name": "bower-asset/punycode", + "version": "v1.3.2", + "source": { + "type": "git", + "url": "https://github.com/bestiejs/punycode.js.git", + "reference": "38c8d3131a82567bfef18da09f7f4db68c84f8a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bestiejs/punycode.js/zipball/38c8d3131a82567bfef18da09f7f4db68c84f8a3", + "reference": "38c8d3131a82567bfef18da09f7f4db68c84f8a3", + "shasum": "" + }, + "type": "bower-asset-library", + "extra": { + "bower-asset-main": "punycode.js", + "bower-asset-ignore": [ + "coverage", + "tests", + ".*", + "component.json", + "Gruntfile.js", + "node_modules", + "package.json" + ] + }, + "time": "2014-10-22T12:02:42+00:00" + }, + { + "name": "bower-asset/yii2-pjax", + "version": "2.0.7.1", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/jquery-pjax.git", + "reference": "aef7b953107264f00234902a3880eb50dafc48be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/jquery-pjax/zipball/aef7b953107264f00234902a3880eb50dafc48be", + "reference": "aef7b953107264f00234902a3880eb50dafc48be", + "shasum": "" + }, + "require": { + "bower-asset/jquery": ">=1.8" + }, + "type": "bower-asset-library", + "extra": { + "bower-asset-main": "./jquery.pjax.js", + "bower-asset-ignore": [ + ".travis.yml", + "Gemfile", + "Gemfile.lock", + "CONTRIBUTING.md", + "vendor/", + "script/", + "test/" + ] + }, + "license": [ + "MIT" + ], + "time": "2017-10-12T10:11:14+00:00" + }, + { + "name": "cebe/markdown", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/cebe/markdown.git", + "reference": "9bac5e971dd391e2802dca5400bbeacbaea9eb86" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cebe/markdown/zipball/9bac5e971dd391e2802dca5400bbeacbaea9eb86", + "reference": "9bac5e971dd391e2802dca5400bbeacbaea9eb86", + "shasum": "" + }, + "require": { + "lib-pcre": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "cebe/indent": "*", + "facebook/xhprof": "*@dev", + "phpunit/phpunit": "4.1.*" + }, + "bin": [ + "bin/markdown" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "cebe\\markdown\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Carsten Brandt", + "email": "mail@cebe.cc", + "homepage": "http://cebe.cc/", + "role": "Creator" + } + ], + "description": "A super fast, highly extensible markdown parser for PHP", + "homepage": "https://github.com/cebe/markdown#readme", + "keywords": [ + "extensible", + "fast", + "gfm", + "markdown", + "markdown-extra" + ], + "time": "2018-03-26T11:24:36+00:00" + }, { "name": "composer/semver", - "version": "1.4.2", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573" + "reference": "46d9139568ccb8d9e7cdd4539cab7347568a5e2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573", - "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573", + "url": "https://api.github.com/repos/composer/semver/zipball/46d9139568ccb8d9e7cdd4539cab7347568a5e2e", + "reference": "46d9139568ccb8d9e7cdd4539cab7347568a5e2e", "shasum": "" }, "require": { @@ -1151,20 +1418,20 @@ "validation", "versioning" ], - "time": "2016-08-30T16:08:34+00:00" + "time": "2019-03-19T17:25:45+00:00" }, { "name": "doctrine/annotations", - "version": "v1.6.0", + "version": "v1.6.1", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5" + "reference": "53120e0eb10355388d6ccbe462f1fea34ddadb24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", - "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/53120e0eb10355388d6ccbe462f1fea34ddadb24", + "reference": "53120e0eb10355388d6ccbe462f1fea34ddadb24", "shasum": "" }, "require": { @@ -1219,31 +1486,33 @@ "docblock", "parser" ], - "time": "2017-12-06T07:11:42+00:00" + "time": "2019-03-25T19:12:02+00:00" }, { "name": "doctrine/instantiator", - "version": "1.1.0", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" + "reference": "a2c590166b2133a4633738648b6b064edae0814a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", - "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/a2c590166b2133a4633738648b6b064edae0814a", + "reference": "a2c590166b2133a4633738648b6b064edae0814a", "shasum": "" }, "require": { "php": "^7.1" }, "require-dev": { - "athletic/athletic": "~0.1.8", + "doctrine/coding-standard": "^6.0", "ext-pdo": "*", "ext-phar": "*", - "phpunit/phpunit": "^6.2.3", - "squizlabs/php_codesniffer": "^3.0.2" + "phpbench/phpbench": "^0.13", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-shim": "^0.11", + "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { @@ -1268,12 +1537,12 @@ } ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", "keywords": [ "constructor", "instantiate" ], - "time": "2017-07-22T11:58:36+00:00" + "time": "2019-03-17T17:37:11+00:00" }, { "name": "doctrine/lexer", @@ -1329,18 +1598,65 @@ ], "time": "2014-09-09T13:34:57+00:00" }, + { + "name": "ezyang/htmlpurifier", + "version": "v4.10.0", + "source": { + "type": "git", + "url": "https://github.com/ezyang/htmlpurifier.git", + "reference": "d85d39da4576a6934b72480be6978fb10c860021" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/d85d39da4576a6934b72480be6978fb10c860021", + "reference": "d85d39da4576a6934b72480be6978fb10c860021", + "shasum": "" + }, + "require": { + "php": ">=5.2" + }, + "require-dev": { + "simpletest/simpletest": "^1.1" + }, + "type": "library", + "autoload": { + "psr-0": { + "HTMLPurifier": "library/" + }, + "files": [ + "library/HTMLPurifier.composer.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL" + ], + "authors": [ + { + "name": "Edward Z. Yang", + "email": "admin@htmlpurifier.org", + "homepage": "http://ezyang.com" + } + ], + "description": "Standards compliant HTML filter written in PHP", + "homepage": "http://htmlpurifier.org/", + "keywords": [ + "html" + ], + "time": "2018-02-23T01:58:20+00:00" + }, { "name": "friendsofphp/php-cs-fixer", - "version": "v2.13.1", + "version": "v2.15.0", "source": { "type": "git", "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "54814c62d5beef3ba55297b9b3186ed8b8a1b161" + "reference": "adfab51ae979ee8b0fcbc55aa231ec2786cb1f91" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/54814c62d5beef3ba55297b9b3186ed8b8a1b161", - "reference": "54814c62d5beef3ba55297b9b3186ed8b8a1b161", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/adfab51ae979ee8b0fcbc55aa231ec2786cb1f91", + "reference": "adfab51ae979ee8b0fcbc55aa231ec2786cb1f91", "shasum": "" }, "require": { @@ -1349,7 +1665,7 @@ "doctrine/annotations": "^1.2", "ext-json": "*", "ext-tokenizer": "*", - "php": "^5.6 || >=7.0 <7.3", + "php": "^5.6 || ^7.0", "php-cs-fixer/diff": "^1.3", "symfony/console": "^3.4.17 || ^4.1.6", "symfony/event-dispatcher": "^3.0 || ^4.0", @@ -1361,20 +1677,17 @@ "symfony/process": "^3.0 || ^4.0", "symfony/stopwatch": "^3.0 || ^4.0" }, - "conflict": { - "hhvm": "*" - }, "require-dev": { "johnkary/phpunit-speedtrap": "^1.1 || ^2.0 || ^3.0", "justinrainbow/json-schema": "^5.0", - "keradus/cli-executor": "^1.1", + "keradus/cli-executor": "^1.2", "mikey179/vfsstream": "^1.6", "php-coveralls/php-coveralls": "^2.1", "php-cs-fixer/accessible-object": "^1.0", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.0.1", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.0.1", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.1", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.1", "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1", - "phpunitgoodpractices/traits": "^1.5.1", + "phpunitgoodpractices/traits": "^1.8", "symfony/phpunit-bridge": "^4.0" }, "suggest": { @@ -1387,6 +1700,11 @@ "php-cs-fixer" ], "type": "application", + "extra": { + "branch-alias": { + "dev-master": "2.15-dev" + } + }, "autoload": { "psr-4": { "PhpCsFixer\\": "src/" @@ -1418,20 +1736,20 @@ } ], "description": "A tool to automatically fix PHP code style", - "time": "2018-10-21T00:32:10+00:00" + "time": "2019-05-06T07:13:51+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.8.1", + "version": "1.9.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8" + "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", - "reference": "3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", + "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", "shasum": "" }, "require": { @@ -1466,7 +1784,7 @@ "object", "object graph" ], - "time": "2018-06-11T23:09:50+00:00" + "time": "2019-04-07T13:18:21+00:00" }, { "name": "paragonie/random_compat", @@ -1722,16 +2040,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "4.3.0", + "version": "4.3.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08" + "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", + "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", "shasum": "" }, "require": { @@ -1769,7 +2087,7 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2017-11-30T07:14:17+00:00" + "time": "2019-04-30T17:48:53+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -1883,22 +2201,23 @@ }, { "name": "phpstan/phpstan-phpunit", - "version": "0.10", + "version": "0.11", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "6feecc7faae187daa6be44140cd0f1ba210e6aa0" + "reference": "70c22d44b96a21a4952fc13021a5a63cc83f5c81" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/6feecc7faae187daa6be44140cd0f1ba210e6aa0", - "reference": "6feecc7faae187daa6be44140cd0f1ba210e6aa0", + "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/70c22d44b96a21a4952fc13021a5a63cc83f5c81", + "reference": "70c22d44b96a21a4952fc13021a5a63cc83f5c81", "shasum": "" }, "require": { "nikic/php-parser": "^4.0", "php": "~7.1", - "phpstan/phpstan": "^0.10" + "phpstan/phpdoc-parser": "^0.3", + "phpstan/phpstan": "^0.11" }, "conflict": { "phpunit/phpunit": "<7.0" @@ -1908,7 +2227,7 @@ "dealerdirect/phpcodesniffer-composer-installer": "^0.4.4", "jakub-onderka/php-parallel-lint": "^1.0", "phing/phing": "^2.16.0", - "phpstan/phpstan-strict-rules": "^0.10", + "phpstan/phpstan-strict-rules": "^0.11", "phpunit/phpunit": "^7.0", "satooshi/php-coveralls": "^1.0", "slevomat/coding-standard": "^4.5.2" @@ -1916,7 +2235,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "0.10-dev" + "dev-master": "0.11-dev" } }, "autoload": { @@ -1929,7 +2248,7 @@ "MIT" ], "description": "PHPUnit extensions and rules for PHPStan", - "time": "2018-06-22T18:12:17+00:00" + "time": "2018-12-22T14:05:04+00:00" }, { "name": "phpunit/php-code-coverage", @@ -2087,16 +2406,16 @@ }, { "name": "phpunit/php-timer", - "version": "2.0.0", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f" + "reference": "8b389aebe1b8b0578430bda0c7c95a829608e059" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b8454ea6958c3dee38453d3bd571e023108c91f", - "reference": "8b8454ea6958c3dee38453d3bd571e023108c91f", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b389aebe1b8b0578430bda0c7c95a829608e059", + "reference": "8b389aebe1b8b0578430bda0c7c95a829608e059", "shasum": "" }, "require": { @@ -2108,7 +2427,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "2.1-dev" } }, "autoload": { @@ -2132,7 +2451,7 @@ "keywords": [ "timer" ], - "time": "2018-02-01T13:07:23+00:00" + "time": "2019-02-20T10:12:59+00:00" }, { "name": "phpunit/php-token-stream", @@ -2185,16 +2504,16 @@ }, { "name": "phpunit/phpunit", - "version": "7.5.1", + "version": "7.5.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "c23d78776ad415d5506e0679723cb461d71f488f" + "reference": "134669cf0eeac3f79bc7f0c793efbc158bffc160" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c23d78776ad415d5506e0679723cb461d71f488f", - "reference": "c23d78776ad415d5506e0679723cb461d71f488f", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/134669cf0eeac3f79bc7f0c793efbc158bffc160", + "reference": "134669cf0eeac3f79bc7f0c793efbc158bffc160", "shasum": "" }, "require": { @@ -2212,7 +2531,7 @@ "phpunit/php-code-coverage": "^6.0.7", "phpunit/php-file-iterator": "^2.0.1", "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^2.0", + "phpunit/php-timer": "^2.1", "sebastian/comparator": "^3.0", "sebastian/diff": "^3.0", "sebastian/environment": "^4.0", @@ -2265,7 +2584,7 @@ "testing", "xunit" ], - "time": "2018-12-12T07:20:32+00:00" + "time": "2019-04-19T15:50:46+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -2378,23 +2697,23 @@ }, { "name": "sebastian/diff", - "version": "3.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "366541b989927187c4ca70490a35615d3fef2dce" + "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/366541b989927187c4ca70490a35615d3fef2dce", - "reference": "366541b989927187c4ca70490a35615d3fef2dce", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29", + "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29", "shasum": "" }, "require": { "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "^7.0", + "phpunit/phpunit": "^7.5 || ^8.0", "symfony/process": "^2 || ^3.3 || ^4" }, "type": "library", @@ -2430,32 +2749,35 @@ "unidiff", "unified diff" ], - "time": "2018-06-10T07:54:39+00:00" + "time": "2019-02-04T06:01:07+00:00" }, { "name": "sebastian/environment", - "version": "4.0.1", + "version": "4.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "febd209a219cea7b56ad799b30ebbea34b71eb8f" + "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/febd209a219cea7b56ad799b30ebbea34b71eb8f", - "reference": "febd209a219cea7b56ad799b30ebbea34b71eb8f", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/f2a2c8e1c97c11ace607a7a667d73d47c19fe404", + "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404", "shasum": "" }, "require": { "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "^7.4" + "phpunit/phpunit": "^7.5" + }, + "suggest": { + "ext-posix": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -2480,7 +2802,7 @@ "environment", "hhvm" ], - "time": "2018-11-25T09:31:21+00:00" + "time": "2019-05-05T09:05:15+00:00" }, { "name": "sebastian/exporter", @@ -2832,16 +3154,16 @@ }, { "name": "symfony/event-dispatcher", - "version": "v4.2.1", + "version": "v4.2.8", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "921f49c3158a276d27c0d770a5a347a3b718b328" + "reference": "fbce53cd74ac509cbe74b6f227622650ab759b02" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/921f49c3158a276d27c0d770a5a347a3b718b328", - "reference": "921f49c3158a276d27c0d770a5a347a3b718b328", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/fbce53cd74ac509cbe74b6f227622650ab759b02", + "reference": "fbce53cd74ac509cbe74b6f227622650ab759b02", "shasum": "" }, "require": { @@ -2892,20 +3214,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2018-12-01T08:52:38+00:00" + "time": "2019-04-06T13:51:08+00:00" }, { "name": "symfony/filesystem", - "version": "v4.2.1", + "version": "v4.2.8", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "2f4c8b999b3b7cadb2a69390b01af70886753710" + "reference": "e16b9e471703b2c60b95f14d31c1239f68f11601" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/2f4c8b999b3b7cadb2a69390b01af70886753710", - "reference": "2f4c8b999b3b7cadb2a69390b01af70886753710", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/e16b9e471703b2c60b95f14d31c1239f68f11601", + "reference": "e16b9e471703b2c60b95f14d31c1239f68f11601", "shasum": "" }, "require": { @@ -2942,20 +3264,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2018-11-11T19:52:12+00:00" + "time": "2019-02-07T11:40:08+00:00" }, { "name": "symfony/options-resolver", - "version": "v4.2.1", + "version": "v4.2.8", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "a9c38e8a3da2c03b3e71fdffa6efb0bda51390ba" + "reference": "fd4a5f27b7cd085b489247b9890ebca9f3e10044" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/a9c38e8a3da2c03b3e71fdffa6efb0bda51390ba", - "reference": "a9c38e8a3da2c03b3e71fdffa6efb0bda51390ba", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/fd4a5f27b7cd085b489247b9890ebca9f3e10044", + "reference": "fd4a5f27b7cd085b489247b9890ebca9f3e10044", "shasum": "" }, "require": { @@ -2996,20 +3318,20 @@ "configuration", "options" ], - "time": "2018-11-11T19:52:12+00:00" + "time": "2019-04-10T16:20:36+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.10.0", + "version": "v1.11.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "e3d826245268269cd66f8326bd8bc066687b4a19" + "reference": "82ebae02209c21113908c229e9883c419720738a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19", - "reference": "e3d826245268269cd66f8326bd8bc066687b4a19", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a", + "reference": "82ebae02209c21113908c229e9883c419720738a", "shasum": "" }, "require": { @@ -3021,7 +3343,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.9-dev" + "dev-master": "1.11-dev" } }, "autoload": { @@ -3043,7 +3365,7 @@ }, { "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" + "email": "backendtea@gmail.com" } ], "description": "Symfony polyfill for ctype functions", @@ -3054,20 +3376,20 @@ "polyfill", "portable" ], - "time": "2018-08-06T14:22:27+00:00" + "time": "2019-02-06T07:57:58+00:00" }, { "name": "symfony/polyfill-php70", - "version": "v1.10.0", + "version": "v1.11.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "6b88000cdd431cd2e940caa2cb569201f3f84224" + "reference": "bc4858fb611bda58719124ca079baff854149c89" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/6b88000cdd431cd2e940caa2cb569201f3f84224", - "reference": "6b88000cdd431cd2e940caa2cb569201f3f84224", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/bc4858fb611bda58719124ca079baff854149c89", + "reference": "bc4858fb611bda58719124ca079baff854149c89", "shasum": "" }, "require": { @@ -3077,7 +3399,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.9-dev" + "dev-master": "1.11-dev" } }, "autoload": { @@ -3113,20 +3435,20 @@ "portable", "shim" ], - "time": "2018-09-21T06:26:08+00:00" + "time": "2019-02-06T07:57:58+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.10.0", + "version": "v1.11.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "9050816e2ca34a8e916c3a0ae8b9c2fccf68b631" + "reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9050816e2ca34a8e916c3a0ae8b9c2fccf68b631", - "reference": "9050816e2ca34a8e916c3a0ae8b9c2fccf68b631", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/ab50dcf166d5f577978419edd37aa2bb8eabce0c", + "reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c", "shasum": "" }, "require": { @@ -3135,7 +3457,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.9-dev" + "dev-master": "1.11-dev" } }, "autoload": { @@ -3168,20 +3490,20 @@ "portable", "shim" ], - "time": "2018-09-21T13:07:52+00:00" + "time": "2019-02-06T07:57:58+00:00" }, { "name": "symfony/process", - "version": "v4.2.1", + "version": "v4.2.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "2b341009ccec76837a7f46f59641b431e4d4c2b0" + "reference": "8cf39fb4ccff793340c258ee7760fd40bfe745fe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/2b341009ccec76837a7f46f59641b431e4d4c2b0", - "reference": "2b341009ccec76837a7f46f59641b431e4d4c2b0", + "url": "https://api.github.com/repos/symfony/process/zipball/8cf39fb4ccff793340c258ee7760fd40bfe745fe", + "reference": "8cf39fb4ccff793340c258ee7760fd40bfe745fe", "shasum": "" }, "require": { @@ -3217,20 +3539,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2018-11-20T16:22:05+00:00" + "time": "2019-04-10T16:20:36+00:00" }, { "name": "symfony/stopwatch", - "version": "v4.2.1", + "version": "v4.2.8", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "ec076716412274e51f8a7ea675d9515e5c311123" + "reference": "b1a5f646d56a3290230dbc8edf2a0d62cda23f67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/ec076716412274e51f8a7ea675d9515e5c311123", - "reference": "ec076716412274e51f8a7ea675d9515e5c311123", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/b1a5f646d56a3290230dbc8edf2a0d62cda23f67", + "reference": "b1a5f646d56a3290230dbc8edf2a0d62cda23f67", "shasum": "" }, "require": { @@ -3267,20 +3589,20 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2018-11-11T19:52:12+00:00" + "time": "2019-01-16T20:31:39+00:00" }, { "name": "theseer/tokenizer", - "version": "1.1.0", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b" + "reference": "1c42705be2b6c1de5904f8afacef5895cab44bf8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b", - "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/1c42705be2b6c1de5904f8afacef5895cab44bf8", + "reference": "1c42705be2b6c1de5904f8afacef5895cab44bf8", "shasum": "" }, "require": { @@ -3307,24 +3629,25 @@ } ], "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "time": "2017-04-07T12:08:54+00:00" + "time": "2019-04-04T09:56:43+00:00" }, { "name": "webmozart/assert", - "version": "1.3.0", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a" + "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a", + "url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9", + "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^5.3.3 || ^7.0", + "symfony/polyfill-ctype": "^1.8" }, "require-dev": { "phpunit/phpunit": "^4.6", @@ -3357,7 +3680,161 @@ "check", "validate" ], - "time": "2018-01-29T19:49:41+00:00" + "time": "2018-12-25T11:19:39+00:00" + }, + { + "name": "yiisoft/yii2", + "version": "2.0.18", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/yii2-framework.git", + "reference": "be563f0211bd5d4424680d0fcdef578090f08e41" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/yii2-framework/zipball/be563f0211bd5d4424680d0fcdef578090f08e41", + "reference": "be563f0211bd5d4424680d0fcdef578090f08e41", + "shasum": "" + }, + "require": { + "bower-asset/inputmask": "~3.2.2 | ~3.3.5", + "bower-asset/jquery": "3.3.*@stable | 3.2.*@stable | 3.1.*@stable | 2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable", + "bower-asset/punycode": "1.3.*", + "bower-asset/yii2-pjax": "~2.0.1", + "cebe/markdown": "~1.0.0 | ~1.1.0 | ~1.2.0", + "ext-ctype": "*", + "ext-mbstring": "*", + "ezyang/htmlpurifier": "~4.6", + "lib-pcre": "*", + "php": ">=5.4.0", + "yiisoft/yii2-composer": "~2.0.4" + }, + "bin": [ + "yii" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "yii\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Qiang Xue", + "email": "qiang.xue@gmail.com", + "homepage": "http://www.yiiframework.com/", + "role": "Founder and project lead" + }, + { + "name": "Alexander Makarov", + "email": "sam@rmcreative.ru", + "homepage": "http://rmcreative.ru/", + "role": "Core framework development" + }, + { + "name": "Maurizio Domba", + "homepage": "http://mdomba.info/", + "role": "Core framework development" + }, + { + "name": "Carsten Brandt", + "email": "mail@cebe.cc", + "homepage": "http://cebe.cc/", + "role": "Core framework development" + }, + { + "name": "Timur Ruziev", + "email": "resurtm@gmail.com", + "homepage": "http://resurtm.com/", + "role": "Core framework development" + }, + { + "name": "Paul Klimov", + "email": "klimov.paul@gmail.com", + "role": "Core framework development" + }, + { + "name": "Dmitry Naumenko", + "email": "d.naumenko.a@gmail.com", + "role": "Core framework development" + }, + { + "name": "Boudewijn Vahrmeijer", + "email": "info@dynasource.eu", + "homepage": "http://dynasource.eu", + "role": "Core framework development" + } + ], + "description": "Yii PHP Framework Version 2", + "homepage": "http://www.yiiframework.com/", + "keywords": [ + "framework", + "yii2" + ], + "time": "2019-04-23T12:48:26+00:00" + }, + { + "name": "yiisoft/yii2-composer", + "version": "2.0.7", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/yii2-composer.git", + "reference": "1439e78be1218c492e6cde251ed87d3f128b9534" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/yii2-composer/zipball/1439e78be1218c492e6cde251ed87d3f128b9534", + "reference": "1439e78be1218c492e6cde251ed87d3f128b9534", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0" + }, + "require-dev": { + "composer/composer": "^1.0" + }, + "type": "composer-plugin", + "extra": { + "class": "yii\\composer\\Plugin", + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "yii\\composer\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Qiang Xue", + "email": "qiang.xue@gmail.com" + }, + { + "name": "Carsten Brandt", + "email": "mail@cebe.cc" + } + ], + "description": "The composer plugin for Yii extension installer", + "keywords": [ + "composer", + "extension installer", + "yii2" + ], + "time": "2018-07-05T15:44:47+00:00" } ], "aliases": [], diff --git a/extension.neon b/extension.neon index 9deb11a..9f8ba2f 100644 --- a/extension.neon +++ b/extension.neon @@ -1,19 +1,37 @@ services: - - class: Proget\PHPStan\Yii2\Type\ContainerDynamicMethodReturnTypeExtension - tags: [phpstan.broker.dynamicMethodReturnTypeExtension] - - - class: Proget\PHPStan\Yii2\Type\ActiveRecordDynamicStaticMethodReturnTypeExtension - tags: [phpstan.broker.dynamicStaticMethodReturnTypeExtension] + class: Proget\PHPStan\Yii2\Reflection\ApplicationPropertiesClassReflectionExtension + tags: [phpstan.broker.propertiesClassReflectionExtension] - class: Proget\PHPStan\Yii2\Reflection\RequestMethodsClassReflectionExtension tags: [phpstan.broker.methodsClassReflectionExtension] - class: Proget\PHPStan\Yii2\Reflection\RequestPropertiesClassReflectionExtension tags: [phpstan.broker.propertiesClassReflectionExtension] + - + class: Proget\PHPStan\Yii2\Reflection\ResponsePropertiesClassReflectionExtension + tags: [phpstan.broker.propertiesClassReflectionExtension] + - + class: Proget\PHPStan\Yii2\Reflection\UserPropertiesClassReflectionExtension + tags: [phpstan.broker.propertiesClassReflectionExtension] + - + class: Proget\PHPStan\Yii2\Type\ActiveQueryDynamicMethodReturnTypeExtension + tags: [phpstan.broker.dynamicMethodReturnTypeExtension] + - + class: Proget\PHPStan\Yii2\Type\ActiveRecordDynamicMethodReturnTypeExtension + tags: [phpstan.broker.dynamicMethodReturnTypeExtension] + - + class: Proget\PHPStan\Yii2\Type\ActiveRecordDynamicStaticMethodReturnTypeExtension + tags: [phpstan.broker.dynamicStaticMethodReturnTypeExtension] + - + class: Proget\PHPStan\Yii2\Type\ContainerDynamicMethodReturnTypeExtension + tags: [phpstan.broker.dynamicMethodReturnTypeExtension] + - + class: Proget\PHPStan\Yii2\Type\YiiDynamicStaticMethodReturnTypeExtension + tags: [phpstan.broker.dynamicStaticMethodReturnTypeExtension] - Proget\PHPStan\Yii2\ServiceMap(%yii2.config_path%) + parameters: ignoreErrors: - '#Call to an undefined method yii\\console\\Response#' - - '#Access to an undefined property yii\\console\\Response#' diff --git a/phpstan.neon b/phpstan.neon index b2b86dc..339ae71 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,3 +1,14 @@ includes: - vendor/phpstan/phpstan-phpunit/extension.neon - vendor/phpstan/phpstan-phpunit/rules.neon + + - extension.neon + +parameters: + autoload_files: + - %rootDir%/../../../vendor/yiisoft/yii2/Yii.php + + reportUnmatchedIgnoredErrors: false + + yii2: + config_path: %rootDir%/../../../tests/assets/yii-config-valid.php diff --git a/src/Reflection/ApplicationPropertiesClassReflectionExtension.php b/src/Reflection/ApplicationPropertiesClassReflectionExtension.php new file mode 100644 index 0000000..2ca90e7 --- /dev/null +++ b/src/Reflection/ApplicationPropertiesClassReflectionExtension.php @@ -0,0 +1,76 @@ +annotationsProperties = $annotationsProperties; + $this->serviceMap = $serviceMap; + } + + public function setBroker(Broker $broker): void + { + $this->broker = $broker; + } + + public function hasProperty(ClassReflection $classReflection, string $propertyName): bool + { + if (!\in_array($classReflection->getName(), ['yii\console\Application', 'yii\web\Application'], true)) { + return false; + } + + if ($classReflection->getName() === 'yii\console\Application') { + $classReflection = $this->broker->getClass('yii\web\Application'); + } + + return $classReflection->hasNativeProperty($propertyName) + || $this->annotationsProperties->hasProperty($classReflection, $propertyName) + || $this->serviceMap->getComponentClassById($propertyName); + } + + public function getProperty(ClassReflection $classReflection, string $propertyName): PropertyReflection + { + if ($classReflection->getName() === 'yii\console\Application') { + $classReflection = $this->broker->getClass('yii\web\Application'); + } + + if (null !== $componentClass = $this->serviceMap->getComponentClassById($propertyName)) { + return new ComponentPropertyReflection(new DummyPropertyReflection(), new ObjectType($componentClass)); + } + + if ($classReflection->hasNativeProperty($propertyName)) { + return $classReflection->getNativeProperty($propertyName); + } + + return $this->annotationsProperties->getProperty($classReflection, $propertyName); + } +} diff --git a/src/Reflection/ComponentPropertyReflection.php b/src/Reflection/ComponentPropertyReflection.php new file mode 100644 index 0000000..3cc3d44 --- /dev/null +++ b/src/Reflection/ComponentPropertyReflection.php @@ -0,0 +1,63 @@ +fallbackProperty = $fallbackProperty; + $this->type = $type; + } + + public function getType(): Type + { + return $this->type; + } + + public function isReadable(): bool + { + return $this->fallbackProperty->isReadable(); + } + + public function isWritable(): bool + { + return $this->fallbackProperty->isWritable(); + } + + public function getDeclaringClass(): ClassReflection + { + return $this->fallbackProperty->getDeclaringClass(); + } + + public function isStatic(): bool + { + return $this->fallbackProperty->isStatic(); + } + + public function isPrivate(): bool + { + return $this->fallbackProperty->isPrivate(); + } + + public function isPublic(): bool + { + return $this->fallbackProperty->isPublic(); + } +} diff --git a/src/Reflection/RequestMethodsClassReflectionExtension.php b/src/Reflection/RequestMethodsClassReflectionExtension.php index dfedd3a..fe7cfb0 100644 --- a/src/Reflection/RequestMethodsClassReflectionExtension.php +++ b/src/Reflection/RequestMethodsClassReflectionExtension.php @@ -28,15 +28,11 @@ public function hasMethod(ClassReflection $classReflection, string $methodName): return false; } - $webRequest = $this->broker->getClass('yii\web\Request'); - - return $webRequest->hasMethod($methodName); + return $this->broker->getClass('yii\web\Request')->hasMethod($methodName); } public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection { - $webRequest = $this->broker->getClass('yii\web\Request'); - - return $webRequest->getNativeMethod($methodName); + return $this->broker->getClass('yii\web\Request')->getNativeMethod($methodName); } } diff --git a/src/Reflection/RequestPropertiesClassReflectionExtension.php b/src/Reflection/RequestPropertiesClassReflectionExtension.php index 2611de2..af21323 100644 --- a/src/Reflection/RequestPropertiesClassReflectionExtension.php +++ b/src/Reflection/RequestPropertiesClassReflectionExtension.php @@ -4,11 +4,7 @@ namespace Proget\PHPStan\Yii2\Reflection; -use PhpParser\PrettyPrinter\Standard; -use PHPStan\Analyser\Scope; -use PHPStan\Analyser\ScopeContext; -use PHPStan\Analyser\ScopeFactory; -use PHPStan\Analyser\TypeSpecifier; +use PHPStan\Analyser\OutOfClassScope; use PHPStan\Broker\Broker; use PHPStan\Reflection\BrokerAwareExtension; use PHPStan\Reflection\ClassReflection; @@ -22,15 +18,9 @@ final class RequestPropertiesClassReflectionExtension implements PropertiesClass */ private $broker; - /** - * @var ScopeFactory - */ - private $scopeFactory; - public function setBroker(Broker $broker): void { $this->broker = $broker; - $this->scopeFactory = new ScopeFactory(Scope::class, $broker, new Standard(), new TypeSpecifier(new Standard(), $broker, [], [], []), []); } public function hasProperty(ClassReflection $classReflection, string $propertyName): bool @@ -39,18 +29,11 @@ public function hasProperty(ClassReflection $classReflection, string $propertyNa return false; } - $webRequest = $this->broker->getClass('yii\web\Request'); - - return $webRequest->hasProperty($propertyName); + return $this->broker->getClass('yii\web\Request')->hasProperty($propertyName); } public function getProperty(ClassReflection $classReflection, string $propertyName): PropertyReflection { - $webRequest = $this->broker->getClass('yii\web\Request'); - - return $webRequest->getProperty( - $propertyName, - $this->scopeFactory->create(ScopeContext::create((string) $classReflection->getFileName())) - ); + return $this->broker->getClass('yii\web\Request')->getProperty($propertyName, new OutOfClassScope()); } } diff --git a/src/Reflection/ResponsePropertiesClassReflectionExtension.php b/src/Reflection/ResponsePropertiesClassReflectionExtension.php new file mode 100644 index 0000000..c21c44b --- /dev/null +++ b/src/Reflection/ResponsePropertiesClassReflectionExtension.php @@ -0,0 +1,39 @@ +broker = $broker; + } + + public function hasProperty(ClassReflection $classReflection, string $propertyName): bool + { + if ($classReflection->getName() !== 'yii\console\Response') { + return false; + } + + return $this->broker->getClass('yii\web\Response')->hasProperty($propertyName); + } + + public function getProperty(ClassReflection $classReflection, string $propertyName): PropertyReflection + { + return $this->broker->getClass('yii\web\Response')->getProperty($propertyName, new OutOfClassScope()); + } +} diff --git a/src/Reflection/UserPropertiesClassReflectionExtension.php b/src/Reflection/UserPropertiesClassReflectionExtension.php new file mode 100644 index 0000000..16afce2 --- /dev/null +++ b/src/Reflection/UserPropertiesClassReflectionExtension.php @@ -0,0 +1,48 @@ +annotationsProperties = $annotationsProperties; + } + + public function hasProperty(ClassReflection $classReflection, string $propertyName): bool + { + if ($classReflection->getName() !== 'yii\web\User') { + return false; + } + + return $classReflection->hasNativeProperty($propertyName) + || $this->annotationsProperties->hasProperty($classReflection, $propertyName); + } + + public function getProperty(ClassReflection $classReflection, string $propertyName): PropertyReflection + { + if ($propertyName === 'identity') { + return new ComponentPropertyReflection(new DummyPropertyReflection(), new MixedType()); + } + + if ($classReflection->hasNativeProperty($propertyName)) { + return $classReflection->getNativeProperty($propertyName); + } + + return $this->annotationsProperties->getProperty($classReflection, $propertyName); + } +} diff --git a/src/ServiceMap.php b/src/ServiceMap.php index 39e5992..00f3c3f 100644 --- a/src/ServiceMap.php +++ b/src/ServiceMap.php @@ -13,6 +13,11 @@ final class ServiceMap */ private $services = []; + /** + * @var string[][] + */ + private $components = []; + public function __construct(string $configPath) { if (!file_exists($configPath)) { @@ -36,6 +41,16 @@ public function __construct(string $configPath) $this->services[$id] = $service['class'] ?? $service[0]['class']; } } + + foreach ($config['components'] ?? [] as $id => $component) { + if (null !== $identityClass = $component['identityClass'] ?? null) { + $this->components[$id]['identityClass'] = $identityClass; + } + + if (null !== $class = $component['class'] ?? null) { + $this->components[$id]['class'] = $class; + } + } } public function getServiceClassFromNode(Node $node): ?string @@ -46,4 +61,14 @@ public function getServiceClassFromNode(Node $node): ?string return null; } + + public function getComponentClassById(string $id): ?string + { + return $this->components[$id]['class'] ?? null; + } + + public function getComponentIdentityClassById(string $id): ?string + { + return $this->components[$id]['identityClass'] ?? null; + } } diff --git a/src/Type/ActiveQueryDynamicMethodReturnTypeExtension.php b/src/Type/ActiveQueryDynamicMethodReturnTypeExtension.php new file mode 100644 index 0000000..bb66645 --- /dev/null +++ b/src/Type/ActiveQueryDynamicMethodReturnTypeExtension.php @@ -0,0 +1,77 @@ +getVariants())->getReturnType() instanceof ThisType) { + return true; + } + + return \in_array($methodReflection->getName(), ['one', 'all'], true); + } + + public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type + { + $calledOnType = $scope->getType($methodCall->var); + if (!$calledOnType instanceof ActiveQueryObjectType) { + throw new ShouldNotHappenException( + sprintf('Unexpected type %s during method call %s at line %d', \get_class($calledOnType), $methodReflection->getName(), $methodCall->getLine()) + ); + } + + $methodName = $methodReflection->getName(); + if ($methodName === 'asArray') { + $argType = isset($methodCall->args[0]) ? $scope->getType($methodCall->args[0]->value) : new ConstantBooleanType(true); + if (!$argType instanceof ConstantBooleanType) { + throw new ShouldNotHappenException( + sprintf('Invalid argument provided to asArray method at line %d', $methodCall->getLine()) + ); + } + + return new ActiveQueryObjectType($calledOnType->getModelClass(), $argType->getValue()); + } + + if (!\in_array($methodName, ['one', 'all'], true)) { + return new ActiveQueryObjectType($calledOnType->getModelClass(), $calledOnType->isAsArray()); + } + + if ($methodName === 'one') { + return TypeCombinator::union( + new NullType(), + $calledOnType->isAsArray() ? new ArrayType(new StringType(), new MixedType()) : new ObjectType($calledOnType->getModelClass()) + ); + } + + return new ArrayType( + new IntegerType(), + $calledOnType->isAsArray() ? new ArrayType(new StringType(), new MixedType()) : new ObjectType($calledOnType->getModelClass()) + ); + } +} diff --git a/src/Type/ActiveQueryObjectType.php b/src/Type/ActiveQueryObjectType.php new file mode 100644 index 0000000..4a6d69f --- /dev/null +++ b/src/Type/ActiveQueryObjectType.php @@ -0,0 +1,44 @@ +modelClass = $modelClass; + $this->asArray = $asArray; + } + + public function getModelClass(): string + { + return $this->modelClass; + } + + public function isAsArray(): bool + { + return $this->asArray; + } + + public function describe(VerbosityLevel $level): string + { + return sprintf('%s<%s>', parent::describe($level), $this->modelClass); + } +} diff --git a/src/Type/ActiveRecordDynamicMethodReturnTypeExtension.php b/src/Type/ActiveRecordDynamicMethodReturnTypeExtension.php new file mode 100644 index 0000000..a630556 --- /dev/null +++ b/src/Type/ActiveRecordDynamicMethodReturnTypeExtension.php @@ -0,0 +1,38 @@ +getName(), ['hasOne', 'hasMany'], true); + } + + public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type + { + $argType = $scope->getType($methodCall->args[0]->value); + if (!$argType instanceof ConstantStringType) { + throw new ShouldNotHappenException( + sprintf('Invalid argument provided to method %s'.PHP_EOL.'Hint: You should use ::class instead of ::className()', $methodReflection->getName()) + ); + } + + return new ActiveQueryObjectType($argType->getValue(), false); + } +} diff --git a/src/Type/ActiveRecordDynamicStaticMethodReturnTypeExtension.php b/src/Type/ActiveRecordDynamicStaticMethodReturnTypeExtension.php index a30d621..3743ff8 100644 --- a/src/Type/ActiveRecordDynamicStaticMethodReturnTypeExtension.php +++ b/src/Type/ActiveRecordDynamicStaticMethodReturnTypeExtension.php @@ -23,16 +23,23 @@ public function getClass(): string public function isStaticMethodSupported(MethodReflection $methodReflection): bool { - return $methodReflection->getName() === 'findOne'; + return \in_array($methodReflection->getName(), ['findOne', 'find'], true); } public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope): Type { - /** @var Name $name */ - $name = $methodCall->class; + /** @var Name $className */ + $className = $methodCall->class; + $name = $scope->resolveName($className); - return TypeCombinator::union( - new NullType(), new ObjectType($name->toString()) - ); + $methodName = $methodReflection->getName(); + if ($methodName === 'findOne') { + return TypeCombinator::union( + new NullType(), + new ObjectType($name) + ); + } + + return new ActiveQueryObjectType($name, false); } } diff --git a/src/Type/YiiDynamicStaticMethodReturnTypeExtension.php b/src/Type/YiiDynamicStaticMethodReturnTypeExtension.php new file mode 100644 index 0000000..c1b8b6f --- /dev/null +++ b/src/Type/YiiDynamicStaticMethodReturnTypeExtension.php @@ -0,0 +1,84 @@ +getName() === 'createObject'; + } + + public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, StaticCall $methodCall, Scope $scope): Type + { + $class = null; + if ($methodCall->args[0]->value instanceof String_) { + $class = $methodCall->args[0]->value->value; + } elseif ($methodCall->args[0]->value instanceof ClassConstFetch) { + if ($methodCall->args[0]->value->class instanceof Name) { + $class = $methodCall->args[0]->value->class->toString(); + } elseif ($methodCall->args[0]->value->class instanceof String_) { + $class = $methodCall->args[0]->value->class->value; + } + } elseif ($methodCall->args[0]->value instanceof Array_) { + $class = $this->extractClassFromArray($methodCall->args[0]->value); + } elseif ($methodCall->args[0]->value instanceof Closure) { + $returnType = $methodCall->args[0]->value->getReturnType(); + if ($returnType instanceof Name) { + return new ObjectType($returnType->toString()); + } + + throw new ShouldNotHappenException('Invalid $type callable argument provided to createObject method - return type is required.'); + } + + if (!$class) { + throw new ShouldNotHappenException('Invalid $type argument provided to createObject method.'); + } + + return new ObjectType($class); + } + + private function extractClassFromArray(Array_ $array): string + { + $class = null; + foreach ($array->items as $item) { + if ($item->key instanceof String_ && $item->key->value === 'class') { + if (!$item->value instanceof String_) { + throw new ShouldNotHappenException('Invalid $type array argument provided to createObject method - "class" key must be a string.'); + } + + if ($class) { + throw new ShouldNotHappenException('Invalid $type array argument provided to createObject method - duplicate "class" key.'); + } + + $class = $item->value->value; + } + } + + if (!$class) { + throw new ShouldNotHappenException('Invalid $type array argument provided to createObject method - missing "class" key.'); + } + + return $class; + } +} diff --git a/tests/ServiceMapTest.php b/tests/ServiceMapTest.php index d786c9c..d81bdfb 100644 --- a/tests/ServiceMapTest.php +++ b/tests/ServiceMapTest.php @@ -7,6 +7,7 @@ use PhpParser\Node\Scalar\String_; use PHPUnit\Framework\TestCase; use Proget\PHPStan\Yii2\ServiceMap; +use Proget\Tests\PHPStan\Yii2\Yii\MyActiveRecord; final class ServiceMapTest extends TestCase { @@ -26,13 +27,15 @@ public function testThrowExceptionWhenClosureServiceHasMissingReturnType(): void new ServiceMap(__DIR__.DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'yii-config-invalid.php'); } - public function testItLoadsServices(): void + public function testItLoadsServicesAndComponents(): void { $serviceMap = new ServiceMap(__DIR__.DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'yii-config-valid.php'); $this->assertSame(\SplStack::class, $serviceMap->getServiceClassFromNode(new String_('closure'))); $this->assertSame(\SplObjectStorage::class, $serviceMap->getServiceClassFromNode(new String_('service'))); $this->assertSame(\SplFileInfo::class, $serviceMap->getServiceClassFromNode(new String_('nested-service-class'))); + + $this->assertSame(MyActiveRecord::class, $serviceMap->getComponentClassById('customComponent')); } /** diff --git a/tests/Yii/MyActiveRecord.php b/tests/Yii/MyActiveRecord.php new file mode 100644 index 0000000..4905f0f --- /dev/null +++ b/tests/Yii/MyActiveRecord.php @@ -0,0 +1,29 @@ +hasMany(self::class, ['link'])->where(['condition'])->all(); + } + + public function getMaster(): ?self + { + return $this->hasOne(self::class, ['link'])->one(); + } + + /** + * @return self[] + */ + public function test(): array + { + return self::find()->all(); + } +} diff --git a/tests/Yii/MyController.php b/tests/Yii/MyController.php new file mode 100644 index 0000000..621354e --- /dev/null +++ b/tests/Yii/MyController.php @@ -0,0 +1,53 @@ +where(['flag' => \Yii::$app->request->post('flag', true)])->one(); + if ($record) { + $record->flag = false; + $record->save(); + } + + $record = MyActiveRecord::findOne(['condition']); + if ($record) { + $record->flag; + } + + $records = MyActiveRecord::find()->asArray()->where(['flag' => \Yii::$app->request->post('flag', true)])->all(); + foreach ($records as $record) { + $record['flag']; + } + + $records = MyActiveRecord::findAll('condition'); + foreach ($records as $record) { + $record->flag; + } + + $records = MyActiveRecord::find()->asArray(false)->where(['condition'])->all(); + foreach ($records as $record) { + $record->flag; + $record['flag']; + } + + \Yii::$app->response->data = \Yii::$app->request->rawBody; + + \Yii::$app->user->isGuest; + \Yii::$app->user->identity->getAuthKey(); + \Yii::$app->user->identity->doSomething(); + + \Yii::$app->customComponent->flag; + + \Yii::createObject(\SplObjectStorage::class)->count(); + \Yii::createObject('SplObjectStorage')->count(); + \Yii::createObject(['class' => '\SplObjectStorage'])->count(); + \Yii::createObject(static function (): \SplObjectStorage { + return new \SplObjectStorage(); + })->count(); + } +} diff --git a/tests/assets/yii-config-valid.php b/tests/assets/yii-config-valid.php index ea4482c..39e05e6 100644 --- a/tests/assets/yii-config-valid.php +++ b/tests/assets/yii-config-valid.php @@ -1,13 +1,22 @@ ['singletons' => [ - 'closure' => function(): \SplStack { - return new \SplStack(); - }, - 'service' => ['class' => \SplObjectStorage::class], - 'nested-service-class' => [ - ['class' => \SplFileInfo::class] + 'components' => [ + 'customComponent' => [ + 'class' => MyActiveRecord::class, + ], + ], + 'container' => [ + 'singletons' => [ + 'closure' => function(): \SplStack { + return new \SplStack(); + }, + 'service' => ['class' => \SplObjectStorage::class], + 'nested-service-class' => [ + ['class' => \SplFileInfo::class] + ] ] - ]] + ] ];