Symfony FosUserBundle 和 HTMLPurifierBundle

Symfony FosUserBundle and HTMLPurifierBundle

在我的个人 Symfony3.2 项目中,我想在我的 UserProfile 表单中使用 HtmlPurifier 以防止 XSS 攻击。

因此如中所述:https://github.com/Exercise/HTMLPurifierBundle我修改了UserProfileFormType

namespace AppUserBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;

class UserProfileFormType extends AbstractType
{
    private $purifierTransformer;

    public function __construct(DataTransformerInterface $purifierTransformer)
    {
        $this->purifierTransformer = $purifierTransformer;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        parent::buildForm($builder, $options);        

        $builder->addViewTransformer($this->purifierTransformer);
        $builder->add('name',TextType::class,array('label'=>'profile.first_name','required' => false));
        $builder->add('surname',TextType::class,array('label'=>'profile.surnname','required' => false));
        $builder->remove('username');
        $builder->add('username',TextType::class,['required' => false]);
        $builder->add('email',TextType::class,['required' => false]);
        $builder->add('description',TextareaType::class,['required' => false]);
        $builder->remove('current_password');
    }

    public function getParent()
    {
        return 'FOS\UserBundle\Form\Type\ProfileFormType';
    }

    public function getBlockPrefix()
    {
        return 'app_user_profile';
    }

    // For Symfony 2.x
    public function getName()
    {
        return $this->getBlockPrefix();
    }
}

并且还在 services.yml 个条目中使用了这些条目:

services:
  app_user.html_purifier:
    class: Exercise\HTMLPurifierBundle\Form\HTMLPurifierTransformer
    arguments: ["@exercise_html_purifier.default"]

  app_user.user_profile_form:
    class: AppUserBundle\Form\Type\UserProfileFormType
    arguments: ["@app_user.html_purifier"]
    tags:
      - { name: form.type, alias: app_user_profile }

我也把这些条目放在 config.yml:

fos_user:
  db_driver: orm # other valid values are 'mongodb' and 'couchdb'
  firewall_name: main
  user_class: '%user_class%'
  from_email:
    address: "somemail@example.com"
    sender_name: "App Mailer"
  registration:
    confirmation:
      enabled: false
  profile:
    form:
      type: AppUserBundle\Form\Type\UserProfileFormType

exercise_html_purifier:
  default:
    Cache.SerializerPath: '%kernel.cache_dir%/htmlpurifier'

使用这些选项,我收到以下错误消息:

Type error: Argument 1 passed to AppUserBundle\Form\Type\UserProfileFormType::__construct() must be an instance of Symfony\Component\Form\DataTransformerInterface, none given, called in /home/pcmagas/Kwdikas/php/apps/symfonyAdminLTE/vendor/symfony/symfony/src/Symfony/Component/Form/FormRegistry.php on line 85

我还尝试更改 src/AppUserBundle/Resources/config.yml 中的以下值:

fos_user:
   #Some configuration
  profile:
    form:
      type: AppUserBundle\Form\Type\UserProfileFormType

有了这个:

fos_user #一些配置 轮廓: 形式: 输入:app_user.user_profile_form

即returns以下错误:

Could not load type "app_user.user_profile_form"

你知道我将如何解决这个问题吗?只要我了解问题是 FosUserBundle 无法以某种方式加载正确的服务。您知道我将如何告诉您将适当的服务加载到配置中吗?

编辑 1:

UserProfileFormType 方法中我替换了:

$builder->add('description',TextareaType::class,['required' => false]);

与:

$builder->add('description',PurifiedTextAreaType::class,['required' => false]);

我收到以下错误:

Type error: Argument 1 passed to AppUserBundle\Form\Type\PurifiedTextAreaType::__construct() must implement interface Symfony\Component\Form\DataTransformerInterface, none given, called in /home/pcmagas/Kwdikas/php/apps/symfonyAdminLTE/var/cache/dev/appDevDebugProjectContainer.php on line 389

请记住我创建了 AppUserBundle/Form/Type/PurifiedTextAreaType.php:

namespace AppUserBundle\Form\Type;


use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class PurifiedTextAreaType extends AbstractType
{
    private $purifierTransformer;

    public function __construct(DataTransformerInterface $purifierTransformer)
    {
        $this->purifierTransformer = $purifierTransformer;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addViewTransformer($this->purifierTransformer);
    }

    public function getParent()
    {
        return 'textarea';
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
                'compound' => false,
        ));
    }

    public function getName()
    {
        return 'purified_textarea';
    }
}

我还忘了提到我使用不同的包来进行任何类型的用户管理和处理名为 AppUserBudnle 所有自定义表单都在这个包中。

我认为,使用此扩展的最佳方法是如教程中所述,使用一个 Textarea,您可以在最终形式中将其调用为您自己的 TextAreaType:

我在你的描述中看到了这个错误,有命名空间但是 "UserProfileFormType" class 名称丢失了。

services:
  app_user.user_profile_form:
    class: AppUserBundle\Form\Type
    arguments: ["@app_user.html_purifier"]
    tags:
      - { name: form.type, alias: app_user_profile }

在此配置中

fos_user:
  db_driver: orm # other valid values are 'mongodb' and 'couchdb'
  firewall_name: main
  user_class: '%user_class%'
  from_email:
    address: "somemail@example.com"
    sender_name: "App Mailer"
  registration:
    confirmation:
      enabled: false
  profile:
    form:
      type: AppUserBundle\Form\Type\UserProfileFormType

您必须覆盖个人资料表单类型,然后按名称而不是 class 名称调用它(这可能会在不带参数的情况下构造您的表单):

看看那里:http://symfony.com/doc/current/bundles/FOSUserBundle/overriding_forms.html#overriding-a-form-type

正如最后 Manuel DUVERNON 所说,我创建了这个表示 HtmlPurified TextArea 的 FormType:

namespace AppUserBundle\Form\Type;


use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Exercise\HTMLPurifierBundle\Form\HTMLPurifierTransformer;
use HTMLPurifier;

class PurifiedTextAreaType extends AbstractType
{
    private $purifierTransformer;

    /**
     * I Do not Dependency Inject the HtmlPurifier because I want to Use it as
     * FormType in FosUserBundle's extended forms in the wat that is described in: 
     * https://symfony.com/doc/master/bundles/FOSUserBundle/overriding_forms.html
     * 
     * And the method described above does not favour Dependency Injection.
     */
    public function __construct()
    {
        $this->purifierTransformer = new HTMLPurifierTransformer(new \HTMLPurifier());
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addViewTransformer($this->purifierTransformer);
    }

    public function getParent()
    {
        return 'Symfony\Component\Form\Extension\Core\Type\TextareaType';
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
                'compound' => false,
        ));
    }

    public function getName()
    {
        return 'purified_textarea';
    }
}

请记住不要通过依赖注入加载 HTMLPurifierTransformer,因为 FosUserBundle 的 FormBuilder 无法通过依赖注入加载扩展表单。还要记住使用要扩展的 FormType 的命名空间(在我的例子中是 Symfony\Component\Form\Extension\Core\Type\TextareaType),因为 FormBuilder 也有对特定接口的限制。