├── .editorconfig ├── CHANGELOG.md ├── composer.json ├── psalm-baseline.xml ├── src ├── Plugin.php └── Provider │ └── ReturnTypeProvider │ └── CollectionFirstAndLast.php └── stubs ├── AbstractLazyCollection.phpstub ├── ArrayCollection.phpstub ├── ClassMetadata.phpstub ├── ClassMetadataInfo.phpstub ├── Collections.phpstub ├── Connection.phpstub ├── DBAL ├── ExpressionBuilder.phpstub └── QueryBuilder.phpstub ├── EntityManager.phpstub ├── EntityManagerInterface.phpstub ├── EntityRepository.phpstub ├── Expr.phpstub ├── ExpressionBuilder.phpstub ├── ObjectManager.phpstub ├── ObjectRepository.phpstub ├── Paginator.phpstub ├── ParameterType.phpstub ├── PersistentCollection.phpstub ├── Query.phpstub └── QueryBuilder.phpstub /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | indent_style = space 7 | indent_size = 2 8 | 9 | [{*.php, *.json}] 10 | indent_size = 4 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file, in reverse chronological order by release. 4 | 5 | ## 1.0.0 - 2021-01-03 6 | 7 | ### Added 8 | 9 | - [#61](https://github.com/weirdan/doctrine-psalm-plugin/pull/61) Added taint sinks for DBAL\Connection (@adrienlucas) 10 | 11 | - [#67](https://github.com/weirdan/doctrine-psalm-plugin/pull/67) [#66](https://github.com/weirdan/doctrine-psalm-plugin/issues/66) Allow pushed to ArrayCollection 12 | 13 | - [#64](https://github.com/weirdan/doctrine-psalm-plugin/pull/64) [#63](https://github.com/weirdan/doctrine-psalm-plugin/issues/63) EntityRepository::matching() stub (@ygottschalk) 14 | 15 | ### Changed 16 | 17 | - [#72](https://github.com/weirdan/doctrine-psalm-plugin/pull/72) [#71](https://github.com/weirdan/doctrine-psalm-plugin/issues/71) Return type of ObjectRepository::findAll() from list to T[] 18 | 19 | - [#62](https://github.com/weirdan/doctrine-psalm-plugin/pull/62) Test on Symfony 5 (@amberovsky) 20 | 21 | ### Deprecated 22 | 23 | - Nothing. 24 | 25 | ### Removed 26 | 27 | - [#78](https://github.com/weirdan/doctrine-psalm-plugin/pull/78) Removed support for Psalm <4.3.2 (@tugmaks) 28 | 29 | ### Fixed 30 | 31 | - [#75](https://github.com/weirdan/doctrine-psalm-plugin/pull/75) [#69](https://github.com/weirdan/doctrine-psalm-plugin/issues/69) MethodSignatureMismatch on EntityManager methods 32 | 33 | - [#74](https://github.com/weirdan/doctrine-psalm-plugin/pull/74) [#70](https://github.com/weirdan/doctrine-psalm-plugin/issues/70) ManagerRegistry deprecation/removal 34 | 35 | ## 0.11.3 - 2020-06-21 36 | 37 | ### Added 38 | 39 | - Nothing. 40 | 41 | ### Changed 42 | 43 | - Changed stub files extension to hide them from some IDEs 44 | 45 | ### Deprecated 46 | 47 | - Nothing. 48 | 49 | ### Removed 50 | 51 | - Nothing. 52 | 53 | ### Fixed 54 | 55 | - Nothing. 56 | 57 | ## 0.11.2 - 2020-06-20 58 | 59 | ### Added 60 | 61 | - Nothing. 62 | 63 | ### Changed 64 | 65 | - Nothing. 66 | 67 | ### Deprecated 68 | 69 | - Nothing. 70 | 71 | ### Removed 72 | 73 | - Nothing. 74 | 75 | ### Fixed 76 | 77 | - [#57](https://github.com/weirdan/doctrine-psalm-plugin/pull/57) Allow classes extending query builder to return instances of themselves (thanks @enumag) 78 | 79 | ## 0.11.1 - 2020-04-16 80 | 81 | ### Added 82 | 83 | - Nothing. 84 | 85 | ### Changed 86 | 87 | - Nothing. 88 | 89 | ### Deprecated 90 | 91 | - Nothing. 92 | 93 | ### Removed 94 | 95 | - Nothing. 96 | 97 | ### Fixed 98 | 99 | - [#55](https://github.com/weirdan/doctrine-psalm-plugin/pull/55) Fixed EntityManager::getReference() type to be nullable (thanks @seferov) 100 | 101 | ## 0.11.0 - 2020-03-30 102 | 103 | ### Added 104 | 105 | - Nothing. 106 | 107 | ### Changed 108 | 109 | - [#54](https://github.com/weirdan/doctrine-psalm-plugin/pull/54) EntityManager::getReference() return type changed to nullable (thanks @simPod) 110 | 111 | ### Deprecated 112 | 113 | - Nothing. 114 | 115 | ### Removed 116 | 117 | - Nothing. 118 | 119 | ### Fixed 120 | 121 | - Nothing. 122 | 123 | ## 0.10.0 - 2020-02-27 124 | 125 | ### Added 126 | 127 | - [#48](https://github.com/weirdan/doctrine-psalm-plugin/pull/48) Added stub for Doctrine\DBAL\Query\Expression\ExpressionBuilder (thanks @mpolyakovsky) 128 | 129 | ### Changed 130 | 131 | - Nothing. 132 | 133 | ### Deprecated 134 | 135 | - Nothing. 136 | 137 | ### Removed 138 | 139 | - Nothing. 140 | 141 | ### Fixed 142 | 143 | - [#49](https://github.com/weirdan/doctrine-psalm-plugin/pull/49) Allow WHERE IN clauses in the ORM QueryBuilder (thanks @jaikdean) 144 | 145 | - [#50](https://github.com/weirdan/doctrine-psalm-plugin/pull/50) Fixed compatibility with Alpine Linux (missing GLOB_BRACE) (thanks @bendavies) 146 | 147 | ## 0.9.0 - 2020-01-19 148 | 149 | ### Added 150 | 151 | - [#45](https://github.com/weirdan/doctrine-psalm-plugin/pull/29) Added support for DBAL Query Builder (thanks @mpolyakovsky) 152 | 153 | ### Changed 154 | 155 | @orklah and @mpolyakovsky contributed a number of improvements to the test suite and other misc fixes 156 | 157 | ### Deprecated 158 | 159 | - Nothing. 160 | 161 | ### Removed 162 | 163 | - Support for Psalm older than 3.6.2 164 | 165 | ### Fixed 166 | 167 | - Nothing. 168 | 169 | ## 0.8.0 - 2019-10-17 170 | 171 | ### Added 172 | 173 | - [#29](https://github.com/weirdan/doctrine-psalm-plugin/pull/29) Added ClassMetadataInfo::$sequenceGeneratorDefinition 174 | 175 | ### Changed 176 | 177 | - Nothing. 178 | 179 | ### Deprecated 180 | 181 | - Nothing. 182 | 183 | ### Removed 184 | 185 | - Nothing. 186 | 187 | ### Fixed 188 | 189 | - Nothing. 190 | 191 | ## 0.7.1 - 2019-10-14 192 | 193 | ### Added 194 | 195 | - Nothing. 196 | 197 | ### Changed 198 | 199 | - Nothing. 200 | 201 | ### Deprecated 202 | 203 | - Nothing. 204 | 205 | ### Removed 206 | 207 | - Nothing. 208 | 209 | ### Fixed 210 | 211 | - [#28](https://github.com/weirdan/doctrine-psalm-plugin/pull/28) [#27](https://github.com/weirdan/doctrine-psalm-plugin/issues/27) `Expr\Comparison` is now allowed in `QueryBuilder::{where,orWhere,andWhere}()` 212 | 213 | ## 0.7.0 - 2019-10-13 214 | 215 | ### Added 216 | 217 | - [#26](https://github.com/weirdan/doctrine-psalm-plugin/pull/26) Support for variadic arguments of QueryBuilder methods (thanks @2e3s) 218 | 219 | ### Changed 220 | 221 | - Nothing. 222 | 223 | ### Deprecated 224 | 225 | - Nothing. 226 | 227 | ### Removed 228 | 229 | - Nothing. 230 | 231 | ### Fixed 232 | 233 | - Nothing. 234 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "weirdan/doctrine-psalm-plugin", 3 | "type": "psalm-plugin", 4 | "description": "Stubs to let Psalm understand Doctrine better", 5 | "minimum-stability": "dev", 6 | "keywords": [ 7 | "php", 8 | "code", 9 | "inspection", 10 | "doctrine", 11 | "orm", 12 | "doctrine2", 13 | "dbal", 14 | "psalm", 15 | "plugin", 16 | "psalm-plugin", 17 | "static analysis", 18 | "static-analysis", 19 | "extension" 20 | ], 21 | "license": "MIT", 22 | "authors": [ 23 | { 24 | "name": "Bruce Weirdan", 25 | "email": "weirdan@gmail.com" 26 | } 27 | ], 28 | "require": { 29 | "php": "^8", 30 | "composer/semver": "^1.4 || ^2.0 || ^3.0", 31 | "vimeo/psalm": "^6" 32 | }, 33 | "conflict": { 34 | "doctrine/collections": "<1.8", 35 | "doctrine/orm": "<2.6", 36 | "doctrine/persistence": "<2.0" 37 | }, 38 | "require-dev": { 39 | "codeception/codeception": "^4.0", 40 | "doctrine/coding-standard": "^9.0", 41 | "doctrine/collections": "^1.8 || ^2.0", 42 | "doctrine/doctrine-bundle": "^1.11 || ^2.0", 43 | "doctrine/orm": "^2.6", 44 | "doctrine/persistence": "^2.0", 45 | "phly/keep-a-changelog": "^2.1", 46 | "squizlabs/php_codesniffer": "^3.3", 47 | "weirdan/codeception-psalm-module": "^0.13.1" 48 | }, 49 | "config": { 50 | "sort-packages": true, 51 | "allow-plugins": { 52 | "composer/package-versions-deprecated": true, 53 | "dealerdirect/phpcodesniffer-composer-installer": true, 54 | "php-http/discovery": true 55 | } 56 | }, 57 | "extra": { 58 | "psalm": { 59 | "pluginClass": "Weirdan\\DoctrinePsalmPlugin\\Plugin" 60 | } 61 | }, 62 | "autoload": { 63 | "psr-4": { 64 | "Weirdan\\DoctrinePsalmPlugin\\": "src" 65 | } 66 | }, 67 | "autoload-dev": { 68 | "psr-4": { 69 | "Weirdan\\DoctrinePsalmPlugin\\Tests\\": [ 70 | "tests/_support", 71 | "tests/acceptance" 72 | ] 73 | } 74 | }, 75 | "scripts": { 76 | "check": [ 77 | "@phpcs", 78 | "@test", 79 | "@psalm" 80 | ], 81 | "phpcs": "phpcs --colors", 82 | "psalm": "psalm", 83 | "test": "codecept --colors run -v" 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /psalm-baseline.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/Plugin.php: -------------------------------------------------------------------------------- 1 | getStubFiles() as $file) { 25 | $psalm->addStubFile($file); 26 | } 27 | 28 | if (class_exists(CollectionFirstAndLast::class)) { 29 | $psalm->registerHooksFromClass(CollectionFirstAndLast::class); 30 | } 31 | } 32 | 33 | /** 34 | * @return string[] 35 | * 36 | * @psalm-suppress RiskyTruthyFalsyComparison 37 | */ 38 | private function getStubFiles(): array 39 | { 40 | return array_merge( 41 | glob(__DIR__ . '/../stubs/*.phpstub') ?: [], 42 | glob(__DIR__ . '/../stubs/DBAL/*.phpstub') ?: [] 43 | ); 44 | } 45 | 46 | private function hasPackage(string $packageName): bool 47 | { 48 | try { 49 | $this->getPackageVersion($packageName); 50 | } catch (OutOfBoundsException $e) { 51 | return false; 52 | } 53 | 54 | return true; 55 | } 56 | 57 | /** 58 | * @throws OutOfBoundsException 59 | * 60 | * @psalm-suppress UnusedParam 61 | */ 62 | private function getPackageVersion(string $packageName): string 63 | { 64 | if (class_exists(Versions::class)) { 65 | return (string) Versions::getVersion($packageName); 66 | } 67 | 68 | throw new OutOfBoundsException(); 69 | } 70 | 71 | private function hasPackageOfVersion(string $packageName, string $constraints): bool 72 | { 73 | $packageVersion = $this->getPackageVersion($packageName); 74 | if (strpos($packageVersion, '@') !== false) { 75 | [$packageVersion] = explode('@', $packageVersion); 76 | } 77 | 78 | if (strpos($packageVersion, 'dev-') === 0) { 79 | $packageVersion = '9999999-dev'; 80 | } 81 | 82 | return Semver::satisfies($packageVersion, $constraints); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/Provider/ReturnTypeProvider/CollectionFirstAndLast.php: -------------------------------------------------------------------------------- 1 | */ 24 | public static function getClassLikeNames(): array 25 | { 26 | return [ 27 | 'Doctrine\Common\Collections\Collection', 28 | 'Doctrine\Common\Collections\ReadableCollection', 29 | ]; 30 | } 31 | 32 | public static function getMethodReturnType(MethodReturnTypeProviderEvent $event): ?Type\Union 33 | { 34 | $stmt = $event->getStmt(); 35 | if (! $stmt instanceof MethodCall) { 36 | return null; 37 | } 38 | 39 | // Get variable or property string 40 | $varStmt = $stmt->var; 41 | $varParts = []; 42 | while ($varStmt instanceof PropertyFetch && $varStmt->name instanceof Identifier) { 43 | $varParts[] = $varStmt->name->name; 44 | $varStmt = $varStmt->var; 45 | } 46 | 47 | if (! $varStmt instanceof Variable || ! is_string($varStmt->name)) { 48 | return null; 49 | } 50 | 51 | $varParts[] = $varStmt->name; 52 | $scopedVarName = '$' . implode('->', array_reverse($varParts)) . '->isempty()'; 53 | 54 | if ($event->getFqClasslikeName() === 'Doctrine\Common\Collections\Collection') { 55 | if ($event->getMethodNameLowercase() === 'add') { 56 | $event->getContext()->vars_in_scope[$scopedVarName] = Type::getFalse(); 57 | 58 | return null; 59 | } 60 | 61 | if ($event->getMethodNameLowercase() === 'remove' || $event->getMethodNameLowercase() === 'removeelement') { 62 | $event->getContext()->remove($scopedVarName); 63 | 64 | return null; 65 | } 66 | } 67 | 68 | if ( 69 | ! isset($event->getContext()->vars_in_scope[$scopedVarName]) 70 | || $event->getMethodNameLowercase() !== 'first' 71 | && $event->getMethodNameLowercase() !== 'last' 72 | ) { 73 | return null; 74 | } 75 | 76 | $type = $event->getContext()->vars_in_scope[$scopedVarName]; 77 | 78 | if ($type->isFalse()) { 79 | $collectionType = $event->getSource()->getNodeTypeProvider()->getType($stmt->var); 80 | if ($collectionType === null) { 81 | return null; 82 | } 83 | 84 | $atomicTypes = $collectionType->getAtomicTypes(); 85 | if (count($atomicTypes) !== 1) { 86 | return null; 87 | } 88 | 89 | $type = current($atomicTypes); 90 | if (! $type instanceof Type\Atomic\TGenericObject) { 91 | return null; 92 | } 93 | 94 | $childNode = $type->type_params; 95 | if (! isset($childNode[1]) || ! $childNode[1] instanceof Type\Union) { 96 | return null; 97 | } 98 | 99 | return $childNode[1]; 100 | } 101 | 102 | if ($type->isTrue()) { 103 | return Type::getFalse(); 104 | } 105 | 106 | return null; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /stubs/AbstractLazyCollection.phpstub: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class AbstractLazyCollection implements Collection 11 | { 12 | /** 13 | * @return bool 14 | * @psalm-mutation-free 15 | */ 16 | public function isEmpty(); 17 | } 18 | -------------------------------------------------------------------------------- /stubs/ArrayCollection.phpstub: -------------------------------------------------------------------------------- 1 | 11 | * @template-implements Selectable 12 | */ 13 | class ArrayCollection implements Collection, Selectable 14 | { 15 | /** 16 | * @return bool 17 | * @psalm-mutation-free 18 | */ 19 | public function isEmpty(); 20 | 21 | /** 22 | * @return int<0, max> 23 | */ 24 | public function count(); 25 | } 26 | -------------------------------------------------------------------------------- /stubs/ClassMetadata.phpstub: -------------------------------------------------------------------------------- 1 | 15 | * @template-extends ArrayAccess 16 | */ 17 | interface Collection extends ReadableCollection, ArrayAccess 18 | { 19 | 20 | /** 21 | * @param ?TKey $offset 22 | * @param TValue $value 23 | * @return void 24 | */ 25 | public function offsetSet($offset, $value); 26 | 27 | /** 28 | * @param TValue $element 29 | * @return true 30 | */ 31 | public function add($element); 32 | 33 | /** 34 | * @return void 35 | */ 36 | public function clear(); 37 | 38 | /** 39 | * @param TKey $key 40 | * @return TValue|null 41 | */ 42 | public function remove($key); 43 | 44 | /** 45 | * @param TValue $element 46 | * @return bool 47 | */ 48 | public function removeElement($element); 49 | 50 | /** 51 | * @param TKey $key 52 | * @param TValue $value 53 | * @return void 54 | */ 55 | public function set($key, $value); 56 | 57 | /** 58 | * @param Closure(TValue=):bool $p 59 | * @return Collection 60 | */ 61 | public function filter(Closure $p); 62 | 63 | /** 64 | * @param Closure(TKey=,TValue=):bool $p 65 | * @return array{0:Collection,1:Collection} 66 | */ 67 | public function partition(Closure $p); 68 | } 69 | 70 | /** 71 | * @template TKey as array-key 72 | * @template-covariant TValue 73 | * 74 | * @template-extends IteratorAggregate 75 | */ 76 | interface ReadableCollection extends Countable, IteratorAggregate 77 | { 78 | 79 | /** 80 | * @param TValue $element 81 | * @return bool 82 | */ 83 | public function contains($element); 84 | 85 | /** 86 | * @return bool 87 | * @psalm-mutation-free 88 | */ 89 | public function isEmpty(); 90 | 91 | /** 92 | * @param TKey $key 93 | * @return bool 94 | */ 95 | public function containsKey($key); 96 | 97 | /** 98 | * @param TKey $key 99 | * @return TValue|null 100 | */ 101 | public function get($key); 102 | 103 | /** 104 | * @return list 105 | */ 106 | public function getKeys(); 107 | 108 | /** 109 | * @return list 110 | */ 111 | public function getValues(); 112 | 113 | /** 114 | * @return array 115 | */ 116 | public function toArray(); 117 | 118 | /** 119 | * @return TValue|false 120 | */ 121 | public function first(); 122 | 123 | /** 124 | * @return TValue|false 125 | */ 126 | public function last(); 127 | 128 | /** 129 | * @return TKey|null 130 | */ 131 | public function key(); 132 | 133 | /** 134 | * @return TValue|false 135 | */ 136 | public function current(); 137 | 138 | /** 139 | * @return TValue|false 140 | */ 141 | public function next(); 142 | 143 | /** 144 | * @param int $offset 145 | * @param int|null $length 146 | * @return array 147 | */ 148 | public function slice($offset, $length = null); 149 | 150 | /** 151 | * @param Closure(TKey=,TValue=):bool $p 152 | * @return bool 153 | */ 154 | public function exists(Closure $p); 155 | 156 | /** 157 | * @param Closure(TValue=):bool $p 158 | * @return ReadableCollection 159 | */ 160 | public function filter(Closure $p); 161 | 162 | /** 163 | * @template T 164 | * @param Closure(TValue=):T $func 165 | * @return Collection 166 | */ 167 | public function map(Closure $func); 168 | 169 | /** 170 | * @param Closure(TKey=,TValue=):bool $p 171 | * @return array{0:ReadableCollection,1:ReadableCollection} 172 | */ 173 | public function partition(Closure $p); 174 | 175 | /** 176 | * @param Closure(TKey=,TValue=):bool $p 177 | * @return bool 178 | */ 179 | public function forAll(Closure $p); 180 | 181 | /** 182 | * @param TValue $element 183 | * @return false|TKey 184 | */ 185 | public function indexOf($element); 186 | } 187 | 188 | /** 189 | * @template TKey as array-key 190 | * @template TValue 191 | */ 192 | interface Selectable 193 | { 194 | /** 195 | * @return Collection 196 | */ 197 | public function matching(Criteria $criteria); 198 | } 199 | -------------------------------------------------------------------------------- /stubs/Connection.phpstub: -------------------------------------------------------------------------------- 1 | $params The query parameters. 65 | * @psalm-param array $types The parameter types. 66 | * 67 | * @throws DBALException 68 | * @psalm-taint-sink sql $query 69 | */ 70 | public function executeUpdate(string $query, array $params = [], array $types = []): int {} 71 | 72 | /** 73 | * @psalm-param list|array $params Statement parameters 74 | * @psalm-param array|array $types Parameter types 75 | * 76 | * @throws DBALException 77 | * @psalm-taint-sink sql $sql 78 | */ 79 | public function executeStatement($sql, array $params = [], array $types = []): int {} 80 | 81 | /** 82 | * @psalm-pure 83 | * 84 | * @psalm-param mixed $input 85 | * @psalm-return string 86 | * 87 | * @psalm-taint-escape sql 88 | * @psalm-flow ($input) -> return 89 | */ 90 | public function quote($input, int $type = ParameterType::STRING); 91 | } 92 | -------------------------------------------------------------------------------- /stubs/DBAL/ExpressionBuilder.phpstub: -------------------------------------------------------------------------------- 1 | $entityName 10 | * 11 | * @return EntityRepository 12 | */ 13 | public function getRepository($entityName) 14 | { 15 | } 16 | 17 | /** 18 | * @template T 19 | * @param class-string $entityName 20 | * @param mixed $id 21 | * @param null|int $lockMode 22 | * @param null|int $lockVersion 23 | * 24 | * @return null|T 25 | */ 26 | public function find($entityName, $id, $lockMode = null, $lockVersion = null) 27 | { 28 | } 29 | 30 | /** 31 | * @template T 32 | * @param class-string $entityName 33 | * @param mixed $id 34 | * 35 | * @return null|T 36 | */ 37 | public function getReference($entityName, $id) 38 | { 39 | } 40 | 41 | /** 42 | * @param object $entity 43 | * @param null|int $lockMode 44 | * 45 | * @return void 46 | */ 47 | public function refresh($entity, $lockMode = null) 48 | { 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /stubs/EntityManagerInterface.phpstub: -------------------------------------------------------------------------------- 1 | $entityName 11 | * 12 | * @return EntityRepository 13 | * 14 | * @template T 15 | */ 16 | public function getRepository(string $entityName); 17 | 18 | /** 19 | * @param class-string $entityName 20 | * @param mixed $id 21 | * 22 | * @return ?T 23 | * 24 | * @template T 25 | */ 26 | public function find(string $entityName, $id, ?int $lockMode = null, ?int $lockVersion = null); 27 | 28 | /** 29 | * @param class-string $entityName 30 | * @param mixed $id 31 | * 32 | * @return T|null 33 | * 34 | * @template T 35 | */ 36 | public function getReference(string $entityName, $id); 37 | 38 | /** 39 | * @param object $entity 40 | * 41 | * @return void 42 | */ 43 | public function refresh($entity, ?int $lockMode = null); 44 | } 45 | -------------------------------------------------------------------------------- /stubs/EntityRepository.phpstub: -------------------------------------------------------------------------------- 1 | 13 | * @template-implements ObjectRepository 14 | */ 15 | class EntityRepository implements ObjectRepository, Selectable 16 | { 17 | /** 18 | * @var string 19 | * @psalm-supress PropertyNotSetInConstructor 20 | */ 21 | protected $_entityName; 22 | 23 | /** 24 | * @var EntityManagerInterface 25 | * @psalm-supress PropertyNotSetInConstructor 26 | */ 27 | protected $_em; 28 | 29 | /** 30 | * @var Mapping\ClassMetadata 31 | * @psalm-supress PropertyNotSetInConstructor 32 | */ 33 | protected $_class; 34 | 35 | /** @param Mapping\ClassMetadata $class */ 36 | public function __construct(EntityManagerInterface $em, Mapping\ClassMetadata $class) 37 | { 38 | } 39 | 40 | /** 41 | * @param ?int $lockMode 42 | * @param ?int $lockVersion 43 | * 44 | * @return ?T 45 | */ 46 | public function find($id, $lockMode = null, $lockVersion = null) 47 | { 48 | } 49 | 50 | /** @return list */ 51 | public function findAll() 52 | { 53 | } 54 | 55 | /** 56 | * @param ?int $limit 57 | * @param ?int $offset 58 | * 59 | * @return list 60 | */ 61 | public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null) 62 | { 63 | } 64 | 65 | /** @return ?T */ 66 | public function findOneBy(array $criteria, ?array $orderBy = null) 67 | { 68 | } 69 | 70 | /** 71 | * @return Collection 72 | */ 73 | public function matching(Criteria $criteria) 74 | { 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /stubs/Expr.phpstub: -------------------------------------------------------------------------------- 1 | $className 9 | * 10 | * @return ObjectRepository 11 | * 12 | * @template T 13 | */ 14 | public function getRepository(string $className); 15 | 16 | /** 17 | * @param class-string $className 18 | * 19 | * @return Mapping\ClassMetadata 20 | * 21 | * @template T 22 | */ 23 | public function getClassMetadata(string $className); 24 | 25 | /** 26 | * @param class-string $className 27 | * 28 | * @return ?T 29 | * 30 | * @template T 31 | */ 32 | public function find(string $className, $id); 33 | } 34 | -------------------------------------------------------------------------------- /stubs/ObjectRepository.phpstub: -------------------------------------------------------------------------------- 1 | 19 | */ 20 | public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null); 21 | 22 | /** @return ?T */ 23 | public function findOneBy(array $criteria); 24 | } 25 | -------------------------------------------------------------------------------- /stubs/Paginator.phpstub: -------------------------------------------------------------------------------- 1 | 23 | */ 24 | public function getIterator(): \Traversable {} 25 | } 26 | -------------------------------------------------------------------------------- /stubs/ParameterType.phpstub: -------------------------------------------------------------------------------- 1 | 12 | * @template-implements Selectable 13 | */ 14 | class PersistentCollection implements Collection, Selectable 15 | { 16 | /** 17 | * @return bool 18 | * @psalm-mutation-free 19 | */ 20 | public function isEmpty(); 21 | } 22 | -------------------------------------------------------------------------------- /stubs/Query.phpstub: -------------------------------------------------------------------------------- 1 | 17 | * : mixed 18 | * ) 19 | */ 20 | public function getResult($hydrationMode = self::HYDRATE_OBJECT) 21 | { 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /stubs/QueryBuilder.phpstub: -------------------------------------------------------------------------------- 1 | 95 | */ 96 | public function getQuery(): Query 97 | { 98 | } 99 | } 100 | --------------------------------------------------------------------------------