I'm using the event listener onKernelResponse.
I used :
if (HttpKernelInterface::MASTER_REQUEST != $event->getRequestType()) {
return;
}
It's having a MASTER_REQUEST twice in my action, there is one before the <!DOCTYPE html> <html> <head>etc, and the other one as excepted after the end of the layout.
He is my services.yml :
history.listener:
class: VENDOR\MyBundle\Service\HistoryListener
arguments: [#doctrine.orm.entity_manager, #logger, #history]
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
- { name: kernel.event_listener, event: kernel.response, method: onKernelResponse }
Did I do something wrong?
Finally found the origin of the problem : the debug toolbar !
It actually sends an ajax request, meaning another MASTER_REQUEST..
My solution is to filter on Controller, with a white/black list of controller's names.
UPDATE:
Here is the code I'm using (so you can easily exclude some other controllers if needed).
public function __construct()
{
$this->classesExcluded = array("Symfony\Bundle\WebProfilerBundle\Controller\ProfilerController");
}
public function onKernelController(FilterControllerEvent $event)
{
$controller = $event->getController();
if (!is_array($controller) || HttpKernelInterface::MASTER_REQUEST != $event->getRequestType() || in_array(get_class($controller[0]), $this->classesExcluded)) {
return;
}
// ...
}
Related
I'm trying to use Sylius' ImagesUploadListener for a custom entity.
In the documentation it says I should listen to an event like "sylius.shipping_method.pre_create". For my custom entity there is no event called that I could hook on.
So what I tried was hooking on the product.pre_create event and giving my entity as a parameter, but it seems that the image upload is only triggered on the product entity and my entity configuration is ignored. Although the ImagesUploadListener is triggered two times, once from the core and once from my configuration.
The error I get is "Column 'path' cannot be null" which basically means that the ImagesUploadListener was not performing the image upload before saving the entity.
app.listener.images_upload:
class: Sylius\Bundle\CoreBundle\EventListener\ImagesUploadListener
parent: sylius.listener.images_upload
autowire: true
autoconfigure: false
public: false
tags:
- { name: kernel.event_listener, event: sylius.product.pre_create, entity: MyBundle\Entity\MyEntity, method: uploadImages }
There should be an event to hook on if you created the entity correctly (the Sylius way). You need to define the entity as a Resource:
# config/packages/sylius_resource.yaml
sylius_resource:
resources:
app.name_of_etity:
driver: doctrine/orm
classes:
model: App\Entity\NameOfEntity
If you defined the resource like this, the events would be:
event: app.system_manual.pre_create
event: app.app.name_of_entity.pre_update
Follow this guide:
https://docs.sylius.com/en/1.6/cookbook/entities/custom-model.html
Update
Because you are managing your custom entity through the existing product form the above will not work. To make it work, you can create your own event listener.
final class ProductSeoTranslationImagesUploadListener
{
/** #var ImageUploaderInterface */
private $uploader;
public function __construct(ImageUploaderInterface $uploader)
{
$this->uploader = $uploader;
}
public function uploadImages(GenericEvent $event): void
{
$subject = $event->getSubject();
// Add a ProductSeoInterface so you can use this check:
Assert::isInstanceOf($subject, ProductSeoInterface::class);
foreach ($subject->getSeo()->getTranslations() as $translation) {
Assert::isInstanceOf($translation, ImagesAwareInterface::class);
$this->uploadSubjectImages($translation);
}
}
private function uploadSubjectImages(ImagesAwareInterface $subject): void
{
$images = $subject->getImages();
foreach ($images as $image) {
if ($image->hasFile()) {
$this->uploader->upload($image);
}
// Upload failed? Let's remove that image.
if (null === $image->getPath()) {
$images->removeElement($image);
}
}
}
}
Tip: Create a (Product)SeoInterface so you can perform the type check.
Don't forget to register the eventListener:
App\EventListener\ProductSeoTranslationImagesUploadListener:
tags:
- {
name: kernel.event_listener,
event: sylius.product.pre_create,
method: uploadImages,
}
- {
name: kernel.event_listener,
event: sylius.product.pre_update,
method: uploadImages,
}
I have a problem with throwing Symfony 2 exception inside event listner. When I do it I get Uncaught exception (onRequest method of listener). Is there any way to throw exception in listener that can be caught by Symfony.
I was trying to avoid this problem by changing the controller in case of an exception (onController method of listener). Target controller had just one line:
throw $this->createNotFoundException('Test');
The controller swap worked but it also resulted in uncaught exception error.
How to wrap a listener or swapped controller inside symfony exception catcher.
My listener:
namespace AppBundle\Listener;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use AppBundle\Controller\HomeController;
class SessionListener {
private $container;
public function __construct($container)
{
$this->container = $container;
}
public function onController(FilterControllerEvent $event)
{
$controller=new HomeController();
$replacementController= array($controller, 'notFoundAction');
$event->setController($replacementController);
}
public function onRequest(Event $event) {
$session = $this->container->get('session');
$kernel = $this->container->get('kernel');
throw new NotFoundHttpException('Test');
}
}
My services.yml
services:
app.session_listener:
class: AppBundle\Listener\SessionListener
arguments: [#service_container]
tags:
- { name: kernel.event_listener, event: kernel.request, method: onRequest }
- { name: kernel.event_listener, event: kernel.controller, method: onController }
probably with a try catch
public function onRequest(Event $event) {
try{
$session = $this->container->get('session');
$kernel = $this->container->get('kernel');
}catch(NotFoundHttpException ex){
throw new NotFoundHttpException('Test');
}
}
As an alternative you can return a 404 response instead of throwing an exception:
class SessionListener
{
public function onRequest(GetResponseEvent $event)
{
$event->setResponse(new Response('Test', 404));
}
}
I am developping some kind of cronjob monitoring on our symfony2 application.
I created a CommandExecution entity with a 'completed' property.
I'm using console events to create and persist this entity.
My service :
kernel.listener.console:
class: Evo\CronBundle\EventListener\ConsoleListener
arguments: [#doctrine.orm.entity_manager]
tags:
- { name: kernel.event_listener, event: console.command, method: onConsoleCommand }
- { name: kernel.event_listener, event: console.terminate, method: onConsoleTerminate }
- { name: kernel.event_listener, event: console.exception, method: onConsoleException }
and the ConsoleListener:onConsoleCommand() and ConsoleListener:onConsoleTerminate() methods called when a command starts and ends to execute :
public function onConsoleCommand(ConsoleCommandEvent $event)
{
$command = $event->getCommand();
$commandEntity = $this->em->getRepository('EvoCronBundle:Command')->findOneBy(['name' => $command->getName()]);
$commandExecution = new CommandExecution();
$commandExecution->setCommand($commandEntity);
$this->em->persist($commandExecution);
$this->em->flush();
// here I want to pass my entity to the command, so I can get it back in the onConsoleTerminate() method
$command->setCommandExecution($commandExecution);
}
public function onConsoleTerminate(ConsoleTerminateEvent $event)
{
$command = $event->getCommand();
// here, retrieve the commandExecution entity passed in onConsoleCommand() method
$commandExecution = $command->getCommandExecution();
$commandExecution->setCompleted(true);
$this->em->flush();
}
As you can see in these methods, I would like to add a commandExecution property to the Symfony Component Console\Command\Command.php, so I can pass in my commandExecution entity and change its status.
Do I have to override this component ? If yes, how ? Or can I do it in a simpler way ?
Add the commandExecution property in your ConsoleListener
protected $commandExecution = null;
Then set it in your onConsoleCommand() method
public function onConsoleCommand(ConsoleCommandEvent $event)
{
$command = $event->getCommand();
$commandEntity = $this->em->getRepository('EvoCronBundle:Command')->findOneBy(['name' => $command->getName()]);
$commandExecution = new CommandExecution();
$commandExecution->setCommand($commandEntity);
$this->em->persist($commandExecution);
$this->em->flush();
$this->commandExecution = $commandExecution;
}
Then you can access to it in your onConsoleTerminate() method
public function onConsoleTerminate(ConsoleTerminateEvent $event)
{
$command = $event->getCommand();
// here, retrieve the commandExecution entity passed in onConsoleCommand() method
$commandExecution = $this->commandExecution;
$commandExecution->setCompleted(true);
$this->em->flush();
}
Don't forget to test if commandExecution value is null in onConsoleTerminate() method
I've got little problem.
I've overrided all html exception templates in app/Resources/TwigBundle/Resources/Exception...
My problem is, that these error pages are only rendered when I'm on the dev env.
When it comes to prod I'll get something like:
http://i.stack.imgur.com/GHd7t.png
Please help me out.
You can do it by registering a service listening to the kernel.view event.
in your service.yml:
your.kernel_listener:
class: Your\AppBundle\EventListener\KernelListener
arguments: [#kernel]
tags:
- { name: kernel.event_listener, event: kernel.view, method: onKernelView }
in your class KernelListener:
namespace Your\AppBundle\EventListener;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\HttpFoundation\Response;
class KernelListener
{
private $kernel;
public function __construct(Kernel $kernel)
{
$this->kernel = $kernel;
}
public function onKernelView(GetResponseForControllerResultEvent $event)
{
if ($this->kernel->getEnvironment() == 'dev') {
$result = $event->getControllerResult();
$response = new Response(print_r($result, true), 200, array('Content-Type' => 'text/html'));
$event->setResponse($response);
}
}
}
Have a look at this guide.
I use the OneUp bundle for symfony 2, method's listener class is never call
//service.yml
amd_picture.uploadListener:
class: Amd\PictureBundle\Services\UploadListener
arguments: ["#doctrine.orm.entity_manager"]
tag:
- {name: kernel.event_listener, event: oneup_uploader.post_chunk_upload, method: onUpload}
the listener class implements the onUpload method and the corresponding event , is it the rigth event to listen ???
class UploadListener {
private $doctrine;
public function __construct($doctrine) {
$this->doctrine = $doctrine;
}
public function onUpload(PostChunkUploadEvent $event) {
//source code
}
}
the srcipt for the front end template
<script>
YUI().use('uploader', function(Y) {
var uploader = new Y.Uploader(
{
multipleFiles: true,
uploadURL: "{{ oneup_uploader_endpoint('gallery') }}",
width: "300px",
height: "60px"
}).render("#fileupload");
</script>
i don't find why the onUpload method is never call?
you have to use the postPersitentEvent in you use statement:
use Oneup\UploaderBundle\Event\PostPersistEvent;
Small correction:
//service.yml
amd_picture.uploadListener:
class: Amd\PictureBundle\Services\UploadListener
arguments: ["#doctrine.orm.entity_manager"]
tag:
- {name: kernel.event_listener, event: oneup_uploader.post_persist, method: onUpload}
Is not tag. Is:
tags:
- {name: kernel.event_listener, event: oneup_uploader.post_persist, method: onUpload}
The YUI3-Uploader is not able to split files into chunks, therefore the YUI3Controller of the OneupUploaderBundle does not support it either. This means there is no post_chunk_upload which will be dispatched and your EventListener is never called.
If you want to process your file after it is uploaded successfully, try listen to the PostPersistEvent like described in the bundles manual.
//service.yml
amd_picture.uploadListener:
class: Amd\PictureBundle\Services\UploadListener
arguments: ["#doctrine.orm.entity_manager"]
tag:
- {name: kernel.event_listener, event: oneup_uploader.post_persist, method: onUpload}
And be sure to pass a PostPersistEvent object to the listener.
use Oneup\UploaderBundle\Event\PostPersistEvent;
class UploadListener {
public function onUpload(PostPersistEvent $event)
{
//...
}
}