Override FosUserBundle template in own bundle, not app/Resources - symfony

According to this http://symfony.com/doc/current/bundles/FOSUserBundle/overriding_templates.html
I can override FOSUserBundle templates in the app/Resources directory or create a child bundle.
Is there a way to place these templates into my own bundle directory instead?
I've tried adding:
twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
paths:
'%kernel.root_dir%/../src/AppBundle/Resources/FOSUserBundle/views/': FOSUSerBundle
to my config.yml

No, the template names are hardcoded inside the FOSUserBundle's controllers, thus you are not able to place them in your own bundle. (Unless you overwrite all controllers completely)

No, you can't. Template names are hardcoded in fosub controllers. But,
as a workaround you can include your own template in rewrited one. For sample, do it like this:
// app/Resources/FOSUserBundle/views/layout.html.twig
{% include '#YourBundleName/layout.html.twig' %}

I did template overriding for FosUserBundle in one of my project developed in symfony2.3 version.
Please try below code that may help you
config.yml
twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
FrontBundle/Controller/LoginController.php
<?php
namespace Dhi\UserBundle\Controller;
use FOS\UserBundle\Controller\SecurityController as Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\RedirectResponse;
class LoginController extends Controller
{
protected function loginController(array $data)
{
$request = $this->get('request');
return $this->render('FrontBundle:login:login.html.twig');
}
}
FrontBundle/Resources/views/login/login.html.twig
{% extends "DhiUserBundle::layout.html.twig" %}
{% trans_default_domain 'FOSUserBundle' %}
{% block body %}
{% block fos_user_content %}
{% trans_default_domain 'FOSUserBundle' %}
// Your login form code here
{% endblock fos_user_content %}
{% endblock body %}

You may look at your versions of FOSUser and Symfony and read this thread : https://github.com/FriendsOfSymfony/FOSUserBundle/issues/2439
I've experience this bug which didn't allow me to override FOS templates because they used (in latest version 2.0.0-beta) the namespaced syntax (the one with # symbol) to link templates. And because of it, before Symfony's 2.7.23 version, you can't override templates by putting the right named file in the same folders as described here : http://symfony.com/doc/master/bundles/FOSUserBundle/overriding_templates.html

I had the same issue today. My config.yml file is below:
# Twig Configuration
twig:
debug: '%kernel.debug%'
strict_variables: '%kernel.debug%'
paths:
"%kernel.root_dir%/../src/WebBundle/Resources/views/user/": FOSUser
I added all FOSUserBundle templates under WebBundle/Resources/views/user/ and made some extend/include changes in all templates and now it works.

Related

Overriding PriceHelper in Sylius

I am trying to override PriceHelper class by adding getOriginalPrice function but since the service not registered, on service.yml, I put:
services:
AppBundle\Helper\PriceHelper\:
class: AppBundle\Helper\PriceHelper
arguments:
- "#sylius.calculator.product_variant_price"
tags:
- { name: templating.helper, event: sylius.templating.helper.price, method: getOriginalPrice, alias: sylius_calculate_original_price }
On twig, I added:
{%- macro calculateOriginalPrice(variant) -%}
{% from _self import convertAndFormat %}
{{- convertAndFormat(variant|sylius_calculate_original_price({'channel': sylius.channel})) }}
{%- endmacro -%}
and replaced:
{{ money.calculatePrice(product|sylius_resolve_variant) }}
to
{{ money.calculateOriginalPrice(product|sylius_resolve_variant) }}
Error:
Unknown "sylius_calculate_original_price" filter. Did you mean
"sylius_calculate_price"?
Any idea?
Problem solved.
The services.yml is actually fine. Just need to add below in config.yml:
twig:
globals:
sylius_calculate_original_price: "#app.templating.helper.price"
and in twig:
{{ sylius_calculate_original_price.getOriginalPrice(variant,{'channel': sylius.channel}) }}
services.yml can be shorten to:
app.templating.helper.price:
decorates: sylius.templating.helper.price
class: AppBundle\Helper\PriceHelper
arguments:
- "#sylius.calculator.product_variant_price"
The PriceHelper service is configured in this file: https://github.com/Sylius/Sylius/blob/f7d42d2ce64288407372775e0ed421debcd50cd3/src/Sylius/Bundle/CoreBundle/Resources/config/services/templating.xml
But instead of replacing the service like you did, you should decorate it. Extend the PriceHelper class with a new class and add the functionality that you need, then add configuration for your new service like described in the following link, to decorate the PriceHelper service: http://symfony.com/doc/current/service_container/service_decoration.html
In your specific case, you have to use this configuration:
AppBundle\Helper\PriceHelper:
decorates: '#sylius.templating.helper.price'
arguments:
$productVariantPriceCalculator: '#sylius.calculator.product_variant_price'

Sonata admin non-deprecated method for setting templates?

The documentation for Sonata Admin Bundle offers this method for setting per-admin templates:
https://sonata-project.org/bundles/admin/2-0/doc/reference/templates.html
However that method has now been deprecated. Is there a new method, not mentioned yet in the documentation, or have the devs simply jumped the gun with this deprecation?
You can define your custom template for each admin by using the following code in your admin class.
public function configure()
{
$this->setTemplate('show', 'sonata_admin/show.html.twig');
// similarly for all actions
}
You must place your twig file in templates/sonata_admin/ folder, if you are using symfony 4.
The twig file must be like,
{% extends '#SonataAdmin/CRUD/show.html.twig' %}
{% block block_name %}
//your content
{% endblock %}

Permanently extend symfony twig template

In my symfony2 application I created a dashboard which currently consists of many navigation elements.
Now I am trying to split those elements into several bundles.
This is the code I have:
{# app/Resources/views/base.html.twig #}
{# ... #}
{% block body %} {% endblock %}
{# ... #}
Then in the ProfileBundle:
{# src/MyApp/ProfileBundle/Resources/views/Dashboard/index.html.twig #}
{% block body %}
<p>Heading</p>
<ul>
{% block dashboardNavi %} {% endblock %}
</ul>
{% block %}
edit: The controller:
class DashboardController extends Controller
{
public function indexAction()
{
return $this->render('MyAppProfileBundle:Dashboard:index.html.twig', array());
}
}
The routing:
pricecalc_profile_dashboad_security:
pattern: /dashboard
defaults: {_controller: MyAppProfileBundle:Dashboard:index }
That template is rendered correctly, when my route "/dashboard" is loaded.
What I now'd like to do, is extend that dashboardNavi-Block in multiple Bundles without changing the route from my ProfileBundle.
Each of those Bundles brings it`s own routes and controllers for custom actions, but all bundles should extend that one block to add links for their custom actions to the dashboard screen.
What I have so far is:
{# src/MyApp/ProfileNewsletterBundle/Resources/views/Dashboard/indexNewsletter.html.twig #}
{% extends 'MyAppProfileBundle:Dashboard:index.html.twig' %}
{% block dashboardNavi %}
{{ parent() }}
<li>Test</li>
{% endblock %}
but that template is never rendered.
edit 2:
Maybe my understanding of how symfony is working in terms of template inheritance is kind of wrong. I'll specify what I am trying to do.
I got one Bundle (DashboardBundle) which consists of an own route, controller, view etc. The view contains two blocks - like navigation and dashboard.
Now, I would like to have those two blocks extended by some other Bundles - just adding new navigation items and shortcuts on that dashboard and navigation block.
I would like to do those enhancements without modifying my Dashboard-Bundle - if that is possible at all.
When finished, I will have 16 Bundles, each providing own functionality in own Controllers - and they should just be linked on that dashboard.
Is it possible to have the dashboard-view extended that way without modifying the view itself?
I finally managed to fix that after having understood how symfony works in extending controllers and views.
I added a new Controller:
{# src/MyApp/ProfileNewsletterBundle/Controllers/DashboardController.php #}
class DashboardController extends Controller {
public function indexAction()
{
return $this->render('ProfileNewsletterBundle:Dashboard:index.html.twig', array());
}
}
modified the bundle ProfileNewsletterBundle to let the method getParent return ProfileBundle,
and modified the view:
{% extends 'ProfileBundle:Dashboard:index.html.twig' %}
{% block dashboardNavi %}
<li>Test</li>
{% endblock %}
That seems to work fine so far.
Thank you all for spending your time on that.

How can I change symfony2 form fields default options globally?

Is there a way to change default options for form fields globally in symfony2?
More specifically, I want to change the render of ALL datetime fields to use single_text instead of the default choice widget.
Can it be done? Or do I need to implement a custom type and set the default in there, like for example the birthdate type?
I prefer an option that leads to minimal changes in the codebase.
The post is old, but you can use an alternative method, overriding the DateType symfony class ...
service.yml
services:
form.type.date:
class: "YourApp\YourBundle\Form\DateType"
tags:
- { name: "form.type", alias: "date" }
DateType.php
<?php
namespace YourApp\YourBundle\Form;
use Symfony\Component\Form\Extension\Core\Type\DateType as SymfonyDateType;
use Symfony\Component\OptionsResolver\OptionsResolver;
class DateType extends SymfonyDateType
{
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
parent::configureOptions( $resolver );
$resolver->setDefault( 'widget', 'single_text' );
}
}
You can check if the service is taken by container
$ ./app/console debug:container | grep form.type.date
form.type.date YourApp\YourBundle\Form\DateType
form.type.datetime Symfony\Component\Form\Extension\Core\Type\DateTimeType
You have to define a form theme.
It's very easy and requires only a little bit coding time. First of all, you have to know which block to customize; in that case, you can do something like
{% block my_data_widget %}
{% spaceless %}
{% if type is defined and type == 'date' %}
// do all your customization
{% else %}
// don't know ...
{% endif %}
{% endspaceless %}
{% endblock form_widget_simple %}
Now that you have defined this snippet of code, you can use it into your main template (or whatever you use into your form views) in that way
{% form_theme form 'YourBundle:Form:myDataWidget' %}
Last but not least important, you have to place your form theme into Resources/views folder. In my example, your path will be Resources/views/Form/myDataWidget
Update
Did you tried with
{% set type = type|default('single_text') %}
or something like that?

twig: find out if I'm in a subroute of a mainroute

I'm trying to exclude a menu if I'm in a subroute of a mainroute.
So for example this:
if route is /backend/* then exclude
else if route is /backend/admin/* don't exlude
else if route is /backend/admin/create then exclude
Is there a way to achieve this in twig with a few lines of code?
To get current path in twig you can use app.request.pathinfo.
Edit:
If you want to get route name of current url you can do it in following way.
Add Router object as template global variable.
#In app/config.yml
#.......
# Twig Configuration
twig:
globals:
router: #router
And then in your template,
{% set route_info = router.match(app.request.pathinfo) %}
{% set route_name = route_info._router %}
Then you can include/exclude your template based on route name.
Edit Again
Route name can be found in much simpler way.
{{ app.request.attributes.get('_route') }}

Resources