Sonata : Améliorer le CKEditor de FormatterBundle

Nous allons insérer ici deux choses :

  • Un plugin permettant d’ajouter des vidéos Youtube dans CKEditor
  • Utiliser un « File Browser » pour gérer les différents médias : KCFinder

On va commencer par étendre le FormatterBundle :

php app/console sonata:easy-extends:generate --dest=src SonataPageBundle

que l’on va ensuite activer dans AppKernel.php

1
2
3
4
5
6
7
8
9
10
11
public function registerBundles()
{
    // ...
 
    $bundles = array(
        // ...
        new Application\Sonata\FormatterBundle\ApplicationSonataFormatterBundle(),
    );
 
    // ...
}

Insérer un plugin pour Youtube

On va parler ici de l’insertion d’un plugin pour Youtube, mais cela doit fonctionner avec d’autres plugins. Je suis parti du plugin suivant :

https://github.com/fonini/ckeditor-youtube-plugin

Le décompresser dans le répertoire web/ckeditor/plugins/youtube/

On va dupliquer le dossier vendor/sonata-project/formatter-bundle/Sonata/FormatterBundle/Resources/views/Form dans le dossier views de notre extension, puis on édite le fichier formatter.html.twig. On remplace :

1
2
3
4
5
6
7
8
9
10
11
12
13
case 'richhtml':
    {{ source_id }}_rich_instance = CKEDITOR.replace('{{ source_id }}', {
        toolbar: [
            [ 'Bold','Italic','Underline',
              '-', 'Cut','Copy','Paste','PasteText','PasteFromWord',
              '-','Undo','Redo',
              '-', 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote',
              '-', 'Image', 'Link','Unlink'
            ], [
              'Maximize', 'Source'
            ]
        ]
    });

Par

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
case 'richhtml':
    CKEDITOR.plugins.addExternal('youtube', '/ckeditor/plugins/youtube/', 'plugin.js');
    {{ source_id }}_rich_instance = CKEDITOR.replace('{{ source_id }}', {
        toolbar: [
            [ 'Bold','Italic','Underline',
              '-', 'Cut','Copy','Paste','PasteText','PasteFromWord',
              '-','Undo','Redo',
              '-', 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote',
              '-', 'Image', 'youtube', 'Link','Unlink'
            ], [
              'Maximize', 'Source'
            ]
        ],
        extraPlugins: 'youtube'
    });

Désormais vous devriez pouvoir trouver l’icône Youtube à côté de l’icône de liens.

Installer KCFinder

J’ai décidé d’utiliser KCFinder car c’est une alternative gratuite et open source de CKFinder qui lui est payant.

Pour commencer, on va télécharger KCFinder et on va le décompresser dans web/kcfinder

On va ensuite éditer le fichier src\Application\Sonata\FormatterBundle\Resources\views\Form\formatter.html.twig

On va modifier le bloc :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
case 'richhtml':
    CKEDITOR.plugins.addExternal('youtube', '/ckeditor/plugins/youtube/', 'plugin.js');
    {{ source_id }}_rich_instance = CKEDITOR.replace('{{ source_id }}', {
        toolbar: [
            [ 'Bold','Italic','Underline',
              '-', 'Cut','Copy','Paste','PasteText','PasteFromWord',
              '-','Undo','Redo',
              '-', 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote',
              '-', 'Image', 'youtube', 'Link','Unlink'
            ], [
              'Maximize', 'Source'
            ]
        ],
        extraPlugins: 'youtube'
    });

Comme suit :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
case 'richhtml':
    CKEDITOR.plugins.addExternal('youtube', '/plugins/youtube/', 'plugin.js');
    {{ source_id }}_rich_instance = CKEDITOR.replace('{{ source_id }}', {
        toolbar: [
            [ 'Bold','Italic','Underline',
              '-', 'Cut','Copy','Paste','PasteText','PasteFromWord',
              '-','Undo','Redo',
              '-', 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote',
              '-', 'Image', 'youtube', 'Link','Unlink'
            ], [
              'Maximize', 'Source'
            ]
        ],
        extraPlugins: 'youtube',
        filebrowserBrowseUrl: '/kcfinder/browse.php?type=files',
        filebrowserImageBrowseUrl: '/kcfinder/browse.php?type=images',
        filebrowserFlashBrowseUrl: '/kcfinder/browse.php?type=flash',
        filebrowserUploadUrl: '/kcfinder/upload.php?type=files',
        filebrowserImageUploadUrl: '/kcfinder/upload.php?type=images',
        filebrowserFlashUploadUrl: '/kcfinder/upload.php?type=flash'
    });

Normalement à ce moment, le plugin est fonctionnel, sauf que si vous tentez de l’utiliser vous devriez avoir un message d’erreur vous indiquant que vous n’avez pas les droits pour accéder à cette partie du serveur. C’est normal, par défaut KCFinder est désactivé. On peut l’activer de façon systématique, mais cela n’est pas très sécurisé car n’importe qui ayant l’url de KCFinder pourra alors y accéder et uploader / éditer / supprimer des fichiers sur votre serveur.

La technique pour la sécurisation est la suivante : On va passer en session l’autorisation d’accéder à KCFinder au moment de la génération du formulaire. C’est là que ça se complique…

Dans un premier temps, étant donné que Symfony2 utilise un gestionnaire de session personnalisé, nous allons devoir paramétrer le même répertoire de sauvegarde des sessions pour KCFinder, sinon il nous sera impossible d’accéder aux sessions de Symfony. Pour cela, éditer le fichier web/kcfinder/core/autoload.php et rajouter en toute fin de fichier :

1
2
// PUT YOUR ADDITIONAL CODE HERE
ini_set('session.save_path', realpath('../../app/cache/dev/sessions'));

Maintenant, occupons nous de passer les paramètres d’autorisation de KCFinder en session. Pour que cela se fasse au moment de la création du formulaire, j’ai choisis de surcharger le service FormatterBlockService et de placer ces autorisations dans la méthode buildEditForm(). J’ai donc dupliqué le fichier vendor\sonata-project\formatter-bundle\Sonata\FormatterBundle\Block\FormatterBlockService.php dans src\Application\Sonata\FormatterBundle\. J’ai édité mon fichier et modifié buidEditForm() comme suit :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public function buildEditForm(FormMapper $formMapper, BlockInterface $block)
{
    $formMapper->add('settings', 'sonata_type_immutable_array', array(
        'keys' => array(
            array('format', 'sonata_formatter_type_selector', array(
                'source' => 'rawContent',
                'target' => '[content]',
                'listener' => true,
            )),
            array('rawContent', 'textarea', array()),
        )
    ));
 
    $_SESSION['KCFINDER'] = array();
    $_SESSION['KCFINDER']['disabled'] = false;
}

Problème : notre fichier ne se sera pas automatiquement pris en compte. Pour cela il va falloir passer par une Passe de Compilation.

Créer le fichier src\Application\Sonata\FormatterBundle\DependencyInjection\Compiler\OverrideServiceCompilerPass.php et y insérer le code suivant :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
 
namespace Application\Sonata\FormatterBundle\DependencyInjection\Compiler;
 
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
 
class OverrideServiceCompilerPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        $definition = $container->getDefinition('sonata.formatter.block.formatter');
        $definition->setClass('Application\Sonata\FormatterBundle\Block\FormatterBlockService');
    }
}

Puis modifier le fichier src\Application\Sonata\FormatterBundle\ApplicationSonataFormatterBundle.php comme suit :

rajouter :

1
2
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Application\Sonata\FormatterBundle\DependencyInjection\Compiler\OverrideServiceCompilerPass;

puis rajouter :

1
2
3
4
5
6
public function build(ContainerBuilder $container)
{
    parent::build($container);
 
    $container->addCompilerPass(new OverrideServiceCompilerPass());
}

Nous pouvons enfin utiliser KCFinder !

Mots-clefs : , , ,



Laisser une réponse

Vous devez être connecté pour publier un commentaire.