PHP – 最終クラス FormErrorHandler を JWT シリアライザーでオーバーライドできません

プログラミングQA


おはようございます。symfony 2.8 アプリケーションをバージョン 5.4 に完全に移行しました。 私は今、単体テストの段階にいます。

しかし、テストを実行する際に少し問題があります。 私のプロジェクトの古いバージョンでは、オーバーロードされた JWT シリアライザー バンドルの FormErrorHandler クラスを使用していました。 しかし、Symfony のバージョン 5.4 と互換性のあるバンドルの新しいバージョンでは、クラスが final に渡され、オーバーライドできなくなりました。 これを回避する簡単な方法はありますか? 前もって感謝します。

私の古いクラス:

use JMS\Serializer\Context;
use JMS\Serializer\Handler\FormErrorHandler as JMSFormErrorHandler;
use JMS\Serializer\JsonSerializationVisitor;
use JMS\Serializer\VisitorInterface;
use JMS\Serializer\XmlSerializationVisitor;
use Symfony\Component\Form\Form;
use JMS\Serializer\YamlSerializationVisitor;
use Symfony\Component\Form\FormError;
use Symfony\Component\Translation\TranslatorInterface;
use JMS\Serializer\GraphNavigator;

/**
 * Extend the JMS FormErrorHandler to include more informations when using the ViewHandler.
 */
class FormErrorHandler extends JMSFormErrorHandler
{
    /** @var TranslatorInterface */
    private $translator;
    /** @var string */
    private $translationDomain;

    public static function getSubscribingMethods()
    {
        $methods = array();
        foreach (array('xml', 'json', 'yml') as $format) {
            $methods[] = array(
                'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
                'type' => 'Symfony\Component\Form\Form',
                'format' => $format,
            );
            $methods[] = array(
                'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
                'type' => 'Symfony\Component\Form\FormError',
                'format' => $format,
            );
        }

        return $methods;
    }

    public function __construct(TranslatorInterface $translator = null, $translationDomain = 'validators')
    {
        parent::__construct($translator, $translationDomain);
    }

    public function serializeFormToXml(XmlSerializationVisitor $visitor, Form $form, array $type)
    {
        if (null === $visitor->document) {
            $visitor->document = $visitor->createDocument(null, null, false);
            $visitor->document->appendChild($formNode = $visitor->document->createElement('form'));
            $visitor->setCurrentNode($formNode);
        } else {
            $visitor->getCurrentNode()->appendChild(
                $formNode = $visitor->document->createElement('form')
            );
        }

        $formNode->setAttribute('name', $form->getName());

        $formNode->appendChild($errorsNode = $visitor->document->createElement('errors'));
        foreach ($form->getErrors() as $error) {
            $errorNode = $visitor->document->createElement('entry');
            $errorNode->appendChild($this->serializeFormErrorToXml($visitor, $error, array()));
            $errorsNode->appendChild($errorNode);
        }

        foreach ($form->all() as $child) {
            if ($child instanceof Form) {
                if (null !== $node = $this->serializeFormToXml($visitor, $child, array())) {
                    $formNode->appendChild($node);
                }
            }
        }

        return $formNode;
    }

    public function serializeFormToJson(JsonSerializationVisitor $visitor, Form $form, array $type)
    {
        return new \ArrayObject($this->clearEmptyValues($this->convertFormToArray($visitor, $form)));
    }

    public function serializeFormToYml(YamlSerializationVisitor $visitor, Form $form, array $type)
    {
        return new \ArrayObject($this->clearEmptyValues($this->convertFormToArray($visitor, $form)));
    }

    public function serializeFormErrorToXml(XmlSerializationVisitor $visitor, FormError $formError, array $type)
    {
        if (null === $visitor->document) {
            $visitor->document = $visitor->createDocument(null, null, true);
        }

        return $visitor->document->createCDATASection($this->getErrorMessage($formError));
    }

    public function serializeFormErrorToJson(JsonSerializationVisitor $visitor, FormError $formError, array $type)
    {
        return $this->getErrorMessage($formError);
    }

    public function serializeFormErrorToYml(YamlSerializationVisitor $visitor, FormError $formError, array $type)
    {
        return $this->getErrorMessage($formError);
    }

    private function getErrorMessage(FormError $error)
    {

        if ($this->translator === null){
            return $error->getMessage();
        }

        if (null !== $error->getMessagePluralization()) {
            return $this->translator->transChoice($error->getMessageTemplate(), $error->getMessagePluralization(), $error->getMessageParameters(), $this->translationDomain);
        }

        return $this->translator->trans($error->getMessageTemplate(), $error->getMessageParameters(), $this->translationDomain);
    }

    /**
     * @param VisitorInterface $visitor
     * @param Form $data
     * @return array
     */
    private function convertFormToArray(VisitorInterface $visitor, Form $data)
    {
        $isRoot = null === $visitor->getRoot();

        $form = [];
        $errors = array();
        foreach ($data->getErrors() as $error) {
            $errors = $this->getErrorMessage($error);
        }

        if ($errors) {
            $form = $errors;
        }

        $children = array();
        foreach ($data->all() as $child) {
            if ($child instanceof Form && empty($errors)) {
                $children[$child->getName()] = $this->convertFormToArray($visitor, $child);
            } else if (!empty($errors)) {
                $children[$child->getName()] = $errors;
            }
        }

        if ($children) {
            $form = $children;
        }

        if ($isRoot) {
            $visitor->setRoot($form);
        }

        return count($form) > 0 ? $form : null;
    }

    /**
     * Remove fields without errors
     * @param $array
     * @return array
     */
    private function clearEmptyValues($array)
    {
        foreach ($array as $key => &$value) {
            if (is_array($value)) {
                $value = $this->clearEmptyValues($value);
            }
            if (empty($value)) {
                unset($array[$key]);
            }
        }
        return $array;
    }
}

私の古い設定:

# API Form error handler
 jms_serializer.form_error_handler:
    class: WORD\CoreBundle\Serializer\Handler\FormErrorHandler
    arguments:
        - '@translator'
    tags:
        - { name: jms_serializer.subscribing_handler }

final としてマークされた新しい FormErrorHandler :

<?php

declare(strict_types=1);

namespace JMS\Serializer\Handler;

use JMS\Serializer\GraphNavigatorInterface;
use JMS\Serializer\Visitor\SerializationVisitorInterface;
use JMS\Serializer\XmlSerializationVisitor;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Contracts\Translation\TranslatorInterface as TranslatorContract;

use function get_class;

final class FormErrorHandler implements SubscribingHandlerInterface
{
    /**
     * @var TranslatorInterface|null
     */
    private $translator;

    /**
     * @var string
     */
    private $translationDomain;

    /**
     * {@inheritdoc}
     */
    public static function getSubscribingMethods()
    {
        $methods = [];
        foreach (['xml', 'json'] as $format) {
            $methods[] = [
                'direction' => GraphNavigatorInterface::DIRECTION_SERIALIZATION,
                'type' => Form::class,
                'format' => $format,
            ];
            $methods[] = [
                'direction' => GraphNavigatorInterface::DIRECTION_SERIALIZATION,
                'type' => FormInterface::class,
                'format' => $format,
                'method' => 'serializeFormTo' . ucfirst($format),
            ];
            $methods[] = [
                'direction' => GraphNavigatorInterface::DIRECTION_SERIALIZATION,
                'type' => FormError::class,
                'format' => $format,
            ];
        }

        return $methods;
    }

    public function __construct(?object $translator = null, string $translationDomain = 'validators')
    {
        if (null !== $translator && (!$translator instanceof TranslatorInterface && !$translator instanceof TranslatorContract)) {
            throw new \InvalidArgumentException(sprintf(
                'The first argument passed to %s must be instance of %s or %s, %s given',
                self::class,
                TranslatorInterface::class,
                TranslatorContract::class,
                get_class($translator)
            ));
        }

        $this->translator = $translator;
        $this->translationDomain = $translationDomain;
    }

    /**
     * @param array $type
     */
    public function serializeFormToXml(XmlSerializationVisitor $visitor, FormInterface $form, array $type): \DOMElement
    {
        $formNode = $visitor->getDocument()->createElement('form');

        $formNode->setAttribute('name', $form->getName());

        $formNode->appendChild($errorsNode = $visitor->getDocument()->createElement('errors'));
        foreach ($form->getErrors() as $error) {
            $errorNode = $visitor->getDocument()->createElement('entry');
            $errorNode->appendChild($this->serializeFormErrorToXml($visitor, $error, []));
            $errorsNode->appendChild($errorNode);
        }

        foreach ($form->all() as $child) {
            if ($child instanceof Form) {
                if (null !== $node = $this->serializeFormToXml($visitor, $child, [])) {
                    $formNode->appendChild($node);
                }
            }
        }

        return $formNode;
    }

    /**
     * @param array $type
     */
    public function serializeFormToJson(SerializationVisitorInterface $visitor, FormInterface $form, array $type): \ArrayObject
    {
        return $this->convertFormToArray($visitor, $form);
    }

    /**
     * @param array $type
     */
    public function serializeFormErrorToXml(XmlSerializationVisitor $visitor, FormError $formError, array $type): \DOMCdataSection
    {
        return $visitor->getDocument()->createCDATASection($this->getErrorMessage($formError));
    }

    /**
     * @param array $type
     */
    public function serializeFormErrorToJson(SerializationVisitorInterface $visitor, FormError $formError, array $type): string
    {
        return $this->getErrorMessage($formError);
    }

    private function getErrorMessage(FormError $error): ?string
    {
        if (null === $this->translator) {
            return $error->getMessage();
        }

        if (null !== $error->getMessagePluralization()) {
            if ($this->translator instanceof TranslatorContract) {
                return $this->translator->trans($error->getMessageTemplate(), ['%count%' => $error->getMessagePluralization()] + $error->getMessageParameters(), $this->translationDomain);
            } else {
                return $this->translator->transChoice($error->getMessageTemplate(), $error->getMessagePluralization(), $error->getMessageParameters(), $this->translationDomain);
            }
        }

        return $this->translator->trans($error->getMessageTemplate(), $error->getMessageParameters(), $this->translationDomain);
    }

    private function convertFormToArray(SerializationVisitorInterface $visitor, FormInterface $data): \ArrayObject
    {
        $form = new \ArrayObject();
        $errors = [];
        foreach ($data->getErrors() as $error) {
            $errors[] = $this->getErrorMessage($error);
        }

        if ($errors) {
            $form['errors'] = $errors;
        }

        $children = [];
        foreach ($data->all() as $child) {
            if ($child instanceof FormInterface) {
                $children[$child->getName()] = $this->convertFormToArray($visitor, $child);
            }
        }

        if ($children) {
            $form['children'] = $children;
        }

        return $form;
    }
}



Source link

コメント

タイトルとURLをコピーしました