-
Notifications
You must be signed in to change notification settings - Fork 29
object actions template ok? #183
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Hi @calvera The line you mentioned on your link is working only in the situation your objectAction is CSRF protected (meaning, require POST request) but the request made is a GET one. We so in that situation display a simple page with the object form action so the user can submit it with a POST request... (this is only if javacript fails, or user call the action in a new window or something like that). Everything else should be enough to handle all your situations. Your proposition failed on csrf protected action with a GET request. Let us know what you were trying to do, and we'll advice you on how to proceed. |
i want to implement sending invitation to user as object action, administrator will choose email template and email is sent... I implemented it by the following code (overriding attemptObjectMail), but I'm looking for better/prefered solution (just curios): protected function attemptObjectMail($pk)
{
$user = $this->getObject($pk);
try {
$this->checkCredentials('hasRole("ROLE_ADMIN")', $user);
$form = $this->createFormBuilder(array())
->add('template', 's2a_select2_entity', array(
'class' => 'CHCLanguageTestingBundle:MailTemplate',
'property' => 'name',
)
)
->getForm();
$form->handleRequest($this->get('request'));
if ($form->isValid()) {
$data = $form->getData();
$mailTemplate = $data['template'];
$twig = $this->get('twig');
$template = twig_template_from_string($twig, $mailTemplate->getBody());
$message = \Swift_Message::newInstance()
->setSubject($mailTemplate->getSubject())
->setFrom('[email protected]', "Channel Crossings Language Testing")
->setTo($user->getEmail(), $user->getName() . ' ' . $user->getSurname())
->setBody(
$template->render(
array('login' => $user->getUsername(),
'password' => $user->getOpenpassword(),
)
),
'text/html'
);
$this->get('mailer')->send($message);
$this->get('session')->getFlashBag()->add(
'success',
$this->get('translator')->trans(
"action.custom.success",
array('%name%' => 'Send invitation'),
'Admingenerator'
)
);
return new RedirectResponse($this->generateUrl("CHC_LanguageTestingBundle_User_list"));
}
return $this->render(
'CHCLanguageTestingBundle:UserActions:index.html.twig',
$this->getAdditionalRenderParameters($user, 'mail') + array(
"User" => $user,
"title" => $this->get('translator')->trans(
"action.custom.title",
array('%name%' => 'mail'),
'Admingenerator'
),
"actionRoute" => "CHC_LanguageTestingBundle_User_object",
"actionParams" => array("pk" => $pk, "action" => "mail"),
"form" => $form->createView(),
)
);
} catch (ValidationException $e) {
return $this->errorObjectMail($e, $user);
}
} |
my alternative solution is: object_actions:
mail:
label: Send invitation to user
credentials: 'hasRole("ROLE_ADMIN")'
icon: fa-envelope
route: CHC_LanguageTestingBundle_User_mail
params:
pk: "{{ User.id }}" then i have dedicated controller: /**
* @Route("/admin/user")
*/
class MailController extends ShowController
{
/**
* @Route("/{pk}/mail", name="CHC_LanguageTestingBundle_User_mail")
*/
public function assignAction(Request $request, $pk)
{
$User = $this->getObject($pk); etc. so I'm wondering which is better, i do not want to 'repeat myself' ;-) |
Actually, you should not override the /**
* (non-PHPdoc)
* @see \Admingenerated\AppBundle\BaseModuleController\ActionsController::executeObjectCopyTo()
*/
protected function executeObjectCopyTo(\Sescandell\AppBundle\Entity\Module $module)
{
$contextManager = $this->get('context_restrictor.manager');
$disabled = $contextManager->disable();
$this->form = $this->createForm(
new ModuleCopyType($this->get('security.context'), $this->get('translator')),
$module->copy()/* clone $module */,
array('action' => $this->getRequest()->getRequestUri())
);
$this->form->handleRequest($this->getRequest());
if ($this->form->isValid()) {
$copy = $this->form->getData();
$copy->setFromAdmin(true);
$copy->setAuthor($this->getUser());
if ($copy->getCustodyAccount()) {
$copy->setCompany(null);
}
$this->getDoctrine()->getManager()->persist($copy);
$this->getDoctrine()->getManager()->flush();
} elseif ($this->form->isSubmitted()) {
if ($disabled) {
$contextManager->enable();
}
throw new \InvalidArgumentException('Form is not valid');
}
if ($disabled) {
$contextManager->enable();
}
}
/**
* (non-PHPdoc)
* @see \Admingenerated\AppBundle\BaseModuleController\ActionsController::successObjectCopyTo()
*/
protected function successObjectCopyTo(\Sescandell\AppBundle\Entity\Module $module)
{
if ($this->form->isSubmitted() && $this->form->isValid()) {
$this->get('session')->getFlashBag()->set('from_copy', true);
return new JsonResponse(array(
'success' => true,
'type' => 'redirect',
'content' => $this->generateUrl("Sescandell_AppBundle_Module_edit", array('pk' => $this->form->getData()->getId())),
));
}
// Get
return $this->render(
'SescandellAppBundle:ModuleActions:copy.html.twig',
array('form' => $this->form->createView())
);
}
/**
* (non-PHPdoc)
* @see \Admingenerated\AppBundle\BaseModuleController\ActionsController::errorObjectCopyTo()
*/
protected function errorObjectCopyTo(\Exception $e, \Sescandell\AppBundle\Entity\Module $module = null)
{
if (is_null($module)) {
return parent::errorObjectCopyTo($e, $module);
}
if (!is_null($this->form) && $this->form->isSubmitted()) {
$this->get('session')->getFlashBag()->add(
'error',
$this->get('translator')->trans("admin.module.object_actions.copy.error", array('%name%' => $module->getName()), 'app')
);
return new JsonResponse(array(
'success' => false,
'type' => 'html',
'content' => $this->renderView(
'SescandellAppBundle:ModuleActions:copy.html.twig',
array('form' => $this->form->createView())
)
));
}
} Just one thing I would do differently is throwing dedicated exception in case of error injecting the form so error handler method would be simpler. What this sample do is:
return new JsonResponse(array(
'success' => false,
'type' => 'html',
'content' => $this->renderView(
'SescandellAppBundle:ModuleActions:copy.html.twig',
array('form' => $this->form->createView())
)
)); Please note that JsonResponse here are because I made an Ajax library able to mix some Admingenerator views&action and AJAX. It might be different in your situation. |
So taking your cas, it should be something like this: protected function executeObjectMail(User $user)
{
$form = $this->createFormBuilder(array())
->add('template', 's2a_select2_entity', array(
'class' => 'CHCLanguageTestingBundle:MailTemplate',
'property' => 'name',
)
)
->getForm();
$form->handleRequest($this->get('request'));
if ($form->isValid()) {
$data = $form->getData();
$mailTemplate = $data['template'];
$twig = $this->get('twig');
$template = twig_template_from_string($twig, $mailTemplate->getBody());
$message = \Swift_Message::newInstance()
->setSubject($mailTemplate->getSubject())
->setFrom('[email protected]', "Channel Crossings Language Testing")
->setTo($user->getEmail(), $user->getName() . ' ' . $user->getSurname())
->setBody(
$template->render(
array('login' => $user->getUsername(),
'password' => $user->getOpenpassword(),
)
),
'text/html'
);
$this->get('mailer')->send($message);
} elseif ($form->isSubmitted()) {
throw new InvalidMailTemplateForm($form);
}
throw new UnsubmittedMailTemplateForm($form);
}
}
protected function successObjectMail(User $user)
{
$this->get('session')->getFlashBag()->add(
'success',
$this->get('translator')->trans(
"action.custom.success",
array('%name%' => 'Send invitation'),
'Admingenerator'
)
);
return new RedirectResponse($this->generateUrl("CHC_LanguageTestingBundle_User_list"));
}
prtected function errorObjectMail(\Exception $e, User $user)
{
if ($e instanceof InvalidMailTemplateForm) {
return $this->render(
'CHCLanguageTestingBundle:UserActions:index.html.twig',
$this->getAdditionalRenderParameters($user, 'mail') + array(
"User" => $user,
"title" => $this->get('translator')->trans(
"action.custom.title",
array('%name%' => 'mail'),
'Admingenerator'
),
"actionRoute" => "CHC_LanguageTestingBundle_User_object",
"actionParams" => array("pk" => $pk, "action" => "mail"),
"form" => $e->getForm()->createView(),
)
);
} elseif ($e instanceof UnsubmittedMailTemplateForm) {
// Display the form for the first time...
}
return parent::errorObjectMail($e, $user);
} And there is no duplication of code. Everything is then depending on how you display your form to correctly manage error / success and throwing exceptions Hoping that helps. |
@sescandell Thanks! I was confused by function names: success and error. I supposed their purpose is different... |
hi,
i'm wondering if object actions template is 100% correct...
see https://github.com/symfony2admingenerator/GeneratorBundle/blob/master/Resources/templates/CommonAdmin/ActionsAction/object_action.php.twig#L40
the return is never called...
also if I return from my objectActionXXX response (for example render page with form), it is not propagated and the page is not rendered.
I would propose an enhacement:
what do you think?
-ks-
The text was updated successfully, but these errors were encountered: