Reputation: 8980
I'm using Symfony 1.4/Doctrine's admin generator.
There's a list of questions and I'd like to be able perform a custom object_action on each of them.
What I'm looking for is to mimic the _delete
object action but doing some calculation before that.
So I created a new action :
public function executeListDeleteAndRecalculate(sfWebrequest $request)
{
// Do the calculation
// Then delete the question
}
And I'm adding it to my generator.yml:
object_actions:
delete_and_recalculate: ~
the new action shows in the admin generator but the delete part doesn't work.
I tried a bunch of thing to make it work:
questionActions/delete
action.executeDelete
code to my new action.But everytime I get the infamous
500 | Internal Server Error | sfValidatorErrorSchema _csrf_token [Required.]
So I'm guessing Symfony is doing some magic before actually deleting an object.
Do you know what I'm missing and what's the best way to implement a deleteAndRecalculate kind of action?
Edit:
Of course if I remove the $request->checkCSRFProtection();
everything works just fine. But I assume it's pretty important so I'd like to find a prettier solution.
Upvotes: 3
Views: 5307
Reputation: 4317
This is because the delete
link from the admin generator uses a token to prevent CSRF attacks.
Basically, it sets a token into your session and into an hidden field of a form then checks them one against another on the request. This is possible because the delete
link in the admin generator is actually a (javascript generated) form (this is done to add a sf_method
hidden field to simulate REST behavior).
For more information on how CSRF works and can be prevented, you can read further on Wikipedia: http://en.wikipedia.org/wiki/Cross-site_request_forgery
What you can do is use the same kind of link, you just have to pass a method
parameter to link_to
for it to generate a form, have a look at lib/generator/sfModelGeneratorHelper.class.php
line 32 to see how it's done in the admin-gen.
You would then execute $request->checkCSRFProtection()
in your executeDeleteAndRecalculate
method, and proceed with whatever you want to do, including deleting the object by hand.
To properly generate the link, you would add a linkToDeleteAndRecalculate
method in the Helper class of your module (that should lie in the lib/${YourModule}GeneratorHelper.class.php
file of your module directory) and add the following code (directly taken and adapted from sfModelGeneratorHelper
):
public function linkToDeleteAndRecalculate($object, $params)
{
if ($object->isNew())
{
return '';
}
return '<li class="sf_admin_action_delete">'.link_to(__($params['label'], array(), 'sf_admin'), 'delete_and_recalculate', $object, array('method' => 'delete', 'confirm' => !empty($params['confirm']) ? __($params['confirm'], array(), 'sf_admin') : $params['confirm'])).'</li>';
}
Please note that you have to change the route (I've put delete_and_recalculate
by default but you might want to prefix it with your module's name) from the link_to
call.
You can then use your delete_and_recalculate
nearly like a builtin method from the admin generator (and pass it a label from the generator.yml
for example)
Now that was the hard-way.
The easy way would be to subscribe to the admin.delete_object
event, from your module's pre-execute for example, and to your job there :-)
Upvotes: 4