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.
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.
/**
* @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(),
);
}
The associated Twig file editMenu.html.twig
only contain the form:
{{ form(form) }}
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With