|  | 
| 21 | 21 | use PHPStan\Type\TypeCombinator; | 
| 22 | 22 | use PHPStan\Type\TypehintHelper; | 
| 23 | 23 | use PHPStan\Type\TypeTraverser; | 
|  | 24 | +use PHPStan\Type\TypeUtils; | 
| 24 | 25 | use PHPStan\Type\VerbosityLevel; | 
| 25 | 26 | use Throwable; | 
| 26 | 27 | use function get_class; | 
| @@ -115,25 +116,58 @@ public function processNode(Node $node, Scope $scope): array | 
| 115 | 116 | 
 | 
| 116 | 117 | 		$enumTypeString = $fieldMapping['enumType'] ?? null; | 
| 117 | 118 | 		if ($enumTypeString !== null) { | 
| 118 |  | -			if ($this->reflectionProvider->hasClass($enumTypeString)) { | 
| 119 |  | -				$enumReflection = $this->reflectionProvider->getClass($enumTypeString); | 
| 120 |  | -				$backedEnumType = $enumReflection->getBackedEnumType(); | 
| 121 |  | -				if ($backedEnumType !== null) { | 
| 122 |  | -					if (!$backedEnumType->equals($writableToDatabaseType) || !$backedEnumType->equals($writableToPropertyType)) { | 
| 123 |  | -						$errors[] = RuleErrorBuilder::message(sprintf( | 
| 124 |  | -							'Property %s::$%s type mapping mismatch: backing type %s of enum %s does not match database type %s.', | 
| 125 |  | -							$className, | 
| 126 |  | -							$propertyName, | 
| 127 |  | -							$backedEnumType->describe(VerbosityLevel::typeOnly()), | 
| 128 |  | -							$enumReflection->getDisplayName(), | 
| 129 |  | -							$writableToDatabaseType->describe(VerbosityLevel::typeOnly()) | 
| 130 |  | -						))->identifier('doctrine.enumType')->build(); | 
|  | 119 | +			if ($writableToDatabaseType->isArray()->no() && $writableToPropertyType->isArray()->no()) { | 
|  | 120 | +				if ($this->reflectionProvider->hasClass($enumTypeString)) { | 
|  | 121 | +					$enumReflection = $this->reflectionProvider->getClass($enumTypeString); | 
|  | 122 | +					$backedEnumType = $enumReflection->getBackedEnumType(); | 
|  | 123 | +					if ($backedEnumType !== null) { | 
|  | 124 | +						if (!$backedEnumType->equals($writableToDatabaseType) || !$backedEnumType->equals($writableToPropertyType)) { | 
|  | 125 | +							$errors[] = RuleErrorBuilder::message(sprintf( | 
|  | 126 | +								'Property %s::$%s type mapping mismatch: backing type %s of enum %s does not match database type %s.', | 
|  | 127 | +								$className, | 
|  | 128 | +								$propertyName, | 
|  | 129 | +								$backedEnumType->describe(VerbosityLevel::typeOnly()), | 
|  | 130 | +								$enumReflection->getDisplayName(), | 
|  | 131 | +								$writableToDatabaseType->describe(VerbosityLevel::typeOnly()) | 
|  | 132 | +							))->identifier('doctrine.enumType')->build(); | 
|  | 133 | +						} | 
| 131 | 134 | 					} | 
| 132 | 135 | 				} | 
|  | 136 | +				$enumType = new ObjectType($enumTypeString); | 
|  | 137 | +				$writableToPropertyType = $enumType; | 
|  | 138 | +				$writableToDatabaseType = $enumType; | 
|  | 139 | +			} else { | 
|  | 140 | +				$enumType = new ObjectType($enumTypeString); | 
|  | 141 | +				if ($this->reflectionProvider->hasClass($enumTypeString)) { | 
|  | 142 | +					$enumReflection = $this->reflectionProvider->getClass($enumTypeString); | 
|  | 143 | +					$backedEnumType = $enumReflection->getBackedEnumType(); | 
|  | 144 | +					if ($backedEnumType !== null) { | 
|  | 145 | +						if (!$backedEnumType->equals($writableToDatabaseType->getIterableValueType()) || !$backedEnumType->equals($writableToPropertyType->getIterableValueType())) { | 
|  | 146 | +							$errors[] = RuleErrorBuilder::message( | 
|  | 147 | +								sprintf( | 
|  | 148 | +									'Property %s::$%s type mapping mismatch: backing type %s of enum %s does not match value type %s of the database type %s.', | 
|  | 149 | +									$className, | 
|  | 150 | +									$propertyName, | 
|  | 151 | +									$backedEnumType->describe(VerbosityLevel::typeOnly()), | 
|  | 152 | +									$enumReflection->getDisplayName(), | 
|  | 153 | +									$writableToDatabaseType->getIterableValueType()->describe(VerbosityLevel::typeOnly()), | 
|  | 154 | +									$writableToDatabaseType->describe(VerbosityLevel::typeOnly()) | 
|  | 155 | +								) | 
|  | 156 | +							)->identifier('doctrine.enumType')->build(); | 
|  | 157 | +						} | 
|  | 158 | +					} | 
|  | 159 | +				} | 
|  | 160 | + | 
|  | 161 | +				$writableToPropertyType = TypeCombinator::intersect(new ArrayType( | 
|  | 162 | +					$writableToPropertyType->getIterableKeyType(), | 
|  | 163 | +					$enumType | 
|  | 164 | +				), ...TypeUtils::getAccessoryTypes($writableToPropertyType)); | 
|  | 165 | +				$writableToDatabaseType = TypeCombinator::intersect(new ArrayType( | 
|  | 166 | +					$writableToDatabaseType->getIterableKeyType(), | 
|  | 167 | +					$enumType | 
|  | 168 | +				), ...TypeUtils::getAccessoryTypes($writableToDatabaseType)); | 
|  | 169 | + | 
| 133 | 170 | 			} | 
| 134 |  | -			$enumType = new ObjectType($enumTypeString); | 
| 135 |  | -			$writableToPropertyType = $enumType; | 
| 136 |  | -			$writableToDatabaseType = $enumType; | 
| 137 | 171 | 		} | 
| 138 | 172 | 
 | 
| 139 | 173 | 		$identifiers = []; | 
|  | 
0 commit comments