Unable to make Ajax call in Symfony - json

I want to handle user registration via ajax call. So therefore I've created a registration class (defined as a service) which will be loaded in different controllers:
public function loadRegisterForm($request)
{
$user = new User();
$form = $this->createForm(RegistrationType::class, $user, array('attr' => array('class' => 'ajaxRegisterForm',)));
$form->handleRequest($request);
$errors = "";
$parametersArray['result'] = "";
if ($form->isSubmitted())
{
if ($form->isValid())
{
$password = $this->get('security.password_encoder')
->encodePassword($user, $user->getPlainPassword());
$user->setPassword($password);
$user->setIsActive(1);
$user->setLastname('none');
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
$parametersArray['result'] = new JsonResponse(
array(
'message' => 'Success! User registered!',
'result' => $this->renderView('ImmoBundle::security/successlogin.html.twig')
), 400);
}
else
{
$errors = $this->get('validator')->validate($form);
$parametersArray['result'] = new JsonResponse(
array(
'message' => 'Failure! User not registered!',
'result' => $this->renderView('ImmoBundle::security/successlogin.html.twig'),
'errors' => $errors,
), 200);
}
}
$parametersArray['register_form'] = $form;
$parametersArray['errors'] = $errors;
return $parametersArray;
}
Then I've created a main controller, where registration form is being loaded:
/*
* #Route("/", name="MainPageNotPaginated")
*/
public function indexAction(Request $request)
{
/**
* Load register form
*/
$registerForm = $this->get('register_form_service');
$registerFormParameters = $registerForm->loadRegisterForm($request);
return $this->render(
'ImmoBundle::Pages/mainPage.html.twig',
array(
'register_form' => $registerFormParameters['register_form']->createView(),
'errors' => $registerFormParameters['errors'],
'result' => $registerFormParameters['result'],
)
);
}
Further I've added an ajax call to my javascript file:
$('.registerFormContainer').on('submit', '.ajaxRegisterForm', function (e) {
e.preventDefault();
$.ajax({
type: $(this).attr('method'),
url: $(this).attr('action'),
data: $(this).serialize()
})
.done(function (data) {
if (typeof data.message !== 'undefined') {
$('.registerFormContainer').html(data.result);
}
alert('success');
})
.fail(function (jqXHR, textStatus, errorThrown) {
if (typeof jqXHR.responseJSON !== 'undefined') {
$('.registerFormError').html(jqXHR.responseJSON.result);
} else {
alert("fail");
}
});
});
Now, when I submit the registration form without filling in data (which normally should return an error) I've got an 'success' alert. The same 'success' alert is visible when the submitted registration form is valid.
I've tried
console.log(data.message)
but console says 'undefined'.
What am I doing wrong here?

Ok, I've figured it out. I've just added this line to my main controller (not the service one):
if ( $request->isXmlHttpRequest() ) {
return $registerFormParameters['result'];
}

Related

Query Wordpress Database after AJAX Call - Getting an Error of Call to a member function get_results() on null

I am trying to query the WP Database but I am receiving an error of Call to a member function get_results() on null. I believe I need to somehow register wpdb but despite reading through multiple similar questions I can't piece together what needs to be done. Any help is greatly appreciated as I am new and learning Wordpress and Ajax.
My JS file is called zip-search-popup.js
(function($) {
$(document).ready(function() {
$('.zip-bar-button').click(function(event) {
event.preventDefault();
submittedZip = $("#zipcode-bar-input").val();
$.ajax({
//need an automatic URL so that this doesn't need to be updated
url: from_php.ajax_url,
type: "GET",
data: {
action : 'zip_search',
submittedZip : submittedZip,
},
success: function (response) {
console.log(response);
alert("working");
}
})
$('.zip-search-popup-con').fadeToggle(350);
})
$('.zip-search-dismiss').click(function() {
$('.zip-search-popup-con').toggle();
})
})
})(jQuery);
I have registered my scripts in functions.php and have my SQL query function within here as well.
add_action('wp_enqueue_scripts', 'hyix_enqueue_custom_js');
function hyix_enqueue_custom_js() {
//enqueue zip-search-popup.js
wp_enqueue_script('zip-search-popup', get_stylesheet_directory_uri().'/js/zip-search-popup.js', array('jquery'), false, true);
wp_localize_script('zip-search-popup', 'from_php', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
}
//hook zip-search-popup function into ajax
add_action( 'wp_ajax_zip_search', 'ajax_zip_search' );
//same hook for users not logged in
add_action( 'wp_ajax_nopriv_zip_search', 'ajax_zip_search' );
//query for pulling in shipping data
function ajax_zip_search() {
$submitted_zip = $_REQUEST['submittedZip'];
global $wpdb;
// The SQL query
$response = $wpdb-> get_results("SELECT {$wpdb->prefix}woocommerce_shipping_zones.zone_name ".
"FROM {$wpdb->prefix}woocommerce_shipping_zone_locations ".
"INNER JOIN {$wpdb->prefix}woocommerce_shipping_zones ".
"ON {$wpdb->prefix}woocommerce_shipping_zone_locations.zone_id = {$wpdb->prefix}woocommerce_shipping_zones.zone_id ".
"WHERE location_code = '$submittedZip' ");
$response = array(
'request' => $_REQUEST,
'zip' => $submitted_zip,
'test' => 'is ok',
);
wp_send_json( $response );
// echo $response;
die();
}
You should use the Wordpress-Way to use AJAX
All Ajax-Request will be recieved by wp-admin/admin-ajax.php which fires the Ajax-Hooks which run your PHP-Code. The Ajax-Hook depends from the action-parameter in your Ajax-Request.
With wp_localize_script() you can provide some data from PHP to Javascript, i.e. the ajax_url.
Place this code in your functions.php. This include the code that handles your Ajax-Request.
add_action('wp_enqueue_scripts', 'hyix_enqueue_custom_js');
function hyix_enqueue_custom_js() {
//enqueue zip-search-popup.js
wp_enqueue_script('zip-search-popup', get_stylesheet_directory_uri().'/js/zip-search-popup.js', array('jquery'), false, true);
wp_localize_script('zip-search-popup', 'from_php', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
}
add_action( 'wp_ajax_zip_search', 'ajax_zip_search' );
add_action( 'wp_ajax_nopriv_zip_search', 'ajax_zip_search' );
function ajax_zip_search() {
$submitted_zip = $_REQUEST['submittedZip'];
// do some zip search
$response = array(
'request' => $_REQUEST,
'zip' => $submitted_zip,
'test' => 'is ok',
'foo' => 'bar'
);
wp_send_json( $response );
}
Now you can use the ajax_url provided by wp_localize_script(). Don't forget to send an action-parameter:
$.ajax({
url: from_php.ajax_url,
type: "GET",
data: {
action: 'zip_search',
submittedZip: submittedZip
},
success: function (response) {
console.log(response);
alert('it works');
}
});

croogo 2 Request blackholed due to "auth" violation

I have a problem with my old website. Now I try to move it to new server (php5.6) and when i try to save data I have error:
Request blackholed due to "auth" violation.
I serach the place whose do it this error:
if ($this->Node->saveWithMeta($this->request->data)) {
Croogo::dispatchEvent('Controller.Nodes.afterAdd', $this, array('data' => $this->request->data));
$this->Session->setFlash(__('%s has been saved', $type['Type']['title']), 'default', array('class' => 'success'));
if (isset($this->request->data['apply'])) {
$this->redirect(array('action' => 'edit', $this->Node->id));
} else {
$this->redirect(array('action' => 'index'));
}
}
I think error do function saveWithMeta(). This function view like:
public function saveWithMeta(Model $model, $data, $options = array()) {
$data = $this->_prepareMeta($data);
return $model->saveAll($data, $options);
}
Can I replace/edit this function so that it starts to work?
edit
if (!$db->create($this, $fields, $values)) {
$success = $created = false;
} else {
$created = true;
}
These lines cause an error.

How to avoid instant saving of the model with ajax validation?

I want to add Ajax validation to check the form before updating. In the view, added to the required field
['enableAjaxValidation' => true]
In the controller in the actionUpdate
if (Yii::$app->request->isAjax && $modelForm->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
if ($modelForm->validate()) {
$model->setAttributes($modelForm->getAttributes());
if ($model->save()) {
return $this->redirect([my way]);
}
if ($model->hasErrors()) {
return ActiveForm::validate($model);
} else {
return ['success' => 1, 'html' =>
$this->renderPartial('view', [my data];
}
} else {
return ActiveForm::validate($modelForm);
}
}
The problem is that the choice of any value in the field, which is "enableAjaxValidation" => true, immediately leads to the saving of the model (even without pressing the save button). How can this be avoided?
In controller try it like this:
$model = new ExampleForm;
// validate any AJAX requests fired off by the form
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
Add this before your if statement, and remove Yii::$app->request->isAjax from your if statement.
Add some thing like below in your form
$form = ActiveForm::begin([
'id' => 'example',
'action' => ['your_action'],
'validateOnSubmit' => true,
'enableAjaxValidation' => true,
])

Service workers with FCM get data in Chrome

I'm try to implement Push Notifications in Chrome with ServiceWorkers and GCM.
The notifications working fine, but the push function the event is null (self.addEventListener('push', function(event)).
The next is my code and working fine, received the notifications, but don't receive the data.
To register:
<script>
document.addEventListener('DOMContentLoaded', function () {
/*navigator.serviceWorker.getRegistration().then(function(r) {
r.unregister();
});*/
// document.querySelector("#enablepush").addEventListener('click', function (e) {
//if(Notification.permission !== 'granted') {
Notification.requestPermission().then(function (permission) {
if (permission === 'granted' && 'serviceWorker' in navigator) {
navigator.serviceWorker.register('myworker.js').then(initialiseState);
} else {
console.log('service worker not present');
}
});
//}
// });
//get subscription token if already subscribed
if (Notification.permission === 'granted') {
navigator.serviceWorker.ready.then(function (registration) {
registration.pushManager.getSubscription().then(function (subscription) {
getToken(subscription);
});
});
}
});
function SalirPush()
{
console.log("Si registro ha sido cancelado");
navigator.serviceWorker.getRegistration().then(function (r) {
r.unregister();
});
navigator.serviceWorker.ready.then(function (reg) {
reg.pushManager.getSubscription().then(function (subscription) {
subscription.unsubscribe().then(function (successful) {
// You've successfully unsubscribed
}).catch(function (e) {
// Unsubscription failed
})
})
});
}
function initialiseState() {
//check if notification is supported or not
if (!('showNotification' in ServiceWorkerRegistration.prototype)) {
console.warn('Notificaiton are not supported');
return;
}
//check if user has blocked push notification
if (Notification.permission === 'denied') {
console.warn('User has blocked the notification');
}
//check if push messaging is supported or not
if (!('PushManager' in window)) {
console.warn('Push messaging is not supported');
return;
}
//subscribe to GCM
navigator.serviceWorker.ready.then(function (serviceWorkerRegistration) {
//call subscribe method on serviceWorkerRegistration object
serviceWorkerRegistration.pushManager.subscribe({userVisibleOnly: true})
.then(function (subscription) {
getToken(subscription);
var met = JSON.stringify(subscription);
console.log("Mensaje", met);
}).catch(function (err) {
console.error('Error occured while subscribe(): ', err);
});
});
}
function getToken(subscription) {
console.log(subscription);
var token = subscription.endpoint.substring(40, subscription.endpoint.length);
//document.querySelector("#token").innerHTML = token;
try
{
$("#apikey").val(token);
}catch (e)
{
}
}
</script>
Next my workers.js is;
self.addEventListener('push', function(event) {
var url = "/push/json-data.php?param=(This is the event data info)";
event.waitUntil(
fetch(url).then(function(response) {
if (response.status !== 200) {
// Either show a message to the user explaining the error
// or enter a generic message and handle the
// onnotificationclick event to direct the user to a web page
console.log('Looks like there was a problem. Status Code: ' + response.status);
throw new Error();
}
// Examine the text in the response
return response.json().then(function(data) {
if (data.error || !data.notification) {
console.log('The API returned an error.', data.error);
throw new Error();
}
var title = data.notification.title;
var message = data.notification.message;
var icon = data.notification.icon;
return self.registration.showNotification(title, {
body: message,
icon: icon,
data: {
url: data.notification.url
}
});
});
}).catch(function(err) {
console.log('Unable to retrieve data', err);
var title = 'An error occurred';
var message = 'We were unable to get the information for this push message';
var icon = 'img/design19.jpg';
var notificationTag = 'notification-error';
return self.registration.showNotification(title, {
body: message,
icon: icon,
tag: notificationTag
});
})
);
});
// The user has clicked on the notification ...
self.addEventListener('notificationclick', function(event) {
console.log(event.notification.data.url);
// Android doesn't close the notification when you click on it
// See: http://crbug.com/463146
event.notification.close();
// This looks to see if the current is already open and
// focuses if it is
event.waitUntil(
clients.matchAll({
type: "window"
})
.then(function(clientList) {
for (var i = 0; i < clientList.length; i++) {
var client = clientList[i];
if (client.url == '/' && 'focus' in client)
return client.focus();
}
if (clients.openWindow) {
return clients.openWindow(event.notification.data.url);
}
})
);
});
Next to send the Push Notifications, I use this PHP:
<?php
$estado=$_GET["estado"];
$idtoken=$_GET["id"];
$op=$_GET["op"];
if ($op != "")
{
sendFCM("My App","Hi to all", $idtoken,$estado);
}
function sendFCM($titulo,$mess,$id,$estado) {
echo "Recibi: $mess , $id, $estado";
$data = array('status'=> $estado,'mensaje'=>'"'.$mess.'"','titulo'=>'"'.$titulo.'"');
$url = 'https://fcm.googleapis.com/fcm/send';
$fields = array (
'to' => $id,
'notification' => array (
"body" => $mess,
"title" => $titulo,
"icon" => "myicon",
"color"=> "#0000ff",
"sound" => "default"
),
'data' => $data,
'payload' => $data
);
$fields = json_encode ( $fields );
$headers = array (
'Authorization: key=' . "MyGoogleKey",
'Content-Type: application/json'
);
$ch = curl_init ();
curl_setopt ( $ch, CURLOPT_URL, $url );
curl_setopt ( $ch, CURLOPT_POST, true );
curl_setopt ( $ch, CURLOPT_HTTPHEADER, $headers );
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt ( $ch, CURLOPT_POSTFIELDS, $fields );
$result = curl_exec ( $ch );
curl_close ( $ch );
echo ($result);
}
?>
Thanks for your help.
use event.data.json().data in your push event:
self.addEventListener('push', function(event) {
event.waitUntil(
self.registration.pushManager.getSubscription().then(function(subscription) {
console.info(event.data.json().data);
});
);
});

No form errors shown in JsonResponse - Symfony

I have a registration form with fields that are validated in User entity class. The validation works fine, however I can't return JsonResponse with form error messages in it.
My registration form controller method looks like this:
/**
* #Route("/register", name="register")
*/
public function registerAction(Request $request)
{
$user = new User();
$form = $this->createForm(RegistrationType::class, $user);
$form->handleRequest($request);
$errors = "";
if ($form->isSubmitted())
{
if ($form->isValid())
{
$password = $this->get('security.password_encoder')
->encodePassword($user, $user->getPlainPassword());
$user->setPassword($password);
$user->setIsActive(1);
$user->setLastname('none');
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
return new JsonResponse(
array(
'message' => 'Success! User registered!',
), 200);
}
else
{
$errors = ($this->get('validator')->validate($form));
return new JsonResponse(
array(
'message' => 'Not registered',
'errors' => $errors,
), 400);
}
}
return $this->render(
'ImmoBundle::Security/register.html.twig',
array('form' => $form->createView(), 'errors' => $errors)
);
}
I get the following json response when I submit the registration form with invalid data:
{"message":"Not registered","errors":{}}
Actually I'm expecting that "errors":{} will contain some error fields, but it doesn't. Does anyone know what the problem here is?
UPD:
My RegistrationType looks like this:
class RegistrationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('firstname', TextType::class)
->add('email', EmailType::class)
->add('plainPassword', RepeatedType::class, array(
'type' => PasswordType::class,
'first_options' => array('label' => 'Password'),
'second_options' => array('label' => 'Repeat password'),
'invalid_message' => "Passwords don't match!",
))
->add('register', SubmitType::class, array('label' => 'Register'));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'ImmoBundle\Entity\User',
'csrf_protection' => true,
'csrf_field_name' => '_token',
'csrf_token_id' => 'authenticate',
));
}
}
UPD2: Found the solution. I needed to do this iteration and then call for getMessage():
$allErrors = ($this->get('validator')->validate($form));
foreach ($allErrors as $error)
{
$errors[] = $error->getMessage();
}
Form validated when you call $form->handleRequest($request);
To get form errors use getErrors method
$errors = $form->getErrors(true); // $errors will be Iterator
to convert errors object to messages array you can use code from this response - Handle form errors in controller and pass it to twig
This is exapmle how i'm process errors in one of my projects
$response = $this->get('http.response_formatter');
if (!$form->isValid()) {
$errors = $form->getErrors(true);
foreach ($errors as $error) {
$response->addError($error->getMessage(), Response::HTTP_BAD_REQUEST);
}
return $response->jsonResponse(Response::HTTP_BAD_REQUEST);
}
It's worked for me.
And also this can help you - Symfony2 : How to get form validation errors after binding the request to the form
You must set error_bubbling to true in your form type by explicitly setting the option for each and every field.