Repository: symfony/symfony
File: src/Symfony/Component/Validator/Constraint.php (PHP)

Code before:
     * Checks whether the child class constructor has named parameters for each
     * required option, meaning it handles their validation itself.
     */
    private function areRequiredOptionsHandledByChildConstructor(): bool
    {
        $constructor = new \ReflectionMethod($this, '__construct');

        if (self::class === $constructor->getDeclaringClass()->getName()) {
            return false;
        }

        $requiredOptionsMethod = new \ReflectionMethod($this, 'getRequiredOptions');

        if (self::class === $requiredOptionsMethod->getDeclaringClass()->getName()) {
            return true;
        }

        $requiredOptions = $this->getRequiredOptions(false);

        if (!$requiredOptions) {
            return true;
        }

        $paramNames = [];
        foreach ($constructor->getParameters() as $param) {
            $paramNames[$param->getName()] = true;
        }

        foreach ($requiredOptions as $option) {
            if (!isset($paramNames[$option])) {
                return false;
            }
        }

        return true;
    }

    /**
     * @deprecated since Symfony 7.4
     *
     * @return array<string, mixed>
     */
    protected function normalizeOptions(mixed $options): array
    {
        $normalizedOptions = [];
        $defaultOption = $this->getDefaultOption(false);
        $invalidOptions = [];
        $missingOptions = array_flip($this->getRequiredOptions(false));
        $knownOptions = get_class_vars(static::class);

        if (\is_array($options) && isset($options['value']) && !property_exists($this, 'value')) {

Review comment (suggestion):
```suggestion
            $paramNames[$param->name] = true;
```

Code after:
     * @deprecated since Symfony 7.4
     *
     * @return array<string, mixed>
     */
    protected function normalizeOptions(mixed $options): array
    {
        $normalizedOptions = [];
        $defaultOption = $this->getDefaultOption(false);
        $invalidOptions = [];
        $missingOptions = array_flip($this->getRequiredOptions(false));
        $knownOptions = get_class_vars(static::class);

        if (\is_array($options) && isset($options['value']) && !property_exists($this, 'value')) {
            if (null === $defaultOption) {
                throw new ConstraintDefinitionException(\sprintf('No default option is configured for constraint "%s".', static::class));
            }

            $options[$defaultOption] = $options['value'];
            unset($options['value']);
        }

        if (\is_array($options)) {
            reset($options);
        }
        if ($options && \is_array($options) && \is_string(key($options))) {
            foreach ($options as $option => $value) {
                if (\array_key_exists($option, $knownOptions)) {
                    $normalizedOptions[$option] = $value;
                    unset($missingOptions[$option]);
                } else {
                    $invalidOptions[] = $option;
                }
            }
        } elseif (null !== $options && !(\is_array($options) && 0 === \count($options))) {
            if (null === $defaultOption) {
                throw new ConstraintDefinitionException(\sprintf('No default option is configured for constraint "%s".', static::class));
            }

            if (\array_key_exists($defaultOption, $knownOptions)) {
                $normalizedOptions[$defaultOption] = $options;
                unset($missingOptions[$defaultOption]);
            } else {
                $invalidOptions[] = $defaultOption;
            }
        }

        if (\count($invalidOptions) > 0) {
            throw new InvalidOptionsException(\sprintf('The options "%s" do not exist in constraint "%s".', implode('", "', $invalidOptions), static::class), $invalidOptions);
        }

        if (\count($missingOptions) > 0) {