How to use config value in symfony2 translation? - php

Is it possible to use global variable from config.yml in translation file in symfony 2?
If yes, please can you give some example or useful link?

For injecting a (or all) twig globals into your translations you need to override the translation service. Check out this answer if you want a detailed explanation. Here is what I did:
Override the translator.class parameter (e.g. in your parameters.yml):
translator.class: Acme\YourBundle\Translation\Translator
Create the new Translator service:
use Symfony\Bundle\FrameworkBundle\Translation\Translator as BaseTranslator;
class Translator extends BaseTranslator
{
}
Finally override both trans and transChoice:
/**
* {#inheritdoc}
*/
public function trans($id, array $parameters = array(), $domain = null, $locale = null)
{
return parent::trans(
$id,
array_merge($this->container->get('twig')->getGlobals(), $parameters),
$domain,
$locale
);
}
/**
* {#inheritdoc}
*/
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
{
return parent::transChoice(
$id,
$number,
array_merge($this->container->get('twig')->getGlobals(), $parameters),
$domain,
$locale
);
}
In this example I am injecting all twig globals. You can only inject one like this:
array_merge(['%your_global%' => $this->container->get('twig')->getGlobals()['your_global']], $parameters)

You can follow those 2 simple steps:
Inject a Global variable in all the templates using the twig configuration:
# app/config/parameters.yml
parameters:
my_favorite_website: www.stackoverflow.com
And
# app/config/config.yml
twig:
globals:
my_favorite_website: "%my_favorite_website%"
Use Message Placeholders to have the ability to place your text in your translation:
# messages.en.yml
I.love.website: "I love %website%!!"
# messages.fr.yml
I.love.website: "J'adore %website%!!"
You now can use the following twig syntax in your templates to get your expected result:
{{ 'I.love.website'|trans({'%website%': my_favorite_website}) }}

Related

Get current route rule

I'm trying to get the current route rule in my filter.
$routes->group('creditCalculator', ['namespace' => '\Modules\CreditCalculator', "filter" => 'auth:recht1', 'extra_credentials' => array('as'=>'test', 'menu'=>'profile')], function($routes){
$routes->post('/', 'CreditCalculator_Controller::index');
$routes->get('test', 'CreditCalculator_Controller::test', ["filter"=>"auth:test1", 'test2' => 'test3']);
$routes->get('test2/(:num)/(:any)', 'CreditCalculator_Controller::test2/$1/$2', ["as"=>'named_route', "filter"=>"auth:recht3", 'right' => 'right1']);
In the "auth" filter I would like to get access to the current matched route to get the routeOptions.
Target:
We want to set some rules for each route. Afterwards we want to check these settings in our Filter. Example: Login-Type. So we can check each route, which login type is needed for this current route.
We are using Codeigniter 4 HMVC.
Any suggestions?
The documentation of CI4 and the api-documentation didn't get me far. I tried several methods of the router, but no method gave me the current matched route.
What I need as return: /test/(:num)/(:any) and the options array of that route
So far - our filter:
<?php
namespace App\Filters;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface;
class filterTest implements FilterInterface {
public function before(RequestInterface $request, $arguments = null) {
$list = \Config\Services::routes();
$routes = $list->getRoutesOptions();
}
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) {
}
}
I just included the wrong Service. Over Service Router I can access the 'getMatchedRouteOptions' method.
$router = \Config\Services::router();
$routeOptions = $router->getMatchedRouteOptions();

__construct function not constructing correctly in the container symfony 3.4

Hello all i got a a report-bundle and a service AdminUsersStatsListBlockService that need a UserRepository.php within the report bundle to access function, i tried to add the BookingBundle.php within the report bundle to the construct function but i keep constructing without it here's my code and my errors:
HERE AdminUsersStatsListBlockService.php (so i tried to add the BookingRepository here):
<?php
/*
* This file is part of the Cocorico package.
*
* (c) Cocolabs SAS <contact#cocolabs.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Cocorico\ReportBundle\Block\Service;
use Cocorico\BookingBundle\Entity\Booking;
use Cocorico\ReportBundle\Repository\UserRepository;
use Cocorico\ReportBundle\Repository\BookingRepository; /*(added)*/
use Sonata\AdminBundle\Admin\Pool;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\BlockBundle\Block\BlockContextInterface;
use Sonata\BlockBundle\Block\Service\AbstractBlockService;
use Sonata\BlockBundle\Model\BlockInterface;
use Sonata\CoreBundle\Validator\ErrorElement;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\OptionsResolver\OptionsResolver;
class AdminUsersStatsListBlockService extends AbstractBlockService
{
protected $userRepository;
protected $bookingRepository;/*(added)*/
protected $adminPool;
/**
* #param string $name
* #param EngineInterface $templating
* #param UserRepository $userRepository
* #param Pool $adminPool
* #param BookingRepository $bookingRepository/*(added)*/
*/
public function __construct(
$name,
EngineInterface $templating,
UserRepository $userRepository,
Pool $adminPool = null,
BookingRepository $bookingRepository/*(added)*/
) {
parent::__construct($name, $templating);
$this->userRepository = $userRepository;
$this->bookingRepository = $bookingRepository;/*(added)*/
$this->adminPool = $adminPool;
}
/**
* {#inheritdoc}
*/
public function execute(BlockContextInterface $blockContext, Response $response = null)
{
$stat = $blockContext->getSetting('stat');
switch ($stat) {
case 'offerers-expiring':
$results = $this->userRepository->getTopOfferersWithBookingsStatusCount(
Booking::STATUS_EXPIRED,
null,
null,
$blockContext->getSetting('limit')
);
break;
case 'offerers-refusing':
$results = $this->userRepository->getTopOfferersWithBookingsStatusCount(
Booking::STATUS_REFUSED,
null,
null,
$blockContext->getSetting('limit')
);
break;
case 'offerers-accepting':
$results = $this->userRepository->getTopOfferersWithBookingsStatusCount(
Booking::STATUS_PAYED,
null,
null,
$blockContext->getSetting('limit')
);
break;
case 'bookings-expired-list':
$results = $this->bookingRepository->getBookingsExpired(); /*there i want to use it*/
break;
default:
$results = array();
}
return $this->renderResponse(
$blockContext->getTemplate(),
array(
'block' => $blockContext->getBlock(),
'settings' => $blockContext->getSettings(),
'results' => $results,
'admin_pool' => $this->adminPool,
),
$response
);
}
}
Here's the error i get:
request.CRITICAL: Uncaught PHP Exception Symfony\Component\Debug\Exception\FatalThrowableError: "Type error: Too few arguments to function Cocorico\ReportBundle\Block\Service\AdminUsersStatsListBlockService::__construct(), 4 passed in /var/www/Symfony/var/cache/prod/Container7aqlalh/getCocoricoReport_Admin_Block_Users_StatsListService.php on line 13 and exactly 5 expected" at /var/www/Symfony/vendor/cocorico/report-bundle/Block/Service/AdminUsersStatsListBlockService.php line 40 {"exception":"[object] (Symfony\Component\Debug\Exception\FatalThrowableError(code: 0): Type error: Too few arguments to function Cocorico\ReportBundle\Block\Service\AdminUsersStatsListBlockService::__construct(), 4 passed in /var/www/Symfony/var/cache/prod/Container7aqlalh/getCocoricoReport_Admin_Block_Users_StatsListService.php on line 13 and exactly 5 expected at /var/www/Symfony/vendor/cocorico/report-bundle/Block/Service/AdminUsersStatsListBlockService.php:40)"} []
and the container still not constructing with the BookingRepository:
<?php
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
// Returns the public 'cocorico_report.admin.block.users.stats_list' shared service.
include_once $this->targetDirs[3].'/vendor/sonata-project/block-bundle/src/Block/BlockServiceInterface.php';
include_once $this->targetDirs[3].'/vendor/sonata-project/block-bundle/src/Block/Service/BlockServiceInterface.php';
include_once $this->targetDirs[3].'/vendor/sonata-project/block-bundle/src/Block/Service/AbstractBlockService.php';
include_once $this->targetDirs[3].'/vendor/cocorico/report-bundle/Block/Service/AdminUsersStatsListBlockService.php';
return $this->services['cocorico_report.admin.block.users.stats_list'] = new \Cocorico\ReportBundle\Block\Service\AdminUsersStatsListBlockService('cocorico_report.admin.block.users.stats_list', ${($_ = isset($this->services['templating']) ? $this->services['templating'] : $this->load('getTemplatingService.php')) && false ?: '_'}, ${($_ = isset($this->services['cocorico_report.user.repository']) ? $this->services['cocorico_report.user.repository'] : $this->load('getCocoricoReport_User_RepositoryService.php')) && false ?: '_'}, ${($_ = isset($this->services['sonata.admin.pool']) ? $this->services['sonata.admin.pool'] : $this->getSonata_Admin_PoolService()) && false ?: '_'});
Edit: found this, is this the loader ? :
services:
cocorico_report.admin.block.stats:
class: Cocorico\ReportBundle\Block\Service\AdminStatsBlockService
arguments:
- "cocorico_report.admin.block.stats"
- "#templating"
- "#cocorico_report.report.manager"
tags:
- { name: sonata.block }
cocorico_report.admin.block.users.stats_list:
class: Cocorico\ReportBundle\Block\Service\AdminUsersStatsListBlockService
arguments:
- "cocorico_report.admin.block.users.stats_list"
- "#templating"
- "#cocorico_report.user.repository"
- "#sonata.admin.pool"
tags:
- { name: sonata.block }
Thanks in advance for help!:)
So all you need to do is to add the booking repository to the service definition.
# ReportBundle/Resources/services.yml
services:
cocorico_report.admin.block.users.stats_list:
class: Cocorico\ReportBundle\Block\Service\AdminUsersStatsListBlockService
arguments:
- "cocorico_report.admin.block.users.stats_list"
- "#templating"
- "#cocorico_report.user.repository"
- "#sonata.admin.pool"
- "#cocorico_report.booking.repository" # ADD THIS #
tags:
- { name: sonata.block }
The assumption here is that you also have the cocorico_report.booking.repository service already defined. If the repository is something you added then you will have to find the user repository service definition and basically clone it.
There is a lot more information available on how to explicitly configure services . Just try to avoid confusing it with the autowire approach.

Routing won't work when there is a slash behind

My route cannot be found if I add a / at the end as you see below.
class QuizController extends Controller {
/**
* #Route("/quiz/{name}")
*/
public function showAction($name = '') {
$templating = $this->container->get('templating');
$html = $templating->render('quiz/show.html.twig', [
'name' => $name,
'title' => 'Hello World'
]);
return new Response($html);
}
}
The problem is:
myurl/quiz/whatever works
myurl/quiz works
myurl/quiz/ doesn't work
Whenever there is a slash but no value behind, I get the message
No route found for "GET /"
I'm new to Symfony. How can I fix this?
Using myurl/quiz indicates the {name} parameter is not used, but when you use myurl/quiz/ it needs the {name} parameter to be passed in.
Suggests you add defaults and a name for the route like so:
/**
* #Route("/quiz/{name}")
* defaults={"name" = 0},
* name="quiz")
*/
Then if you use myurl/quiz/ it will send myurl/quiz/0. This is an example
Add the ending slash in the route declaration, the route without / will be automatically redirected to the one with the /
class QuizController extends Controller
{
/**
* #Route("/quiz/{name}/")
*/
public function showAction($name = '')
{
$templating = $this->container->get('templating');
$html = $templating->render('quiz/show.html.twig', [
'name' => $name,
'title' => 'Hello World'
]);
return new Response($html);
}
}
Edit (via phone) After OP comments Below:
put 2 #Route declarations before controller action, one with slash one without
#Route("/quiz/")
#Route("/quiz/{name}")
Since OP wants the same route controller to handle both trailing slash and non-trailing slash, the solution is the allow Symfony to accept a slash as part of the variable (which is doesn't by default).
Docs Here : http://symfony.com/doc/current/routing/slash_in_parameter.html
So your route becomes
class QuizController extends Controller {
/**
* #Route("/quiz{name}", name="quiz_name", requirements={"name"=".+"})
*/
public function showAction($name = '') {
$templating = $this->container->get('templating');
$html = $templating->render('quiz/show.html.twig', [
'name' => $name,
'title' => 'Hello World'
]);
return new Response($html);
}
}
Please Note: While this answers the OP's question, it's a dangerour practice. For anyone reading this, it might suit the OP for his logic but note that it will also match any route
/quiz*
So while the OP wants this, it will also match
/quiz/name
/quiz/
/quiz
/quiz/name/edit
/quiz/name/delete
For OP, a work-around is to include edit, delete routes before this custom one as Symfony matches routes by first match wins basis.

How to replace all 403 status codes with 404 in Symfony

In Symfony, when a user attempts to access a route which is forbidden for that specific user (according to the user roles), a page with response code 403 will be returned.
So the user can still see that there is a valid route there.
I would like to overwrite this behavior by replacing the status code 403 with 404, so the user will just see that there is no valid route when she/he is not allowed to access that resource.
How can I accomplish that?
This is doable, however almost undocumented. I'm aware of two ways but there might be even more:
Using access_denied_url configuration option. See security config reference. With this option you can set URL where the user is redirected when the user in unauthorized (I think it should work also with route name). See a similar question: Symfony2 Redirection for unauthorised page with access_denied_url
There're also "Entry Points" as mentioned in The Firewall and Authorization. However, no examples, no explanation how to use it.
I looks like this option expects a service name as can be seen in security config reference (search for entry_point option).
One possible solution, as partially explained here, can be the following:
1) Defining a new service controller in services.yml
exception_controller:
class: Path\To\MyBundle\Controller\MyExceptionController
arguments: ['#twig', '%kernel.debug%']
2) Creating the new class which overrides Symfony\Bundle\TwigBundle\Controller\ExceptionController:
namespace Path\To\MyBundle\Controller;
use Symfony\Bundle\TwigBundle\Controller\ExceptionController;
use Symfony\Component\Debug\Exception\FlattenException;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class MyExceptionController extends ExceptionController
{
public function showAction(Request $request, FlattenException $exception, DebugLoggerInterface $logger = null)
{
$currentContent = $this->getAndCleanOutputBuffering($request->headers->get('X-Php-Ob-Level', -1));
$showException = $request->attributes->get('showException', $this->debug); // As opposed to an additional parameter, this maintains BC
$code = $exception->getStatusCode();
if ($code == 403) {
$code = 404;
// other customizations ...
}
return new Response($this->twig->render(
(string) $this->findTemplate($request, $request->getRequestFormat(), $code, $showException),
array(
'status_code' => $code,
'status_text' => isset(Response::$statusTexts[$code]) ? Response::$statusTexts[$code] : '',
'exception' => $exception,
'logger' => $logger,
'currentContent' => $currentContent,
)
));
}
}
3) Setting the following in config.yml under twig:
twig:
exception_controller: 'exception_controller:showAction'
Even though my original goal was to prevent such an exception to be thrown at all with that code.
Another solution can be overwriting the AccessListener service of the Symfony Security component.
The generic procedure about how to override a service of a bundle is documented here. The following is the concrete example about this particular situation.
First of all let's create the class which overrides the AccessListener class:
<?php
namespace Path\To\My\Bundle\Services;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Security\Http\Firewall\AccessListener;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
class OverrideAccessListener extends AccessListener
{
public function handle(GetResponseEvent $event)
{
try {
parent::handle($event);
} catch (AccessDeniedException $e) {
$request = $event->getRequest();
$message = sprintf('No route found for "%s %s"', $request->getMethod(), $request->getPathInfo());
if ($referer = $request->headers->get('referer')) {
$message .= sprintf(' (from "%s")', $referer);
}
throw new NotFoundHttpException($message);
}
}
}
then we need to create a Compiler Pass in order to change the class attribute of the original service with the new class:
<?php
namespace Path\To\My\Bundle\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('security.access_listener');
$definition->setClass('Path\To\My\Bundle\Services\OverrideAccessListener');
}
}
finally we need to register the Compiler Pass in the build method of the bundle:
<?php
namespace Path\To\My\Bundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Path\To\My\Bundle\DependencyInjection\Compiler\OverrideServiceCompilerPass;
class MyBundleName extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new OverrideServiceCompilerPass());
}
}
Finally I found a simpler solution: using an access denied handler.
Unfortunately there is no much documentation about how to create an access denied handler, but it is very simple.
First create a class that implements the AccessDeniedHandlerInterface and set it as a service (for example naming it my_access_denied_handler_service).
In the handle method a Response should be created and returned (in my case I wanted a 404 response).
Then in the security.yml configuration file we have to set the access_denied_handler under the firewall:
...
firewalls:
my_firewall:
...
access_denied_handler: my_access_denied_handler_service
...
...

How can i get the absolute url of route with symfony

I am using symfony and I want to get the url of a specific route ,
my route is like this
project_sign_in:
pattern: /signin
defaults: { _controller: ProjectContactBundle:User:signIn }
i want to generate the url from this route so i can get
localhost/app_dev.php/signin
or {SERVER-ADDRESS}/app_dev/signin
if I was browsing the server.
Using the Routing Component at version 4.0:
<?php
use Symfony\Component\Routing\Generator\UrlGenerator;
UrlGenerator->generate('project_sign_in', [], UrlGenerator::ABSOLUTE_URL);
The last facultative parameter has to be true to generate absolute url:
$router->generate('project_sign_in', array(), true);
in twig:
{{ path('project_sign_in', {}, true) }}
{# or #}
{{ url('project_sign_in') }}
in controller:
$this->generateUrl('project_sign_in', array(), true );
EDIT: for symfony 4, see #Michael B. answer
UrlGenerator->generate('project_sign_in', [], UrlGenerator::ABSOLUTE_URL);
In Symfony 5.0, if you are using Routing within a service:
namespace App\Service;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
.
.
.
private $router;
public function __construct(UrlGeneratorInterface $router)
{
$this->router = $router;
}
public function foo()
{
$this->router->generate('bar', [], urlGeneratorInterface::ABSOLUTE_URL);
}

Categories