PHPUnit WebTestCase using native session when mock session is configured, Symfony 5 - symfony

I am getting the "Failed to start the session because headers have already been sent" error when running the sample smoke test url example from Symfony, https://symfony.com/doc/5.3/best_practices.html#smoke-test-your-urls
<?php
namespace App\Tests;
use Generator;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class ApplicationAvailabilityFunctionalTest extends WebTestCase
{
/**
* #dataProvider urlProvider
*/
public function testPageIsSuccessful($url)
{
$client = self::createClient();
$client->request('GET', $url);
$this->assertResponseIsSuccessful();
}
public function urlProvider(): Generator
{
yield ['/'];
}
}
I have configured mock sessions in my config/packages/framework.yaml file. There are no other overrides in the config/packages/test folder.
when#test:
framework:
test: true
session:
storage_factory_id: session.storage.factory.mock_file
The phpunit.xml.dist file has the appropriate environment specified for the "test" environment.
<server name="APP_ENV" value="test" force="true" />
It makes no difference whether I execute the test form within PHPStorm or from console via php bin/phpunit. I must be missing something with the configuration. Any ideas?
Here is a stack trace leading to the native session:

Answered my own question, but #dbrumann had me heading in the right direction with the event listener hint. Thanks
I added to services.yaml, the event listeners only for non-test environments.
when#dev:
services:
Symfony\Component\HttpKernel\Profiler\Profiler: '#profiler'
App\EventListener\RequestListener:
tags:
- { name: kernel.event_listener, event: kernel.request }
App\EventListener\ResponseListener:
tags:
- { name: kernel.event_listener, event: kernel.response }
when#prod:
services:
App\EventListener\RequestListener:
tags:
- { name: kernel.event_listener, event: kernel.request }
App\EventListener\ResponseListener:
tags:
- { name: kernel.event_listener, event: kernel.response }

Related

Exclude all 404 errors from monolog

Currently I have monolog sending me emails when there are errors. I found that 404 errors were just polluting my email and my provider ended up suspending my account due to the number of emails I sent myself. I decided to exclude all 404 errors because all of them were due to bots looking for vulnerabilities and not from clients.
Exclude code:
excluded_404s:
- ^/
The problem I'm seeing now is that symfony still logs 404 errors if the bots use http methods other than GET. My email is now polluted with entries like
HEAD :80/phpmyAdmin/
How can I exclude all 404 errors including those using http methods other than GET?
Edit:
Oh boy. Beginner mistake here. It seems that after my last deploy of the configuration I did not clear the prod cache and I'm figuring out that the config is cached. I'm using deployer to deploy my code updates but I guess the clear cache command is missing from it.
Symfony 4.1. upwords can can be configured to ignore HTTP Codes:
config/packages/monolog.yaml
monolog:
handlers:
main:
# ...
type: 'fingers_crossed'
excluded_http_codes: [404]
https://symfony.com/blog/new-in-symfony-4-1-ignore-specific-http-codes-from-logs
I know it is an old question, but it is the 1st one when googling.
Meanwhile I found a solution for symfony 3.4, if you need to exclude all 404 errors from your logs you can create an ExceptionListener and check if the exception is a NotFoundHttpException.
If it is the case, then just return a response so that the event is stopped and the logger will not handle the exception.
src/AppBundle/EventListener/ExceptionListener.php
namespace AppBundle\EventListener;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class ExceptionListener
{
public function onKernelException(GetResponseForExceptionEvent $event)
{
$exception = $event->getException();
if (! $exception instanceof NotFoundHttpException) {
return;
}
$response = new Response($exception->getMessage(), $exception->getStatusCode());
// returning a response stop the event propagation
$event->setResponse($response);
}
}
src/AppBundle/Resources/config/services.yml
services:
app.exception.listener:
class: AppBundle\EventListener\ExceptionListener
tags:
- { name: kernel.event_listener, event: kernel.exception }
In Symfony 4/5 you can do:
<?php
declare(strict_types=1);
namespace App\EventListener;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class ExceptionListener
{
public function onKernelException(ExceptionEvent $event)
{
$exception = $event->getThrowable();
if ($exception instanceof NotFoundHttpException) {
$response = new Response($exception->getMessage(), $exception->getStatusCode());
$event->setResponse($response);
}
return;
}
}
and
App\EventListener\ExceptionListener:
tags:
- { name: kernel.event_listener, event: kernel.exception }

How to setup console application with autowire commands?

Please help me with config Console App, in first - config
#!/usr/bin/env php
<?php
use ....
...
$container = new ContainerBuilder();
$config = new YamlFileLoader($container, new FileLocator(__DIR__));
$config->load('config.yml');
$output = $container->get('symfony.console_output');$logger = $container->get('logger');
//I want automatic injection!!!!
$helloCommand = new HelloCommand($container, $logger);
$application = $container->get('symfony.application');
$application->add($helloCommand);
$application->run(null, $output);
And my config.yml
services:
logger:
class: Symfony\Component\Console\Logger\ConsoleLogger
arguments:
- '#symfony.console_output'
symfony.application:
class: Symfony\Component\Console\Application
calls:
//by this variant autowire not working
- [add, [ '#app.command.hello_command' ]]
- [setDispatcher, ['#symfony.event_dispatcher']]
...
app.command.hello_command:
class: App\Command\HelloCommand
autowire: true
tags:
- { name: console.command }
So my HelloCommand has constructor with ContainerInterface and LoggerInterface and it work only if i set this arguments directly, other i have error about wrong constructor
Or may be exists another way for configuration with config.yml
for only logger - its will be simple by set ['#logger'] as arguments, but how can i set current container as argument?
Or i`ll have to install full symfony with httpkernel (but it does not need)
HelloCommand
http://pastebin.com/VRr3FM7Q
THE DECISION
app.command.hello_command:
class: App\Command\HelloCommand
arguments:
- '#service_container'
- '#logger'
tags:
- { name: console.command }
The problem lies in how you configure your command:
app.command.hello_command:
class: App\Command\HelloCommand
autowire: true
tags:
- { name: console.command }
This misses the 2 constructor arguments required: $container, $logger and is probably why you get the exception. You can add constructor arguments like this:
app.command.hello_command:
class: App\Command\HelloCommand
arguments:
- '#service_container'
- '#logger'
[...]
I'm not sure if the id for the service_container is right. I never pass the container or make things ContainerAware, but you get the general idea. ;)

Pre_deserialize callback not working in JMSSerializer

I am trying to just execute my Document's __constructor on pre_deserialization via jmsserializer but I don't have a clue why it is not working.
I am loading the serializer metadata from a yaml file looking like this:
AppBundle\Document\Campaign:
exclusion_policy: ALL
xml_root_name: campaign
properties:
id:
type: string
expose: true
slug:
type: string
expose: true
name:
type: string
expose: true
callback_methods:
pre_deserialize: [__construct]
When I try to deserialize executing:
$object = $serializer->deserialize($jsonString, 'AppBundle\\Document\\Campaign', 'json');
I am unable to reach the contructor function, however If I change the event to any of the others available (pre_serialize, post_serialize and post_deserialize) I do.
I think there are missing code about the handling of this specific event but trying to copy the same code affecting the other events it still not working.
It looks like it is never registered in the event dispatcher or something similar.
My environment is:
symfony 2.6.3
jms/serializer 0.16.0
jms/serializer-bundle 0.13.0
Thanks.
I can verify this appears to be a bug in JMS Serializer. For some reason, the service container is not reading the pre_deserialize events and registering it with JMS.
You can, however, work around this using an event subscriber.
First define the Subscriber class, similar to your listener:
<?php
namespace Acme\AcmeBundle\Listener;
use JMS\Serializer\EventDispatcher\PreDeserializeEvent;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
class SerializationSubscriber implements EventSubscriberInterface
{
/**
* #inheritdoc
*/
static public function getSubscribedEvents()
{
return array(
array('event' => 'serializer.pre_deserialize', 'method' => 'onPreDeserialize'),
);
}
public function onPreDeserialize(PreDeserializeEvent $event)
{
echo "we're about to de-cerealizing";
}
}
Then register the Subscriber in your bundle's services configuration:
parameters:
acme.serializer_subscriber.class: Acme\AcmeBundle\Listener\SerializationSubscriber
services:
acme.serializer.subscriber:
class: %acme.serializer_subscriber.class%
tags:
- { name: jms_serializer.event_subscriber }
Rebuild your cache, and you should be good!
Official Documentation: http://jmsyst.com/libs/serializer/master/event_system

Get twilio instance in FOSUserBundle event

I am trying to send SMS to users who register in my website through Twilio, I got the vresh/twilio-bundle and it works fine.
I am trying to pass twilio instance to the event but I think I am missing something, here is what I am doing:
In config.yml i set the servide like this:
services:
registration.completed.listener:
class: Jaguar\AloBundle\EventListener\RegistrationEventListener
arguments:
entityManager: ["#doctrine.orm.voipswitch_entity_manager", "vresh_twilio"]
tags:
- { name: kernel.event_subscriber, event: performOnRegistrationCompleted }
I have declared the twilio config:
vresh_twilio:
sid: 'xxx'
authToken: 'xxx'
version: '2010-04-01'
retryAttempts: 3
Then, in my method I try to get the instance:
public function performOnRegistrationCompleted(UserEvent $event)
{
$twilio = $event->get('vresh_twilio');
}
But it fails...
Any help on this, please?
Thanks a lot!
There are a few issues with your service setup.
You are not actually passing the Twilio instance as you have no # sign preceding the service name. #vresh_twilio is a service, vresh_twilio is just a string.
You are passing in an associative array with a key of entityManager and a value that is also an array with the values of the service #doctrine.orm.voipswitch_entity_manager and the string vresh_twilio.
You're not passing the Twilio instance in your event you are building a listener with the Twilio instance in the constructor.
Your service should actually look like...
services:
registration.completed.listener:
class: Jaguar\AloBundle\EventListener\RegistrationEventListener
arguments:
entityManager: "#doctrine.orm.voipswitch_entity_manager"
twilio: "#vresh_twilio"
// Or
// - #doctrine.orm.voipswitch_entity_manager
// - #vresh_twilio
// Or
// [#doctrine.orm.voipswitch_entity_manager, #vresh_twilio]
//
// As they all mean the same thing and the keys aren't
// used in your actual service __construct
tags:
- { name: kernel.event_subscriber, event: performOnRegistrationCompleted }
This would mean your listener would then have a constructor to receive those services like..
protected $entityManager;
protected $twilio;
public function __conctruct(ObjectManager $entityManager, TwilioWrapper $twilio)
{
$this->entityManager = $entityManager;
$this->twilio = $twilio;
}
Meaning that you could then call it in your class using $this->twilio.
Also, from looking at the services that the Vresh\TwilioBundle creates it looks like the service that you would want to be injecting would be #twilio.api rather than #vresh_twilio as it doesn't seem to exist but I may be wrong there (I haven't used the bundle myself).

Simple Symfony2 event seemingly setup, but not firing

I am trying to set up a simple event listener to execute some code at the start of and before every request. I'm just trying to echo out a simple message to check it's all working.
If I make a mistake (e.g. a typo) or wrongly configure (like I have for the last 30 minutes) then it returns various error messages. But I think I have it setup as the error messages have gone.
This is my code:
I have added this to my /app/config.yml file
services:
kernel.listener.request_listener:
class: Acme\Bundle\NewBundle\EventListener\RequestListener
tags:
- { name: kernel.event_listener, event: kernel.exception, method: onKernelRequest }
And this is the code in the related file
namespace Acme\Bundle\NewBundle\EventListener;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\Response;
class RequestListener
{
public function onKernelRequest(GetResponseEvent $event)
{
$response = new Response();
$response->setContent("hello");
$event->setResponse($response);
}
}
I believe you have hooked into a wrong event kernel.exception, which is called/dispatched only when exception occurs.
I believe you should have hooked the kernel.request event,
services:
kernel.listener.request_listener:
class: Acme\Bundle\NewBundle\EventListener\RequestListener
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
kernel.request is called/dispatched on every request, and before starting to handle a request.
http://symfony.com/doc/2.0/book/internals.html#handling-requests
Before doing anything else, the kernel.request event is notified -- if one of the listeners returns a Response, it jumps to step 8 directly;

Resources