Reading / Accessing API response while using Ninja Forms Webhooks add-on - javascript

I am using Ninja Forms with Webhooks add-on to submit form data to a third party API. Everything works fine, the data is submitted and I can see a response when running add-on in debug mode.
The question is how do I access an API response so I could use the response data as it returns user ID based on my submitted data. I need to submit that ID to the next page.
My form works as follows:
1. User inputs data
2. Form is submitted to API
3. User is redirected to another page
I need to be able to get user ID from an API response. Thanks!

I realize you've long since moved on from this situation, but for others coming here from search results I have a partial answer.
Checking the Webhooks plugin code, there are several undocumented actions and filters, in particular nf_remote_get and nf_remote_post, both of which are actions that let you do something with the raw response.
function act_on_nf_remote_post_response( $response, $form_id ) {
// output to debug log
error_log( print_r( $response, true ) );
}
add_action( 'nf_remote_post', 'act_on_nf_remote_post_response', 10, 2 );
Unfortunately, it does not pass other data about the submission, only the ID of the form it belongs to, so it would take some gymnastics to store what you need and then reference it in a new page load while also ensuring it's the same user, possibly with some $_SESSION stuff.

Related

Is there a way to send POST data to another form and return the result of that form?

I need to send form data to another page that will allow the user to do something in a form and return the result of that form back to the original page? Is this possible? I know it's not ideal, but the issue is that I need to make a "drop-in" solution that does not need to be integrated with other code. I know it's a very specific request and scenario.
I know how to send POST data that doesn't require any user input on the processing page. i.e. I can send POST data to 'calculate.php' which will do the math and send it back, but if I need additional user input on 'calculate.php', how can I still send it back?
An example of expected results would be:
Page #1: User enters a number and presses submit to go to next page.
Page #2: User enters a second number and presses submit to finish.
Back to Page #1: User receives sum of both numbers.
Obviously, this is a really redundant thing to do, but I'm trying to simplify the problem as much as possible.
EDIT: There a few restrictions I forgot to add.
Page #1 is not my application, I am developing Page #2 as a "drop-in" solution for Page #1. Essentially, I can only use Page #1 to call Page #2 and receive a response from it. The problem is that I need to be able to allow for user input on Page #2.
I know I can post to Page #2 and then post to Page #1 again, but what if I need to maintain the state of Page #1. For example, if there's an open Web Socket connection.
Please note, I understand that this may be impossible or extremely difficult, but if I don't ask I'll never know right?
You want it with PHP or any other language. If you are running Php on server side then you can use Global variables like $_GET and $_POST.
Page #1: Use Post/Get method to send data to second page.
Page #2: Receive all fields' values using Globe variables ($_GET and $_POST). You can use these values as default values of form fields. Now submit this data to page 1 using post or get method.
Back to Page #1: Here you will receive the data of first page from second page and newly posted data from page 2
Either of these should work:
Never leave the page - use AJAX / XMLHttpRequest to call out to other pages to process chunks of data
Do everything on page 1 using "postbacks" -- the form targets are the same page, there is a state variable like "stage=1", and you use JavaScript to add set hidden variables for any additional state that's needed.
... PHP state validation and processing for the different stages ...
... one or more blocks of HTML for the page (PHP if / else can be used to choose between multiple page views) ...
Edit for added restrictions:
Have page 2 use postbacks or AJAX to collect the additional information
I figured out a few ways to do it.
Update a Database (or Data Store of some sort, depends on security needs) and have Page #1 listen for events from a separate page (on the same server as the database). Very similar to the way PayPal's Instant Payment Notification (IPN) works. I was actually able to set up server sent events with it as well.
Essentially, Page #1 sends data to Page #2 where the user will perform the function and then Page #2 will send POST data to a listener somewhere (either on the same server or Page #1's server), the listener will update a database and Page #1 will be listening or pulling to an event handler that will send an update once the database updates.
Use JavaScript Child/Parent Window functions. This is okay if Page #1 and Page #2 are on the same server, but can get messy and browsers have a lot of restrictions and it varies depending on browser.
Page #1 will open Page #2 in a child window, after the user performs a function, Page #2 will call a function that accepts the result data on Page #1.

Insert data into DB with Symfony2 via JavaScript, without a form

I'm currently working on a Symfony2 project where a user can comment on parts of a webpage via contenteditable spans. I now want to save these comments, that are assembled in an array of JSON objects, into the database, with a reference to the page and the user id. This is where I'm stuck.
What steps are needed to put the data from the JavaScript code into the specific DB table?
I already created a Comment class in the Entity folder. And based on this
answer I added the following code in my saveComment() in JavaScript:
$.post('saveComments.php', {
page_id : getPageId(),
user_id : getUserId(),
comments : getJSONcomments(),
});
What next...?
Ok, let's create a saveComments.php ... but where in the bundle? Or could this be done with a Controller? If so, how and what would I need to replace the url ("saveComments.php") in the $.post(...) call with?
Don't post to a PHP page as this breaks the Symfony 2 model. Instead post to a route, like save/comment or along these lines.
Configure the route to point to an action in a controller.
Implement the controller and the action so that it does not take any parameters. Inside the action unpack the posted data the usual PHP way using (because you won't have a form to bind your data to):
$_POST
Just to get it working, echo a var_dump() to the console and see what you get. This is an example on how to write to the console.
Decode the JSON data with the serializer.
The decoded data will be a simple associative PHP array. Interpret the data you received and act accordingly (don't forget to handle security and all that stuff, too -- you don't want to open up security holes through AJAX).
Best is, you check that the route you chose falls into the security tier you need and probably already have configured in the Symfony 2 application. This way you don't need to handle security manually in the action.
Once this is done return an HTTP response with code 200 OK.
return new Response('', Response::HTTP_OK); // no response text at all
If there's any error reply with a 500 class HTTP server error:
return new Response('', Response::HTTP_INTERNAL_SERVER_ERROR); // 500
Also, don't forget to handle client-side errors with the .error() method.

Preventing Duplicate Form Submissions Without JS

I am working on a project and i am building it using the mvc pattern. On successful form submission i redirect user and display a flash message ( success message using session ) i have no issues with users using the back button or refreshing. But if a user encounters an error when submitting a form the form is not redirected so the error can be displayed while keeping old form data to populate the field so users do not have to re-enter information.
The issue i am having is when users will spam the button for any reason. If i double click or spam the button an error is produced ( invalid form token error ) but the db interaction still takes place and inserts the form data. I am trying to find the best js alternative to maintain cross browser compatibility. Is js the way to go? Is their a php alternative?
As you are using session vars, why not set a variable just after your DB update takes place. Then before every DB update check for this value. If false then update DB.
function updateDB(){
if($_SESSION['already_submitted'] == true) return false;
// DB update code
// on success
$_SESSION['already_submitted'] = true
// rest of code
}

How to set a PHP object in session upon a hyperlink click

I have two PHP pages: One displays the information about an object retrieved from MySQL database and the other allows the user to edit it. The user is transferred from the first page (the view page) to the edit page upon clicking a hyperlink.
I would like to set the information retrieved from the database in session before passing on to the edit page so as to avoid an extra database call. How can I set an object in session upon a hyperlink click event? I know I could append the object as a variable to the GET request but is there a cleaner way than that?
Put the object into the session ($_SESSION['object'] = $object) when the page one loads (or when you retrieve the object from the database). This way you avoid a second call to the database. If you want to place it into the session upon the click event, a second call would be necessary, since you would have to make an AJAX call to a PHP script that retrieves the object. However, this may only make sense if the user is expected to edit that information, otherwise it is just storing data into sessions for no reason, which may also expose security bugs. If your database call doesn't retrieve millions of records, or you don't have hundreds of millions of users editing data in the same time, I can assure you that the impact on the performance by making a second call will go unnoticed.
Adding an object to the session:
$_SESSION['the_object'] = $object;
(Disclaimer: Will not work if the object contains any non-serializable components like closures)
Now when to do it? Actually, you have to do it on the page that shows the data, because if you do it later when the user clicks the edit link, this already triggers a new request which then would again go to the database - you'd have two requests (one for the list, one for the edit).
Generally, the edit link has the ID of the database entry to be edited. But pay attention to carefully check whether the user is allowed to have access or not, because MySQL will simply increment the ID, so it's easy to guess which IDs are valid. Anyone with a tiny bit of clue can modify a HTML form to tamper with IDs.
The approach with the session is somewhat easier: You only allow to edit what has been stored in the session, so the access control has to be done on the list page only.
For those who may be looking for a code snippet to help do this - here it is
Page 1 - this page just loads data from a DB and displays it in a non-editable mode on the screen. On this page we need an Javascript function that can be activated when the hyperlink is clicked
<script language="JavaScript" type="text/javascript">
function processEditLink(){
$.post('process_session_put.php', <?php echo "{S-Object:'".json_encode($obj_)."'});"; ?>
window.location.href = 'edit_object.php';
}
</script>
To explain the above code - we are taking an object (referred to as obj_) and encoding it into the JSON version by using the inbuilt function json_encode. Remember to ensure your object implements JsonSerializable in order to accomplish this. After that we are passing that JSON string as a POST URI parameter via AJAX to a secret page called process_session_put.php. This call is never visible to the end user and happens secretly when the hyperlink is clicked. The secret PHP page will decode the JSON string back into the PHP object and put it in session for all to use. Finally, once that function is complete, the window redirects to the actual edit page that can access data from session and populate the screen.
Next we should modify the hyperlink to trigger this Javascript function when it is clicked as below
<a class="edit-link" href="javascript:processEditLink(this);return false;">[Edit]</a>
Finally - the PHP page called process_session_put.php - which actually does the background work of decoding the JSON string passed to it back into the object format and putting it in session
<?php
if (!isset($_SESSION))
{
session_start();
}
// OBTAIN THE JSON STRING FROM POST URL, DECODE IT AND PUT IT BACK AS A OBJECT IN SESSION
$_SESSION["E-Object"] = json_decode($_POST["S-Object"]);
?>

ajax and local/session storage pattern

I'm building a web app that uses ajax to communicate with the server. Basically, the user requests a record, it comes back in json, it's added to the DOM and the user makes changes to it. When the user requests the next record, the current record is stringified and sent back to the server and the following record comes back.
All this works really well.... as long as the user keeps requesting records. However, I am wondering how to handle the situation where the user stops his work: how do I get the last record updated?
I thought of adding the working record to the local storage while he's editing it and at each edit, updating the local storage and if he logs on next time and there's still a record in there, ajax it when he logs on. The problem with his approach is that if another user logs on to the same computer, then when that new user logs on, he's updating the data of another user.
I thought of using the window.unload event also; but that doesn't solve the problem of the user closing his browser before the final update.
What are some good ways to handle this issue. Thanks for your suggestions.
I would consider a 'draft-like' feature. Where you could upload changes after a certain amount of time of no input, for instance, after 15 seconds of no input, push those changes.
If your app requires login, you could key the localStorage using their ids like so:
localStorage.getItem( "user13434" )
would retrieve data for user13434
localStorage.getItem( "user12345" )
would retrieve data for user12345
If the information is sensitive but not too sensitive you could add encryption, but it can be decrypted by experienced users which is why it must not be too sensitive.

Categories

Resources