Подключение WYSWYG редактора в SYMFONY (SONATA ADMIN BUNDLE)

Привет, посвящает тем кто хочеть подключить редактор WYSWYG в Сонату Админ Бандл (SONATA ADMIN BUNDLE)

  1. подключаем редаткор TINYCME (инструкция)
php composer.phar require stfalcon/tinymce-bundle='2.0'

Прописываем в кернеле

// app/AppKernel.php
<?php
    // ...
    public function registerBundles()
    {
        $bundles = array(
            // ...
            new Stfalcon\Bundle\TinymceBundle\StfalconTinymceBundle(),
        );
    }
php app/console assets:install web/

Прописываем конфиг симфони для редактора

config.yml

stfalcon_tinymce:
        include_jquery: true
        tinymce_jquery: true
        selector: ".tinymce"
        language: %locale%
        theme:
            simple:
                theme: "modern"

Теперь что бы подключить редактор, надо подключить его в темлейте. Надо перезаписать теплейт

config.yml

sonata_admin:
    templates:
        edit:       base_edit.html.twig
        layout:     standard_layout.html.twig

берем изначальный файл из  ./vendor/sonata-project/admin-bundle/Resources/views/CRUD/base_edit.html.twig

и кладем в

./app/Resources/views/base_edit.html.twig

То же самое касается темлейта

standard_layout.html.twig

Теперь в самом файле добавляем строку включения редаткора

{{ tinymce_init() }}

Получится так:

{#

This file is part of the Sonata package.

(c) Thomas Rabaix <thomas.rabaix@sonata-project.org>

For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.

#}
{% set _preview              = block('preview') is defined ? block('preview') : null %}
{% set _form                 = block('form') is defined ? block('form') : null %}
{% set _show                 = block('show') is defined ? block('show') : null %}
{% set _list_table           = block('list_table') is defined ? block('list_table') : null %}
{% set _list_filters         = block('list_filters') is defined ? block('list_filters') : null %}
{% set _tab_menu             = block('tab_menu') is defined ? block('tab_menu') : null %}
{% set _content              = block('content') is defined ? block('content') : null %}
{% set _title                = block('title') is defined ? block('title') : null %}
{% set _breadcrumb           = block('breadcrumb') is defined ? block('breadcrumb') : null %}
{% set _actions              = block('actions') is defined ? block('actions') : null %}
{% set _navbar_title         = block('navbar_title') is defined ? block('navbar_title') : null %}
{% set _list_filters_actions = block('list_filters_actions') is defined ? block('list_filters_actions') : null %}

<!DOCTYPE html>
<html {% block html_attributes %}class="no-js"{% endblock %}>
    <head>
        {% block meta_tags %}
            <meta http-equiv="X-UA-Compatible" content="IE=edge">
            <meta charset="UTF-8">
            <meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
        {% endblock %}

        {% block stylesheets %}
            {% for stylesheet in sonata_admin.adminPool.getOption('stylesheets', []) %}
                    <link rel="stylesheet" href="{{ asset(stylesheet) }}">
            {% endfor %}
        {% endblock %}

        {% block javascripts %}
            {{ tinymce_init() }}
            {% block sonata_javascript_config %}
                <script>
                    window.SONATA_CONFIG = {
                        CONFIRM_EXIT: {% if sonata_admin.adminPool.getOption('confirm_exit') %}true{% else %}false{% endif %},
                        USE_SELECT2: {% if sonata_admin.adminPool.getOption('use_select2') %}true{% else %}false{% endif %},
                        USE_ICHECK: {% if sonata_admin.adminPool.getOption('use_icheck') %}true{% else %}false{% endif %},
                        USE_STICKYFORMS: {% if sonata_admin.adminPool.getOption('use_stickyforms') %}true{% else %}false{% endif %}
                    };
                    window.SONATA_TRANSLATIONS = {
                        CONFIRM_EXIT:  '{{ 'confirm_exit'|trans({}, 'SonataAdminBundle')|escape('js') }}'
                    };

                    // http://getbootstrap.com/getting-started/#support-ie10-width
                    if (navigator.userAgent.match(/IEMobile\/10\.0/)) {
                        var msViewportStyle = document.createElement('style');
                        msViewportStyle.appendChild(document.createTextNode('@-ms-viewport{width:auto!important}'));
                        document.querySelector('head').appendChild(msViewportStyle);
                    }
                </script>
            {% endblock %}

            {% block sonata_javascript_pool %}
                {% for javascript in sonata_admin.adminPool.getOption('javascripts', []) %}
                    <script src="{{ asset(javascript) }}"></script>
                {% endfor %}
            {% endblock %}

            {% set locale = app.request.locale %}
            {# localize moment #}
            {% if locale[:2] != 'en' %}
                <script src="{{ asset('bundles/sonatacore/vendor/moment/locale/' ~ locale|replace({'_':'-'}) ~ '.js') }}"></script>
            {% endif %}

            {# localize select2 #}
            {% if sonata_admin.adminPool.getOption('use_select2') %}
                {% if locale == 'pt' %}{% set locale = 'pt_PT' %}{% endif %}

                {# omit default EN locale #}
                {% if locale[:2] != 'en' %}
                    <script src="{{ asset('bundles/sonatacore/vendor/select2/select2_locale_' ~ locale|replace({'_':'-'}) ~ '.js') }}"></script>
                {% endif %}
            {% endif %}
        {% endblock %}

        <title>
        {% block sonata_head_title %}
            {{ 'Admin'|trans({}, 'SonataAdminBundle') }}

            {% if _title is not empty %}
                {{ _title|raw }}
            {% else %}
                {% if action is defined %}
                    -
                    {% for menu in breadcrumbs_builder.breadcrumbs(admin, action) %}
                        {% if not loop.first %}
                            {%  if loop.index != 2 %}
                                &gt;
                            {% endif %}

                            {%- set translation_domain = menu.extra('translation_domain', 'messages') -%}
                            {%- set label = menu.label -%}
                            {%- if translation_domain is not same as(false) -%}
                                {%- set label = label|trans(menu.extra('translation_params', {}), translation_domain) -%}
                            {%- endif -%}

                            {{ label }}
                        {% endif %}
                    {% endfor %}
                {% endif %}
            {% endif%}
        {% endblock %}
        </title>
    </head>
    <body {% block body_attributes %}class="sonata-bc skin-black fixed"{% endblock %}>

    <div class="wrapper">

        {% block sonata_header %}
            <header class="main-header">
                {% block sonata_header_noscript_warning %}
                    <noscript>
                        <div class="noscript-warning">
                            {{ 'noscript_warning'|trans({}, 'SonataAdminBundle') }}
                        </div>
                    </noscript>
                {% endblock %}
                {% block logo %}
                    {% spaceless %}
                        <a class="logo" href="{{ path('sonata_admin_dashboard') }}">
                            {% if 'single_image' == sonata_admin.adminPool.getOption('title_mode') or 'both' == sonata_admin.adminPool.getOption('title_mode') %}
                                <img src="{{ asset(sonata_admin.adminPool.titlelogo) }}" alt="{{ sonata_admin.adminPool.title }}">
                            {% endif %}
                            {% if 'single_text' == sonata_admin.adminPool.getOption('title_mode') or 'both' == sonata_admin.adminPool.getOption('title_mode') %}
                                <span>{{ sonata_admin.adminPool.title }}</span>
                            {% endif %}
                        </a>
                    {% endspaceless %}
                {% endblock %}
                {% block sonata_nav %}
                    <nav class="navbar navbar-static-top" role="navigation">
                        <a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button">
                            <span class="sr-only">Toggle navigation</span>
                        </a>

                        <div class="navbar-left">
                            {% block sonata_breadcrumb %}
                                <div class="hidden-xs">
                                    {% if _breadcrumb is not empty or action is defined %}
                                        <ol class="nav navbar-top-links breadcrumb">
                                            {% if _breadcrumb is empty %}
                                                {% if action is defined %}
                                                    {% for menu in breadcrumbs_builder.breadcrumbs(admin, action) %}
                                                        {%- set translation_domain = menu.extra('translation_domain', 'messages') -%}
                                                        {%- set label = menu.label -%}
                                                        {%- if translation_domain is not same as(false) -%}
                                                            {%- set label = label|trans(menu.extra('translation_params', {}), translation_domain) -%}
                                                        {%- endif -%}

                                                        {% if not loop.last  %}
                                                            <li>
                                                                {% if menu.uri is not empty %}
                                                                    <a href="{{ menu.uri }}">
                                                                        {% if menu.extra('safe_label', true) %}
                                                                            {{- label|raw -}}
                                                                        {% else %}
                                                                            {{- label -}}
                                                                        {% endif %}
                                                                    </a>
                                                                {% else %}
                                                                    {{ label }}
                                                                {% endif %}
                                                            </li>
                                                        {% else %}
                                                            <li class="active"><span>{{ label }}</span></li>
                                                        {% endif %}
                                                    {% endfor %}
                                                {% endif %}
                                            {% else %}
                                                {{ _breadcrumb|raw }}
                                            {% endif %}
                                        </ol>
                                    {% endif %}
                                </div>
                            {% endblock sonata_breadcrumb %}
                        </div>

                        {% block sonata_top_nav_menu %}
                            {% if app.user and is_granted('ROLE_SONATA_ADMIN') %}
                                <div class="navbar-custom-menu">
                                    <ul class="nav navbar-nav">
                                        {% block sonata_top_nav_menu_add_block %}
                                            <li class="dropdown">
                                                <a class="dropdown-toggle" data-toggle="dropdown" href="#">
                                                    <i class="fa fa-plus-square fa-fw" aria-hidden="true"></i> <i class="fa fa-caret-down" aria-hidden="true"></i>
                                                </a>
                                                {% include sonata_admin.adminPool.getTemplate('add_block') %}
                                            </li>
                                        {% endblock %}
                                        {% block sonata_top_nav_menu_user_block %}
                                            <li class="dropdown user-menu">
                                                <a class="dropdown-toggle" data-toggle="dropdown" href="#">
                                                    <i class="fa fa-user fa-fw" aria-hidden="true"></i> <i class="fa fa-caret-down" aria-hidden="true"></i>
                                                </a>
                                                <ul class="dropdown-menu dropdown-user">
                                                    {% include sonata_admin.adminPool.getTemplate('user_block') %}
                                                </ul>
                                            </li>
                                        {% endblock %}
                                    </ul>
                                </div>
                            {% endif %}
                        {% endblock %}
                    </nav>
                {% endblock sonata_nav %}
            </header>
        {% endblock sonata_header %}

        {% block sonata_wrapper %}
            {% block sonata_left_side %}
                <aside class="main-sidebar">
                    <section class="sidebar">
                        {% block sonata_side_nav %}
                            {% block sonata_sidebar_search %}
                                <form action="{{ path('sonata_admin_search') }}" method="GET" class="sidebar-form" role="search">
                                    <div class="input-group custom-search-form">
                                        <input type="text" name="q" value="{{ app.request.get('q') }}" class="form-control" placeholder="{{ 'search_placeholder'|trans({}, 'SonataAdminBundle') }}">
                                            <span class="input-group-btn">
                                                <button class="btn btn-flat" type="submit">
                                                    <i class="fa fa-search" aria-hidden="true"></i>
                                                </button>
                                            </span>
                                    </div>
                                </form>
                            {% endblock sonata_sidebar_search %}

                            {% block side_bar_before_nav %} {% endblock %}
                            {% block side_bar_nav %}
                                {{ knp_menu_render('sonata_admin_sidebar', {template: sonata_admin.adminPool.getTemplate('knp_menu_template')}) }}
                            {% endblock side_bar_nav %}
                            {% block side_bar_after_nav %}
                                <p class="text-center small" style="border-top: 1px solid #444444; padding-top: 10px">
                                    {% block side_bar_after_nav_content %}
                                        <a href="https://sonata-project.org" rel="noreferrer" target="_blank">sonata project</a>
                                    {% endblock %}
                                </p>
                            {% endblock %}
                        {% endblock sonata_side_nav %}
                    </section>
                </aside>
            {% endblock sonata_left_side %}

            <div class="content-wrapper">
                {% block sonata_page_content %}
                    <section class="content-header">

                        {% block sonata_page_content_header %}
                            {% block sonata_page_content_nav %}
                                {% if _tab_menu is not empty or _actions is not empty or _list_filters_actions is not empty %}
                                    <nav class="navbar navbar-default" role="navigation">
                                        <div class="container-fluid">
                                            {% block tab_menu_navbar_header %}
                                                {% if _navbar_title is not empty %}
                                                    <div class="navbar-header">
                                                        <a class="navbar-brand" href="#">{{ _navbar_title|raw }}</a>
                                                    </div>
                                                {% endif %}
                                            {% endblock %}

                                            <div class="navbar-collapse">
                                                <div class="navbar-left">
                                                    {% if _tab_menu is not empty %}
                                                        {{ _tab_menu|raw }}
                                                    {% endif %}
                                                </div>

                                                {% if admin is defined and action is defined and action == 'list' and admin.listModes|length > 1 %}
                                                    <div class="nav navbar-right btn-group">
                                                        {% for mode, settings in admin.listModes %}
                                                            <a href="{{ admin.generateUrl('list', app.request.query.all|merge({_list_mode: mode})) }}" class="btn btn-default navbar-btn btn-sm{% if admin.getListMode() == mode %} active{% endif %}"><i class="{{ settings.class }}"></i></a>
                                                        {% endfor %}
                                                    </div>
                                                {% endif %}

                                                {% block sonata_admin_content_actions_wrappers %}
                                                    {% if _actions|replace({ '<li>': '', '</li>': '' })|trim is not empty %}
                                                        <ul class="nav navbar-nav navbar-right">
                                                        {% if _actions|split('</a>')|length > 2 %}
                                                            <li class="dropdown sonata-actions">
                                                                <a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ 'link_actions'|trans({}, 'SonataAdminBundle') }} <b class="caret"></b></a>
                                                                <ul class="dropdown-menu" role="menu">
                                                                    {{ _actions|raw }}
                                                                </ul>
                                                            </li>
                                                        {% else %}
                                                            {{ _actions|raw }}
                                                        {% endif %}
                                                        </ul>
                                                    {% endif %}
                                                {% endblock sonata_admin_content_actions_wrappers %}

                                                {% if _list_filters_actions is not empty %}
                                                    {{ _list_filters_actions|raw }}
                                                {% endif %}
                                            </div>
                                        </div>
                                    </nav>
                                {% endif %}
                            {% endblock sonata_page_content_nav %}
                        {% endblock sonata_page_content_header %}
                    </section>

                    <section class="content">
                        {% block sonata_admin_content %}

                            {% block notice %}
                                {% include 'SonataCoreBundle:FlashMessage:render.html.twig' %}
                            {% endblock notice %}

                            {% if _preview is not empty %}
                                <div class="sonata-ba-preview">{{ _preview|raw }}</div>
                            {% endif %}

                            {% if _content is not empty %}
                                <div class="sonata-ba-content">{{ _content|raw }}</div>
                            {% endif %}

                            {% if _show is not empty %}
                                <div class="sonata-ba-show">{{ _show|raw }}</div>
                            {% endif %}

                            {% if _form is not empty %}
                                <div class="sonata-ba-form">{{ _form|raw }}</div>
                            {% endif %}

                            {% if _list_table is not empty or _list_filters is not empty %}
                                {% if _list_filters|trim %}
                                    <div class="row">
                                        {{ _list_filters|raw }}
                                    </div>
                                {% endif %}

                                <div class="row">
                                    {{ _list_table|raw }}
                                </div>

                            {% endif %}
                        {% endblock sonata_admin_content %}
                    </section>
                {% endblock sonata_page_content %}
            </div>
        {% endblock sonata_wrapper %}
    </div>

    {% if sonata_admin.adminPool.getOption('use_bootlint') %}
        {% block bootlint %}
            {# Bootlint - https://github.com/twbs/bootlint#in-the-browser #}
            <script type="text/javascript">
                javascript:(function(){var s=document.createElement("script");s.onload=function(){bootlint.showLintReportForCurrentDocument([], {hasProblems: false, problemFree: false});};s.src="https://maxcdn.bootstrapcdn.com/bootlint/latest/bootlint.min.js";document.body.appendChild(s)})();
            </script>
        {% endblock %}
    {% endif %}

    </body>
</html>

Осталось передать форме информацию о классе в методе configureFormFields:

'attr' => ["class" => "tinymce"]

Должно получиться примерно так:

protected function configureFormFields(FormMapper $formMapper)
{

    $formMapper
        ->tab('Содержание')
        ->with('Содержание', array('class' => 'col-md-12'))
        ->add('activity', 'sonata_type_model', array(
            'class' => 'AppBundle\Entity\Activities',
            'property' => 'summary',
            'label' => 'Мероприятие'
        ))
        ->add('hall', 'sonata_type_model', array(
            'class' => 'AppBundle\Entity\Halls',
            'property' => 'hall',
            'label' => 'Зал'
        ))
        ->add('summary', 'text', array('required' => true, 'label' => 'Рабочее название'))
        ->add('active', null, array('required' => false, 'label' => 'Активно'))
        ->add('keywords', 'textarea', array('required' => false, 'label' => 'ключевые слова через пробел'))
        ->add('titleru', 'text', array('required' => true, 'label' => 'Название на русском'))
        ->add('smalltextru', 'textarea', array('required' => false, 'label' => 'Краткое писание на русском','attr' => ["class" => "tinymce"]))
        ->add('fulltextru', 'textarea', array('required' => false, 'label' => 'Подробное описание на русском'))
        ->end()
        ->end()
        ->tab('Языки')
        ->with('Языки')
        ->add('titlede', 'text', array('required' => false, 'label' => 'Название на немецком'))
        ->add('titleen', 'text', array('required' => false, 'label' => 'Название на английском'))
        ->add('smalltextde', 'textarea', array('required' => false, 'label' => 'Краткое описание на немецком'))
        ->add('smalltexten', 'textarea', array('required' => false, 'label' => 'Краткое описание на английском'))
        ->add('fulltextde', 'textarea', array('required' => false, 'label' => 'Подробное описание на немецком'))
        ->add('fulltexten', 'textarea', array('required' => false, 'label' => 'Подробное описание на английском'))
        ->end()
        ->end()
        ->tab('Дата и время')
        ->with('Дата и время', array('class' => 'col-md-6'))
        ->add('eventdate', 'sonata_type_datetime_picker', array('required' => false, 'label' => 'Дата и время начала', 'format' => 'yyyy-MM-dd H:mm:ss'))
        ->end()
        ->with('Зал', array('class' => 'col-md-6'))
        ->add('hall', 'sonata_type_model', array(
            'class' => 'AppBundle\Entity\Halls',
            'property' => 'summary',
            'label' => 'Зал'
        ))
        ->end()
        ->end();

}

 

В итоге получается так:

Symfony TINYMCE WYSWYG
Symfony TINYMCE WYSWYG