Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony - Is it possible to edit twig templates using web editor

Tags:

php

twig

symfony

We have a website that is built on top of Symfony framework and I have been given a task of allowing the admins to make changes to the email templates or even the twig templates via admin panel like in WordPress where you go to the editor and make changes to the files.

I know Symfony is not a CMS and I am wondering if allowing admins to edit email templates and other twig templates is at all possible to do. The templates are not saved in database they are in their normal location NameBundle/Resources/views and as we know on production Symfony uses cache.

While searching online I came across Ace editor and CodeMirror but again I am stuck at how to use anything like this with Symfony

I will really appreciate if anyone can push me in right direction.

like image 605
Saadia Avatar asked Mar 01 '16 05:03

Saadia


2 Answers

I had the same need recently.

I chose to put the edited content in a app/Resources/AcmeBundle/views/Include/menu.html.twig file because I didn't want to put this in a Bundle. A file src/AcmeBundle/Resources/views/Include/menu.html.twig is loaded the first time this page is loaded, its content will be used as a basis for the editable Twig template. The file can also be empty.

Controller's function:

 /**
 * @Route(
 *      "/edit/menu",
 *      name = "page_edit_menu"
 * )
 */
public function editMenuAction(Request $request)
{
    $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Access denied.');

    // Output file.
    $filepath = $this->container->getParameter('kernel.root_dir').
        '/Resources/AcmeBundle/views/Include/menu.html.twig';

    // Dummy object used in the form.
    $file = new \ArrayObject();

    // Check that the output file exists.
    if (file_exists($filepath)) {
        // Load the file content.
        $file->content = file_get_contents($filepath);
    } else {
        // The file is missing, load the file located in the Bundle instead.
        $file->content = file_get_contents(
            $this->container->get('kernel')->locateResource(
            '@AcmeBundle/Resources/views/Include/menu.html.twig')
        );
    }

    // Declare the form.
    $form = $this->createFormBuilder($file)
        // A textarea for the file content.
        ->add('content', 'textarea', array(
            'attr' => array(
                'rows' => 16,
            )
        ))
        ->add('submit', 'submit', array(
            'label' => 'Save'
        ))
        ->getForm();

    $form->handleRequest($request);

    if ($form->isValid())
    {
        // Save the file in app/Resources/...
        file_put_contents($filepath, $file->content);

        // Clear cache (otherwise the changes won't be applied)
        // Be patient, it can take about 15 seconds.
        $console = 'php '.$this->container->getParameter('kernel.root_dir').
            '/console';

        exec($console.' cache:clear --env=prod');
        exec($console.' cache:warmup --env=prod');

        $this->get('session')->getFlashBag()->add('notice',
            'Content saved succesfully.');

        return $this->redirect($this->generateUrl('page_edit_menu'));
    }

    return $this->render('editMenu.html.twig', array(
        'form' => $form->createView(),
    );
}

Twig file

The associated Twig file editMenu.html.twig only contain the form:

{{ form(form) }}

Usage

Here is how the editable template is used where you want to display the file previously edited:

{% include('AcmeBundle:Include:menu.html.twig') %}

Thanks to templates overriding, the app/Resources/AcmeBundle/views/Include/menu.html.twig file will be used instead of the one in the Bundle.

Git

If you use git, you have to add the file path in the .gitignore file:

# File that can be edited from the admin:
/app/Resources/AcmeBundle/views/Include/menu.html.twig

Without this, an update with git may alter or delete this file.

HTML editor

If you want a WYSIWYG editor, you can install TinymceBundle which provide an HTML editor. Here is a quick guide to use it if you already have jQuery. Otherwise follow the documentation.

composer require "stfalcon/tinymce-bundle:dev-master"

A simple configuration to add to app/config/config.yml:

stfalcon_tinymce:
    selector: ".tinymce"
    language: %locale%
    theme:
        simple:
            theme: "modern"
            plugins: "link"
            toolbar1: "undo redo | bold italic | bullist numlist outdent indent | link"

And add 'class' => 'tinymce', after 'rows' => 16, and {{ tinymce_init() }} in your Javascript.

like image 110
A.L Avatar answered Nov 14 '22 23:11

A.L


Twig lets you use multiple template loaders where you can have templates stored as string instead of files. One of the examples shows probably exactly what you need. They're using strings as templates.

I think this feature has changed recently because I remember there used to be Twig_Loader_String class. It looks like it's been removed since 1.15.

In your case you store templates in the database and then add them to the filter chain just like here: http://twig.sensiolabs.org/doc/api.html#twig-loader-chain

Symfony configuration has also twig.loader tag for adding new loaders.

like image 32
martin Avatar answered Nov 15 '22 00:11

martin