Disable console.log() messages generated by Sonata admin bundle - php

I'm using Sonata Admin bundle in my Symfony project. I see many console log messages in the browser generated by Sonata admin bundle.
These messages are generated by Sonata Admin from /vendor/sonata-project/admin-bundle/src/Resources/public/Admin.js by the code,
/**
* render log message
* #param mixed
*/
log: function() {
var msg = '[Sonata.Admin] ' + Array.prototype.join.call(arguments,', ');
if (window.console && window.console.log) {
window.console.log(msg);
} else if (window.opera && window.opera.postError) {
window.opera.postError(msg);
}
},
Does anyone know how to disable these log messages? I don't even get any kind of result from Google search. Is there a way to control these from configuration file or something?
Thanks in advance!!

I have opened a issue in Sonata Admin GitHub repo https://github.com/sonata-project/SonataAdminBundle/issues/5278 and found the solution.
You have to override the sonata admin's standard_layout like,
/config/packages/sonata_admin.yaml
sonata_admin
templates:
layout: 'sonata_admin/layout.html.twig'
Now create layout.html.twig inside /templates/sonata_admin/ and use the following code.
{% extends '#SonataAdmin/standard_layout.html.twig' %}
{% block javascripts %}
{{ parent() }}
<script>
if ('undefined' !== typeof window.Admin) {
window.Admin.log = function() {}
}
</script>
{% endblock %}

If you don't need any Sonata comments at all, I suggest you to comment that code and you should be done. If some error appears (for example, if the function "log()" is called anywhere in the code), you can just comment these two lines:
window.console.log(msg);
window.opera.postError(msg);

Related

Grav CMS: Hide modular pages in page selection lists

I'm working on a project which uses a lot of modular pages.
So naturally, the dropdown which lists all the pages (e.g. when selecting a parent page when creating a new page) gets very bloated with options you don't really use.
I edited /user/plugins/admin/themes/grav/templates/forms/fields/pages/pages.html.twig to prevent the modular pages from rendering.
Original code (line 12):
{% for page_route, option in pages_list %}
<option {% if page_route == value or (field.multiple and page_route in value) %}selected="selected"{% endif %} value="{{ page_route }}">{{ option|raw }}</option>
{% endfor %}
My code:
{% for page_route, option in pages_list %}
{% if page_route|split('/')|last matches '/^(?!_).*/' %}
<option {% if page_route == value or (field.multiple and page_route in value) %}selected="selected"{% endif %} value="{{ page_route }}">{{ option|raw }}</option>
{% endif %}
{% endfor %}
So this works pretty well and hides all the modular pages in the dropdown. Unfortunately, I fear this may be overwritten with the next admin plugin update.
I'd love to create a plugin which forces the admin plugin to use my templates instead of messing around in the original ones, but I don't know how to do that. Is it even possible?
Thanks!
I found something: https://github.com/OleVik/grav-plugin-adminidenticons
It overrides a partial of the admin plugin.
Step 1: Create a plugin
There are plenty of tutorials how to do that.
I have the following file structure inside my plugin folder:
user/plugins
-- myplugin
---- blueprints.yaml
---- myplugin.php
---- myplugin.yaml
Step 2: Copy files
/user/plugins/admin/themes/grav/templates/forms/fields/pages/pages.html.twig
to /user/plugins/myplugin/admin/themes/grav/templates/forms/fields/pages/pages.html.twig
/user/plugins/admin/themes/grav/templates/partials/blueprints-new.html.twig
to /user/plugins/myplugin/admin/themes/grav/templates/partials/blueprints-new.html.twig
Don't forget to add the snippet I posted above into the copied pages.html.twig. You can leave the blueprints-new.html.twig unedited, but you need the partial inside your plugin folder to get Twig to load the local pages.html.twig.
Step 3: PHP
Edit myplugin.php
<?php
namespace Grav\Plugin;
use Grav\Common\Grav;
use Grav\Common\Plugin;
use Grav\Common\Page\Page;
use RocketTheme\Toolbox\Event\Event;
class MyPluginPlugin extends Plugin
{
public static function getSubscribedEvents() {
return [
'onPluginsInitialized' => ['onPluginsInitialized', 0],
];
}
public function onPluginsInitialized()
{
/** #var Uri $uri */
$uri = $this->grav['uri'];
$route = $this->config->get('plugins.admin.route');
if ($route && preg_match('#' . $route . '#', $uri->path())) {
$this->enable([
'onPageInitialized' => ['onPageInitialized', 0],
'onAdminTwigTemplatePaths' => ['onAdminTwigTemplatePaths', 0]
]);
}
}
/**
* Load custom CSS into backend
*
*/
public function onPageInitialized()
{
$assets = $this->grav['assets'];
$assets->addCss('user/plugins/myplugin/style/custom-backend.css', 1);
}
/**
* Register templates and page
*
* #param RocketTheme\Toolbox\Event\Event $event Event handler
*
* #return array
*/
public function onAdminTwigTemplatePaths($event)
{
$event['paths'] = array_merge(
$event['paths'],
[__DIR__ . '/admin/themes/grav/templates']
);
return $event;
}
}
Bonus: Hide unique page templates
Sometimes, you create page templates which are supposed to be used once on just one page. Just the way Grav works, they will still appear inside the list when creating a new page. Of course, you don't want your editors to get creative with the page templates, so it's best to hide them.
If you're actually also reading the code you're copy-pasting, you'll notice, that there is a function onPageInitialized(), which loads a CSS file into the backend.
Update your files:
user/plugins
-- myplugin
---- style
------ custom-backend.scss
------ custom-backend.css
---- blueprints.yaml
---- myplugin.php
---- myplugin.yaml
Edit custom-backend.scss
// hide unique templates
.selectize-dropdown-content {
.option {
$hide_values: "this-template", "home", "that-template";
#each $current_value in $hide_values {
&[data-value="#{$current_value}"] {
display: none;
}
}
}
}
Set the $hide_values to the page templates you want to hide in the backend. I use CSS, that way you can re-enable them with the browser inspector in case you need them. Of course, don't forget to compile your SCSS.
I know this turned into a fully fledged tutorial, but having the modular pages littering the page list is actually a problem I had on multiple projects now and I never found something online. Unfortunately, I don't really have a way to publish this properly, so I hope someday someone will stumble upon this Q&A and put it on some webblog, where it belongs.
Thanks!

Sonata News Bundle - Add CKEditor

I'm a beginner in Symfony and I am trying to set up CKEditor for the Sonata News Bundle.
I have looked everywhere (even on German forums whereas I don't speak German !) but I cannot find any answer anywhere.
Does anyone have a clue or a solution to my question ?
Thank you everyone.
Louis
I would suggest you to use IvoryCKEditorBundle
Download the Bundle:
composer require egeloen/ckeditor-bundle
Register the Bundle, Then, update your app/AppKernel.php
class AppKernel extends Kernel
{
public function registerBundles()
{
$bundles = array(
new Ivory\CKEditorBundle\IvoryCKEditorBundle(),
// ...
);
// ...
}
}
If you're using Symfony <= 2.8:
php app/console ckeditor:install
php app/console assets:install web
If you're using Symfony >= 3.0:
php bin/console ckeditor:install
php bin/console assets:install web
Then usage
The way I do it (symfony: 4.3.5, sonata: 3.54.1).
Download ckeditor JS lib and place it inside public/js so i.e. you should have the file:
your_app/public/js/ckeditor/ckeditor.js
and beside that file dirs: adapters, lang, plugins and skins and some js/css/md files.
Then override base sonata edit template with:
{% extends '#SonataAdmin/CRUD/base_edit.html.twig' %}
{% block javascripts %}
<script src="{{ asset('js/ckeditor/ckeditor.js') }}" type="text/javascript"></script>
{{ parent() }}
{% endblock %}
This code will include ckeditor to your pages and should be placed at: your_app/templates/edit.html.twig
Then, add to "templates" section edit:edit.html.twig so template you created would be used:
sonata_admin:
title: 'Your app Admin'
dashboard:
blocks:
- { type: sonata.admin.block.admin_list, position: left }
templates:
edit: edit.html.twig
This is file: your_app/config/packages/sonata_admin.yaml
Then, when you are adding new field from sonata admin bundle, inside configureFormFields your ckeditor fields should look like:
->add('field_name', null, array('attr'=> array('class' => 'ckeditor')))
Important part is adding array of attributes with class attribute.
Clear the cache and CKEditor should be working now.

Add custom Sonata page route to the navbar

I've created a custom Sonata page
Simple route
medapp_adminStreamCommands:
path: /admin/stream
defaults: { _controller: MedAppBundle:VideoChat/VideoChat:adminStreamCommands }
Controller that returns the admin pool
public function adminStreamCommandsAction(Request $request)
{
return $this->render('#MedApp/AdminSonata/Stream/stream_commands.html.twig', array(
'admin_pool' => $this->get('sonata.admin.pool')));
}
Plain view template
{% extends '#MedApp/AdminSonata/standard_layout.html.twig' %}
{% block content %}
foobar
{% endblock content
This works, I can access it on my website with /admin/foo and I get a page which has the Sonata admin template with my 'foobar' content.
My question is, how can I add this route to the left and top navbar without having to modify the default template?
That is because the left menu is rendered by a KNP menu:
{% block side_bar_nav %}
{% if app.user and is_granted('ROLE_SONATA_ADMIN') %}
{{ knp_menu_render('sonata_admin_sidebar', {template: admin_pool.getTemplate('knp_menu_template')}) }}
{% endif %}
{% endblock side_bar_nav %}
And I somehow need to add my new page to be rendered by this menu.
Normally, a page is added through a service, but these are built on top of an entity:
servicename:
class: Bundle\Class
arguments: [~, Bundle\Entity\Entityname, ~]
tags:
- { name: sonata.admin, manager_type: orm, group: admin, label: CustomName}
My page is not using an entity, though, just static content or content that is not dependant on an entity.
I know already that I can modify the blocks that generate the menus, but I was thinking that the best way would be to add my class as a service tagged as sonata.admin that doesn't have an orm manager_type, in other words, is not an Entity. How can that be done?
You should override standard_layout and modify content of side_bar_nav block. This is simple and fast way. Or you can dig into sonata code to find how to inject something into admin_pool.dashboardgroups - have fun :)
I don't think that's possible, you have to create a new layout, copy the sonata admin layout and customize it to your need.
You can change the layout used by changing the yml configuration for sonata_admin (templates -> layout) or extending the SonataAdmin bundle and creating your own layout.html.twig.

Symfony 2 : Flash message on login / logout

Using Symfony 2.6, I am looking for the best way to add a flash message on login / logout in my application. I precise that in each case I don't want to modify the Response (I don't need to).
Here are my solutions :
Login:
1. First solution :
I can use the security.interactive_login event or the security.authentication.success event. In both case I can implement a listener to add a flash message when the event occurs.
2. Second solution :
I can create my own LoginSuccessHandler that implements the AuthenticationSuccessHandlerInterface, but in this case I have to return a response. Moreover, I am not familiar with this method and I am afraid to overwrite the default success handler. Is that correct ?
Logout:
I can create a LogoutListener that implements the LogoutHandlerInterface. In this case I am also afraid to overwrite the defaut logout handler.
Thank you for your proposals.
Use the FOSUserBundle login/logout logic etc. already implemented...
Thereby you will have the possibilty to show errors on the login-check redirect:
To do this you must return the error to the twig
$session->getFlashBag()->add('error', 'Error message');
And in the twig you will need a block like this to show errors, if the session is holding any:
{% block flashes %}
{% if app.session.flashbag.peekAll|length > 0 %}
{{ session_flash() }}
{% endif %}
{% endblock flashes %}

Symfony2 fos login, register and forgot password in one view

I need to apply a purchased template to our dashboard. In this template, the login, register and forgot password forms are all under the same view, and switching between them using simple JQuery.
I have been looking for a nice, not-too-flashy way of combining all three forms into one, but I came up empty.
My standing options (as I see them), and why I don't like any of them:
Take the views from the fos bundle, copy them to /app/Resources/FOSUserBundle/views/, remove the {% extend %} part and {% include %} them in my own login view. Reason for dislike: to me this looks a little like a quick-n-dirty fix - "that part's not working? Let's break it off!" :)
Extend the fos bundle, accept an extra parameter in the LoginAction and RegisterAction, use {% render %} with parameters in my own login view. Reason for dislike: extending a whole bundle and modifying two different controllers just to change the way it renders feels like bad MVC.
XHR load everything. Reason for dislike: this approach makes sense when using inner pages, but for pages that reload anyway it just doesn't make sense.
TL;DR version: I'm looking for a non-hack way of including the login, register and forgot password form in one page.
Any help would be greatly appreciated!
I found a solution with which I am comfortable with for my current project. The advantages and disadvantages of the proposed solution upfront:
Advantages:
few LOC to implement
FOSUserBundle update proof (does not override the view scripts*)
Disadvantages:
performance overhead due to subrequests
only forms can be displayed, form submission (and subsequently error handling upon submission) will always go to the pages provided by FOSUserBundle
still feels like a quick-n-dirty fix, but better than other options
* only needs to override the layout.html.twig file
With that being said, here is what I have done:
Render the form in your template
Use embedded controllers to render the forms you need:
<div>
<h2>Login</h2>
{{ render(controller('FOSUserBundle:Security:login', { embeddedForm: true})) }}
</div>
<div>
<h2>Reset</h2>
{{ render(controller('FOSUserBundle:Resetting:request', { embeddedForm: true})) }}
</div>
Override FOSUserBundle layout
As I use the routes provided by the bundle, I had to override the FOSUserBundle layout template file to extend the standard layout of my application. As the overriden FOSUserBundle layout file extends the main applications layout file the layout would be repeated for each call {{ render ... }}. To prevent that, we need to dynamically disarm the extended layout file. Here is what the overriden layout file looks like:
{# app/Resources/FOSUserBundle/views/layout.html.twig #}
{% if app.request.get('embeddedForm') %}
{% set layout = 'AcmeBundle::layout-content.html.twig' %}
{% else %}
{% set layout = 'AcmeBundle::layout.html.twig' %}
{% endif %}
{% extends layout %}
{% block content %}
{% block fos_user_content %}{% endblock %}
{% endblock %}
Create the AcmeBundle::layout-content.html.twig file
This layout should only render the content block of the FOSUserBundle view scripts and is such short and simple:
{# src/Acme/DemoBundle/Resources/views/layout-content.html.twig #}
{% block content %}{% endblock %}
Now the forms will render nicely with all dependencies (CSRF and so forth). Submitting the form will however take you to the FOSUserBundle actions.
Alternative solution:
This answer describes how to manually implement the forms and link them to the FOSUserBundle controller.

Categories