How to Add WYSIWYG Field 

There are two ways to add a WYSIWYG field - via the Entity Management UI and programmatically.

Add a WYSIWYG Field via Entity Management UI 

To add a WYSIWYG field via the Entity Management UI:

  1. Create an extended entity field of the WYSIWYG type.

  2. The system manages the WYSIWYG fields similarly to all other extended fields, considering the Show on Form and Show on View entity field config options.

For example, if you add a WYSIWYG field called teaser to an entity, the system automatically creates the teaser_style and teaser_properties fields. Entity getters and setters of these fields will be getTeaserStyle/setTeaserStyle and getTeaserProperties/setTeaserProperties correspondingly.

Add a WYSIWYG Field Programmatically 

You can add a WYSIWYG field programmatically in two ways:

  1. As an extended field if the target entity class cannot be modified. Use the option if you add the field to the default Oro entity or any other entity provided by a vendor.

  2. Explicitly if the target entity class can be modified. Use the option if you want to create and manage the WYSIWYG field, and have a total control over its validation and representation.

Add a WYSIWYG Field as Extended Field 

In terms of the final outcome, this way is similar to adding a field via the entity management UI, as the system is responsible for the WYSIWYG field management, its validation, and representation.

To add a WYSIWYG field as an extended field:

  1. Create a migration that adds 3 columns of the following types: wysiwyg, wysiwyg_style, and wysiwyg_properties.

 1<?php
 2
 3namespace Acme\Bundle\WysiwygBundle\Migrations\Schema\v1_1;
 4
 5use Doctrine\DBAL\Schema\Schema;
 6use Oro\Bundle\EntityConfigBundle\Entity\ConfigModel;
 7use Oro\Bundle\EntityExtendBundle\EntityConfig\ExtendScope;
 8use Oro\Bundle\EntityExtendBundle\Migration\ExtendOptionsManager;
 9use Oro\Bundle\EntityExtendBundle\Migration\OroOptions;
10use Oro\Bundle\MigrationBundle\Migration\Migration;
11use Oro\Bundle\MigrationBundle\Migration\QueryBag;
12
13class AddTeaserField implements Migration
14{
15    /**
16     * {@inheritdoc}
17     */
18    public function up(Schema $schema, QueryBag $queries): void
19    {
20        if (!$schema->hasTable('acme_blog_post')) {
21            return;
22        }
23
24        $table = $schema->getTable('acme_blog_post');
25        if ($table->hasColumn('teaser')) {
26            return;
27        }
28
29        $table->addColumn('teaser', 'wysiwyg', [
30            'notnull' => false,
31            'comment' => '(DC2Type:wysiwyg)',
32            OroOptions::KEY => [
33                'extend' => ['is_extend' => true, 'owner' => ExtendScope::OWNER_CUSTOM],
34                'entity' => ['label' => 'acme.wysiwyg.blogpost.teaser.label'],
35            ],
36        ]);
37        $table->addColumn(
38            'teaser_style',
39            'wysiwyg_style',
40            [
41                'notnull' => false,
42                OroOptions::KEY => [
43                    ExtendOptionsManager::MODE_OPTION => ConfigModel::MODE_HIDDEN,
44                    'extend' => ['is_extend' => true, 'owner' => ExtendScope::OWNER_CUSTOM],
45                ],
46            ]
47        );
48        $table->addColumn(
49            'teaser_properties',
50            'wysiwyg_properties',
51            [
52                'notnull' => false,
53                OroOptions::KEY => [
54                    ExtendOptionsManager::MODE_OPTION => ConfigModel::MODE_HIDDEN,
55                    'extend' => ['is_extend' => true, 'owner' => ExtendScope::OWNER_CUSTOM],
56                ],
57            ]
58        );
59    }
60}

2. Entity getters and setters are generated automatically: getTeaser/setTeaser, getTeaserStyle/setTeaserStyle, getTeaserProperties/setTeaserProperties.

Note

You can add an extended field to the Product entity as a product attribute during the schema migration. For that, set the attribute.is_attribute entity field config option to true in the Oro options of the field column.

Add a WYSIWYG Field Explicitly 

To add a WYSIWYG field explicitly:

  1. Create a migration that adds 3 columns of the following types: wysiwyg, wysiwyg_style, and wysiwyg_properties:

 1<?php
 2
 3namespace Acme\Bundle\WysiwygBundle\Migrations\Schema\v1_1;
 4
 5use Doctrine\DBAL\Schema\Schema;
 6use Oro\Bundle\MigrationBundle\Migration\Migration;
 7use Oro\Bundle\MigrationBundle\Migration\QueryBag;
 8
 9class AddExtraContentField implements Migration
10{
11    public function up(Schema $schema, QueryBag $queries): void
12    {
13        if (!$schema->hasTable('acme_blog_post')) {
14            return;
15        }
16
17        $table = $schema->getTable('acme_blog_post');
18        if ($table->hasColumn('extra_content')) {
19            return;
20        }
21
22        $table->addColumn('extra_content', 'wysiwyg', ['notnull' => false, 'comment' => '(DC2Type:wysiwyg)']);
23        $table->addColumn('extra_content_style', 'wysiwyg_style', ['notnull' => false]);
24        $table->addColumn('extra_content_properties', 'wysiwyg_properties', ['notnull' => false]);
25    }
26}
  1. Add the corresponding properties, getters, and setters to the target entity class:

src/Acme/WysiwygBundle/Entity/BlogPost.php 
class BlogPost implements DatesAwareInterface, ExtendEntityInterface
{
    // ...

    #[ORM\Column(name: 'extra_content', type: 'wysiwyg', nullable: true)]
    #[ConfigField(defaultValues: ['attachment' => ['acl_protected' => false]])]
    protected $extraContent;

    #[ORM\Column(name: 'extra_content_style', type: 'wysiwyg_style', nullable: true)]
    #[ConfigField(defaultValues: ['attachment' => ['acl_protected' => false]])]
    protected $extraContentStyle;

    #[ORM\Column(name: 'extra_content_properties', type: 'wysiwyg_properties', nullable: true)]
    protected $extraContentProperties;

    public function getExtraContent(): ?string
    {
        return $this->extraContent;
    }

    public function setExtraContent(?string $extraContent): self
    {
        $this->extraContent = $extraContent;

        return $this;
    }

    public function getExtraContentStyle(): ?string
    {
        return $this->extraContentStyle;
    }

    public function setExtraContentStyle(?string $extraContentStyle): self
    {
        $this->extraContentStyle = $extraContentStyle;

        return $this;
    }

    public function getExtraContentProperties(): ?array
    {
        return $this->extraContentProperties;
    }

    public function setExtraContentProperties(?array $extraContentProperties): self
    {
        $this->extraContentProperties = $extraContentProperties;

        return $this;
    }

    // ...
}

Note

The entity field config attachment.acl_protected is set to false to disable ACL for the images and files uploaded to the WYSIWYG field to make them publicly accessible.

  1. Declare validation constraints:

src/Acme/WysiwygBundle/Resources/config/validation.yml 
Acme\Bundle\WysiwygBundle\Entity\BlogPost:
    properties:
        # ...

        extraContent:
            - Oro\Bundle\CMSBundle\Validator\Constraints\TwigContent: ~
            - Oro\Bundle\CMSBundle\Validator\Constraints\WYSIWYG: ~
        extraContentStyle:
            - Oro\Bundle\CMSBundle\Validator\Constraints\TwigContent: ~
            - Oro\Bundle\CMSBundle\Validator\Constraints\WYSIWYG: ~

        # ...

For more details on the WYSIWYG field representation, refer to the How to Display a WYSIWYG Field topic.