yii2 binds redirect to each link after first request - redirect

public function actionDone($id)
{
if ($model = $this->findModel($id)) {
$model["status"] = 3;
if ($model->save()) {
return $this->redirect(['test/index']);
}
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
It works only for the first time for each link. After that its just redirects to the 'test/index' without doing anything. Seems like browser (or smth else) remember, that if we open, for example, page site.com/?r=test/done&id=2 it should redirect to 'test/index' anyway.
Why is that? How can I fix it?
I even tried put die(); in the beginning of the method - anyway it redirects to 'test/index' until I use different link with another ID.
Thanks!

Related

Form redirect for confirmation

Form redirect for confirmation can be currently managed using one of these two options:
1/ Flash message: using flashbag on the form page or another page like this:
$this->addFlash('success', 'Thank you');
return $this->redirectToRoute('confirmation_page');
2/ Confirmation page: using a dedicated confirmation like this:
return $this->redirectToRoute('confirmation_page');
BUT using option 2 makes the confirmation_page directly accessible from the browser without having submitted the form before. I am currently using flashbag mechanism to fix it by adding a $this->addFlash('success', true); before the redirection in the form and then checking the flashbag content in the confirmation page so that the route is accessible only once after being successfully redirected from the form.
Is there any best practice or more appropriate way to manage it?
/**
* #Route("/confirmation", methods="GET", name="confirmation_page")
*/
public function confirmation(): Response
{
$flashbag = $this->get('session')->getFlashBag();
$success = $flashbag->get("success");
if (!$success) {
return $this->redirectToRoute('app_home');
}
return $this->render('templates/confirmation.html.twig');
}
Flash Message is designed to display messages. Instead, use sessions in your application.
When submitting the confirmation form, create a variable in the session before the redirect
$this->requestStack->getSession()->set('verifyed',true);
return $this->redirectToRoute('confirmation_page');
Use the created variable in your method
public function confirmation(): Response
{
if (!$this->requestStack->getSession()->get('verifyed')) {
return $this->redirectToRoute('app_home');
}
return $this->render('templates/confirmation.html.twig');
}
Don't forget to inject the RequestStack into your controller
private RequestStack $requestStack;
public function __construct(RequestStack $requestStack)
{
$this->requestStack = $requestStack;
}

Symfony2 esi cache forms not working

I get to the weird situation. I have up to date server files with local files. This "flash message with error" appears when this is not valid:
if ($form->isValid() && $this->checkLastComment($commentRepository,$user,$status, $comment)) {
I have two urls. First /Home (working) for everyone where i load statuses with comments BUT I DO NOT CACHE THE PAGE
Then i have /Suggested url where i load statuses with comments BUT USING
$response->setPublic();
$response->setSharedMaxAge(3600);
I CACHE THE PAGE because its the same for all users.
But its weird because on local machine (caching is on i tested) everything runs normal when i want to create a comment... on prod, dev env.
On server it runs normal when i am under dev env.(caching is off) but when i try post comment on prod env. i get error flash message for the mentioned condition...
WTF? Where could be leak please? i have no idea.
The public esi cache somehow breaks my forms? or...?
One friend is able to post a comment there... another one is not.. weird... i wasn't before but after cache clear i am again able...
EDIT:
After lunch i tried it again and i am not able to post comment... wtf..
This is my header i see in chrome: (sending)
CommentForm[comment]:gllll
status_id:65084
CommentForm[_token]:4858119eccbc91da6219d4cbaa1b6c2e79dbd56a
comment_id:0
Using this jquery code:
var url=Routing.generate('create_comment', {"comment_id": comment_id_value, "status_id": status_id_value})+'.json';
$.post(url, $this.serialize(), function(data) {
To this controller:
public function createAction(Request $request, $comment_id=0, $status_id)
{
// first CHECK if user exists
$user=$this->getUser();
if ($user) {
$em=$this->getDoctrine()->getManager();
// GET REPOSITORIES
$statusRepository=$em->getRepository('WallBundle:Status');
$commentRepository=$em->getRepository('WallBundle:Comments');
$notifyRepository=$em->getRepository('NotifyBundle:Notify');
$userRepository=$em->getRepository('UserBundle:User');
// GET SM
$SM=$this->get('status_manager');
// GET status by ID
$status=$statusRepository->find($status_id);
// CHECK if this status exists
if ($status) {
$targetUser=$status->getUser();
if ($request->isMethod('POST') && ($this->getRequest()->getRequestFormat() == 'json')) {
if ($comment_id==0 || !$cE) {
$cE = new Comments();
}
$form = $this->createForm(new CommentFormType(), $cE);
$form->bind($request);
$comment=$form->getData()->getComment();
if ($form->isValid() && $this->checkLastComment($commentRepository,$user,$status, $comment)) {
AND the checkLastComment function
public function checkLastComment($commentRepository, User $user,Status $status, $comment)
{
// check if last comment was more than 10s ago
$lastCommentQueryArray=$commentRepository->getLastComment($user, $status);
$lastCommentTime=0;
$lastCommentContent='';
foreach ($lastCommentQueryArray as $lastComment) {
$lastCommentTime =$lastComment['time'];
$lastCommentContent=$lastComment['comment'];
}
if (($lastCommentTime+10>=time()) && (trim($lastCommentContent)==trim($comment))) {
return false;
}
else {
return true;
}
}
*But the bug should not be in the code because i am using this technique all over the web and everything runs good... only at this particularly page ITS NOT WORKING ... and the only difference between pages is that this one is cached ... + when i am creating a new comment it has nothing with cache isn't that right? it only takes the data from form which is on cached page... *

Redirect after node delete does not delete the node

I am implementing the 'form_alter' hook in Drupal 7. I want to redirect the web to a specific node after deleting any node of type 'article'.
It seems that the proper way of doing so is:
function mymodule_form_alter(&$form, &$form_state, $form_id){
switch ($form_id){
case 'node_delete_confirm':
if($form['#node']->type == 'article'){
$form['actions']['submit']['#submit'][] = '_mymodule_redirect';
}
break;
}
}
function _mymodule_redirect($form, &$form_state){
$form_state['redirect'] = 'node/60';
}
When I put this code in my module it does redirect after confirming the node delete but the node is not actually deleted, if I go to the home page it is still alive!
If I remove the code the node is deleted as expected and the webpage is redirected to the frontpage as usual.
What am I doing wrong?
UPDATE: I forced the 'node_delete_confirm_submit' before the redirect action writing the following line before adding my redirect handler:
$form['actions']['submit']['#submit'][] = 'node_delete_confirm_submit';
This solves the problem.
The easiest way to accomplish this task (and not have to use a hook at all) would be to use the Rules module. It's a nice clean way of performing any number of actions on your site, and I know there's a rule for redirecting the user after content of a certain type is deleted.
Just for clarification I repeat the entire correct answer:
/**
* Implements hook_form_alter()
*/
function MYMODULE_form_alter(&$form, &$form_state, $form_id){
switch ($form_id) {
case 'node_delete_confirm':
// replace 'article' in next line with your node type machine name
if($form['#node']->type == 'article') {
$form['actions']['submit']['#submit'][] = 'node_delete_confirm_submit';
$form['actions']['submit']['#submit'][] = '_MYMODULE_redirect';
}
break;
}
}
function _MYODULE_redirect($form, &$form_state){
// replace 'node/123' in next line with node you like redirect to
$form_state['redirect'] = 'node/123';
}
Doing only $form['actions']['submit']['#submit'][] = '_MYMODULE_redirect'; was not enough. Still $form['actions']['submit']['#submit'][] = 'node_delete_confirm_submit'; needed to be triggered. Now the delete and the redirect are both triggered.

CakePHP HTTPS Secure payment form

Using CakePHP 1.3 we have a booking system for hotel rooms. A check-availability form should bring the user to a secure payment page (https://secure.domain.com/bookings/payment). After making the payment, the user gets a confirmation page (secured is also ok), but from here, any links in our header/footer should take the user back to the non-secured domain (http://domain.com).
Currently we have our SSL UCC Cert set up for the domains https://secure.domain.com and https://domain.com. We have also hard coded the check-availability form to run the action https://secure.domain.com/bookings/payment. Thus, we can get the user to get in to the HTTPS secured area, but not back out unless we hard code all our links in that section.
Cake's security component is quite confusing and thus I am looking for the best solution to make this happen.
Can Cake's Security component be used for HTTPS payment pages, make life easier, and keep the code more CakePHP standardized? Any other suggestions?
this is a pretty good way to go: http://techno-geeks.org/2009/03/using-the-security-component-in-cakephp-for-ssl/ so you won't even have to hard code anything.
I used the example from http://techno-geeks.org/2009/03/using-the-security-component-in-cakephp-for-ssl/ but found it problematic. I ended up adding the following to my app_controller.php.
The code below redirects HTTPS to www.example.com and HTTP to example.com. If a user is logged in (see $loggedUser), it forces HTTPS for every connection.
// Pages requiring a secure connection.
$secureItems = array();
// beforeFilter
function beforeFilter() {
// Your logic...
$this->__checkSSL();
}
/**
* Check SSL connection.
*/
function __checkSSL() {
/** Make sure we are secure when we need to be! **/
if (empty($this->loggedUser)) {
if (in_array($this->action, $this->secureItems) && !env('HTTPS')) {
$this->__forceSSL();
}
if (!in_array($this->action, $this->secureItems) && env('HTTPS')) {
$this->__unforceSSL();
}
} else {
// Always force HTTPS if user is logged in.
if (!env('HTTPS')) {
$this->__forceSSL();
}
}
}
/**
* Redirect to a secure connection
* #return unknown_type
*/
function __forceSSL() {
if (strstr(env('SERVER_NAME'), 'www.')) {
$this->redirect('https://' . env('SERVER_NAME') . $this->here);
} else {
$this->redirect('https://www.' . env('SERVER_NAME') . $this->here);
}
}
/**
* Redirect to an unsecure connection
* #return unknown_type
*/
function __unforceSSL() {
if (strstr(env('SERVER_NAME'), 'www.')) {
$server = substr(env('SERVER_NAME'), 4);
$this->redirect('http://' . $server . $this->here);
} else {
$this->redirect('http://' . env('SERVER_NAME') . $this->here);
}
}

How to get the complete request that calls my MVC2 controller?

Newbie question … sorry ;-)
I have to write and to integrate a new website in a complex web application.
My new (MVC2) website will be hosted on a separate server and only called when the user clicks on a link in the already existing, complex website.
Means I(!) define the URL which calls my(!) new website.
But “they” (the calling, already existing, complex web application/website) will add an attribute to the url. This attribute is the sessionID.
Ok, I think I understand already that this calls my (MVC2) controller.
But how can I get in my (MVC2) controller the “calling URL” (which include the added sessionID)?
Hopefully that someone understand what I ask ;-)
Thanks in advance!
I want just share my little parser - hopefully it helps someone. ;-)
Also requests like
(Request.Url.Query =) "?sessionID=12345678901234567890123456789012&argumentWithoutValue&x=1&y&z=3"
will be well parsed.
Here my code:
Hashtable attributes = new Hashtable();
string query = Request.Url.Query;
string[] arrPairs = query.Split('&'); // ...?x=1&y=2
if (arrPairs != null)
{
foreach(string s in arrPairs)
{
if (!String.IsNullOrEmpty(s))
{
string onePair = s.Replace("?", "").Replace("&", "");
if (onePair.Contains("="))
{
string[] arr = onePair.Split('=');
if (arr != null)
{
if (arr.Count() == 2)
{
attributes.Add(arr[0], arr[1]);
}
}
}
else
{
// onePair does not contain a pair!
attributes.Add(onePair, "");
}
}
}
You really should set your URL and Route to be more MVC-Like. The URL you are calling should be:
newapp/controller/action/sessionId
Then set your route up:
routes.MapRoute(
"sessionId",
"{controller}/{action}/{sessionId}",
new { controller = "controller", action = "action", sessionId = 0 });
Then in your controller:
public ActionResult Action(int sessionId)
{
}
In your controller you still have direct access to the Request object, so you can use Request.Url, etc.
Does that answer your question, or is it something else that you need?