I have a simple contact form with several required fields which is working fine. I am trying to add reCaptcha to the form for some added spam protection.
I have the reCaptcha displaying on the form correctly, I have my keys installed. In my controller I can call the recaptcha_check_answer method and get back valid responses. I have all of the files installed and configured correctly as I can use the methods from the recaptcha class and get back good responses.
My issue is that I would like to have an invalid reCaptcha trigger a CI form_validation error but I have spent alot of time on this and cannot get it to trigger. I am pretty new to CI so pardon my ignorance if this is something easy.
I have tried to throw a form_validation error when the is_valid response comes back NULL. If NULL then I tried to do the following:
$this->form_validation->set_message('recaptcha_response_field', 'reCaptcha', lang('recaptcha_incorrect_response'));
echo form_error('recaptcha_response_field');
Here is what the reCaptcha API responses look like for Valid and Invalid captcha's:
Valid = stdClass Object ( [0] => is_valid [1] => error [is_valid] => 1 )
Invalid = stdClass Object ( [0] => is_valid [1] => error [is_valid] => [error] => incorrect-captcha-sol )
Here is the code I have in my Controller:
class Contact extends CI_Controller
{
function __construct()
{
parent::__construct();
}
public function index()
{
$this->load->library('recaptcha');
$this->recaptcha->set_key ('MY_PUBLIC_KEY_HERE' ,'public');
$this->recaptcha->set_key ('MY_PRIVATE_KEY_HERE' ,'private'); // For private key
// Is this a Form Submission?
if (!empty($_POST))
{
// LOAD VALIDATION AND SET RULES
$this->load->library('form_validation');
$this->load->helper('form');
$this->form_validation->set_rules('first_name', 'First Name', 'required');
$this->form_validation->set_rules('last_name', 'Last Name', 'required');
$this->form_validation->set_rules('email', 'Email', 'required|valid_email');
$this->form_validation->set_rules('recaptcha_response_field', 'reCaptcha', 'required|recaptcha_check_answer');
$this->_resp = $this->recaptcha->recaptcha_check_answer ( $this->input->ip_address(), $this->input->post('recaptcha_challenge_field',true), $this->input->post('recaptcha_response_field',true));
// If the reCaptcha doesnt match throw an form_valiation Error
if ($this->_resp->is_valid == '')
{
$this->form_validation->set_message('recaptcha_response_field', 'reCaptcha', lang('recaptcha_incorrect_response'));
echo form_error('recaptcha_response_field');
}
if ($this->form_validation->run() !== FALSE)
{
// SUCCESS NO ERRORS - SEND EMAIL DATA AND RETURN TO HOME
$this->load->library('email'); // LOAD EMAIL LIBRARY
$config['protocol'] = 'sendmail';
$config['mailpath'] = '/usr/sbin/sendmail';
$config['charset'] = 'utf-8';
$config['wordwrap'] = TRUE;
$this->email->initialize($config);
$this->email->from($this->input->post('email'), $this->input->post('first_name').' '.$this->input->post('last_name'));
$this->email->to('jassen.michaels#gmail.com');
$this->email->cc('');
$this->email->bcc('');
$this->email->subject('Contact Email From Spider Design Website');
$this->email->message(
'First Name: '.$this->input->post('first_name')."\r\n".
'Last Name: '.$this->input->post('last_name')."\r\n".
'Company: '.$this->input->post('company')."\r\n".
'Location: '.$this->input->post('location')."\r\n"."\r\n".
'I am interested in learning: '."\r\n"."\r\n".
'Information Architecture: '.$this->input->post('information_architecture')."\r\n".
'Web Design: '.$this->input->post('web_design')."\r\n".
'Graphic Design: '.$this->input->post('graphic_design')."\r\n".
'Email Marketing: '.$this->input->post('email_marketing')."\r\n".
'Social Media: '.$this->input->post('social_media')."\r\n".
'Content Management: '.$this->input->post('content_management')."\r\n".
'Search Engine Optimization: '.$this->input->post('seo')."\r\n".
'Web Traffic Analytics: '.$this->input->post('wta')."\r\n"."\r\n".
'Preferred Method of Contact: '."\r\n".
'Phone: '.$this->input->post('phone')."\r\n".
'Email: '.$this->input->post('email')."\r\n"."\r\n".
'Comments: '."\r\n".
$this->input->post('comments')
);
//$this->email->send();
//$this->load->helper('url');
//redirect('http://sdi.myspiderdesign.com/fuel');
}
}
// Not a form submission, load view
$this->load->helper('form');
$this->load->view('include/spider_header');
$this->load->view('contact'); // Content Area
$this->load->view('include/spider_footer'); // Footer
}
}
I have commented out the redirects and contact email at the bottom of the form until I can troubleshoot this issue.
Thanks in advance for all your help!
I used the callback_ function within the form_validation library. Setup an additional function inside the controller that made the API call and if the captcha did not pass it would throw a validation_error.
Related
hoping someone can help me solve this problem, thanks a lot for providing the solution
i recently had a problem with my library called my_form_validation on codeigniter version 3. i don't know why it can enter validation true even though it was wrong in function photo check
I have done several options but none of the results I want. my example already used the callback it's the same
example code controller
public function validation_photo()
{
// load custom library Validation
$this->my_form_validation->config_photo();
$this->my_form_validation->photo_checker($_FILES['photo']);
// Conditional validation form
if ($this->form_validation->run() == FALSE) {
// does not pass validation
$data['Title'] = 'Profile';
$data['Content'] = 'management/V_Profile';
$this->load->view('dinamis/Layout', $data);
} else {
// passed validation
var_dump('passed');
}
}
the code above is my loading from my_form_validation library which works for configuring and validating the upload format
example code my_form_validation (config_photo)
function config_photo()
{
$ci = get_instance();
$config = array(
array(
'field' => 'photo',
'label' => 'photo',
'rules' => 'photo_checker',
),
);
$ci->form_validation->set_rules($config);
}
the code above is to set the rules to be used, I use photo_checker
example code my_form_validation (photo_checker)
function photo_checker($photo)
{
$ci = get_instance();
$allowed_mime_type_arr = array('image/jpeg', 'image/png', 'image/x-png', 'image/jpg');
$mime = $photo['type'];
if (in_array($mime, $allowed_mime_type_arr)) {
return TRUE;
} else {
$ci->form_validation->set_message('photo_checker', 'Please select a supported format (jpeg,png,jpg).');
return FALSE;
}
}
The above code is for validating if it doesn't match the desired format then it returns false with the message set
very very thank you very much for helping me.
I hope this issue gets resolved well in this forum, I'm sure there are really great people here
I try to ajaxify the Drupal 8 Mailchimp SignUp Block but I stuck with the AjaxResponse.
This is my Form alter hook:
function mailchimp_ajax_form_form_alter(&$form, \Drupal\Core\Form\FormStateInterface &$form_state, $form_id) {
if ($form_id != 'mailchimp_signup_subscribe_block_form') {
return;
}
$form['submit']['#ajax'] = [
'callback' => 'mailchimp_ajax_form_callback',
'prevent' => 'click',
'progress' => array(
'type' => 'throbber',
'message' => t('Submitting data...')
)
];
}
This is my callback function:
function mailchimp_ajax_form_callback(array &$form, \Drupal\Core\Form\FormStateInterface $form_state) {
$response = new \Drupal\Core\Ajax\AjaxResponse();
$response->setContent('Response');
return $response;
}
But in Chrome console there is only an error:
Uncaught AjaxError:
An AJAX HTTP error occurred.
HTTP Result Code: 200
Debugging information follows.
Path: /node?ajax_form=1
StatusText: OK
ResponseText: Response
The Signup works, but my question is how can I get the mailchimp response and put it in a valid AjaxResponse?
First, the AjaxResponse object has a setData() method not setContent().
To actually subscribe someone to mailchimp through the Drupal module you can use the mailchimp_subscribe() function in the main mailchimp module.
My "working" solution now is:
alter the form block, add an ajax callback function, prevent click and adds some ajax progress visualization.
/**
* Implements hook_form_FORM_ID_alter()
*
* #param \Drupal\mailchimp_signup\Form\MailchimpSignupPageForm $form
* #param \Drupal\Core\Form\FormStateInterface $form_state
* #param $form_id
*/
function mailchimp_ajax_form_form_alter(&$form, \Drupal\Core\Form\FormStateInterface &$form_state, $form_id) {
if ($form_id != 'mailchimp_signup_subscribe_block_form') {
return;
}
$form['submit']['#ajax'] = [
'callback' => 'mailchimp_ajax_form_callback',
'prevent' => 'click',
'progress' => array(
'type' => 'throbber',
'message' => t('Submitting data...')
)
];
}
This is the Ajax Callback:
I create a new AjaxResponse Object and an array of the Drupal messages via drupal_get_messages(). Then some kind of hack to get the right message.
and add an ReplaceCommandObject which replaces the form with the Mailchimp message.
function mailchimp_ajax_form_callback(array &$form, \Drupal\Core\Form\FormStateInterface $form_state) {
$response = new \Drupal\Core\Ajax\AjaxResponse();
$messages = drupal_get_messages();
$message = $messages['status'][0];
if(!$message){
$message = $messages['warning'][0];
}
$response->addCommand(new \Drupal\Core\Ajax\ReplaceCommand('#mailchimp-signup-subscribe-block-form', $message));
return $response;
}
I think there are much more elegant ways to get this.
I still don't know why the submitForm Method of The Mailchimp Form is still invoked...
The AJAX option is committed to the module, you can find it here: https://www.drupal.org/project/mailchimp/issues/2721249
After applying the patch or using the version that includes it, you'll find a checkbox in the form configuration to enable the AJAX in it.
wondering if anyone can guide me to what ive done wrong (or need to do) and think the problem is in my routes file. When the user is displayed the login form and for example they get their username wrong after submit the url displays as this: http://localhost:8888/codeigniter/login/login_validation. When the are successful and log into the admin area (which pulls news articles from the db) this url is still shown. I am wondering if there is a way to make it to http://localhost:8888/codeigniter/news. I have looked in my routes folder and i tried to use 'wildcards' and was unsuccessful. Here is my code for reference, any other info or files needed let me know! Thanks.
CONTROLLER:
class Login extends CI_Controller {
public function __construct() {
parent::__construct();
}
public function index() {
$this->load->view('login');
}
//Validate login area
public function login_validation() {
$this->load->library('form_validation');
$this->form_validation->set_rules('username', 'Username', 'trim|required|xss_clean|callback_username_check');
$this->form_validation->set_rules('password', 'Password', 'required|xss_clean|callback_password_check');
if($this->form_validation->run() == FALSE) {
//Field validation failed. User redirected to login page
$this->index();
}else{
$this->load->model('user_model');
$query = $this->user_model->login_details();
// if the user's credentials validated...
if($query) {
$data = array(
'username' => $this->input->post('username'),
'is_logged_in' => true
);
$this->session->set_userdata($data);
redirect('news');
}else{
$data['error'] ="Invalid Username or Password";
$this->load->view('login',$data);
}
}
}
function logout() {
$this->session->sess_destroy();
$this->index();
}
}
login_details function from user_model.php
function login_details() {
$this->db->where('username', $this->input->post('username'));
$this->db->where('password', md5($this->input->post('password')));
$query = $this->db->get('login');
if($query->num_rows == 1){
return true;
}
}
If you're logging into any kind of system, you're going to need to store a session using CodeIgniter's Session class. Provided controllers/news.php exists, you can set the session and immediately just perform a redirect with redirect('news');. No need to $this->load->view() because this logic will be in news.php's index anyway and you'd be duplicating code.
I'm not sure what $this->user_model->login_details() is returning, but I'm assuming false or null because you say CodeIgniter is sending you back to the login view. Head into the login_details() function and make sure things are working properly (you might want to post it too). Also, post your routes.php file for us if you made changes just in case.
On a side note: Space is a valid password character, don't trim it or folks with leading or trailing space's in their passwords won't be able to get in ;)
I need to set up the validation rules to validate the related items on a specific object, ie: A user can have no more than 3 products related to it.
I believe DataMapper can check for this validation using _related_max_size rule, but I can't figure out how to use it on the $validation array in the model.
So far I've tried this in both my user and product models:
var $validation = array(
'product' => array(
'rules' => array('max_size' => 3)
)
);
Can somebody show me an example on how to set up this at the model, controller and finally the view?
Edit: What I mean is, a user has many products, and can create a certain amount of them, let's say 3 products, when that amount is reached, the user can no longer create products, and this validation rule should not permit the user to create more products.
This would be the DB Schema:
Users table
------------------
id | username |
------------------
Products table
------------------------
id | user_id | name |
------------------------
More info here: http://codeigniter.com/forums/viewthread/178045/P500/
Thanks!
EDIT:
Ok, I got it all working now… Except, I need to do the following:
var $validation = array(
'product' => array(
'label' => 'productos',
'rules' => array('required','max_size' => $products_limit)
)
);
The $products_limit comes from the “plan” the user has associated, and it’s stored in the session when the user logs in. When I try to run this I get:
Parse error: syntax error, unexpected T_VARIABLE in /var/www/stocker/application/models/user.php on line 11
Is there any way to make this setting dynamic?
In model
var $validation = array(
array(
'field' => 'username',
'label' => 'Username',
'rules' => array('required')
)
);
In controller. $this -> $object = new Your_model();
$object->validate();
if ($object->valid)
{ $object->save();
// Validation Passed
}
else
{ $data['error'] = $object->error;
// Validation Failed
}
In view.
echo $error->field_name
I never use Codeigniter before, but give me a chance to help you. So far I didn't found any built-in validation in Code-igniter (correct me if I'm wrong).
One workaround that I could think of is to Callback:Your own Validation Functions. Below is a snip. Pardon me if it didn't work as you want.
In Model: (create something like)
function product_limit($id)
{
$this->db->where('product_id',$id);
$query = $this->db->get('products');
if ($query->num_rows() > 3){
return true;
}
else{
return false;
}
}
In controller: (create something like)
function productkey_limit($id)
{
$this->product_model->product_exists($id);
}
public function index()
{
$this->form_validation->set_rules('username', 'Username', 'callback_product_limit');
}
For more information Please refer to the manual page which gives more complete. I am also new to CodeIgniter. But I hope this helps you, not complicate you.
First, set up a custom validation rule in libraries/MY_Form_validation.php
If the file doesn't exist, create it.
Contents of MY_Form_validation.php:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Form_validation extends CI_Form_validation
{
function __construct($config = array())
{
parent::__construct($config);
}
function valid_num_products()
{
//Perhaps it would be better to store a maxProducts column in your users table. That way, every user can have a different max products? (just a thought). For now, let's be static.
$maxProducts = 3;
//The $this object is not available in libraries, you must request an instance of CI then, $this will be known as $CI...Yes the ampersand is correct, you want it by reference because it's huge.
$CI =& get_instance();
//Assumptions: You have stored logged in user details in the global data array & You have installed DataMapper + Set up your Product and User models.
$p = new Product();
$count = $p->where('user_id', $CI->data['user']['id'])->count();
if($count>=$maxProducts) return false;
else return true;
}
}
Next, set up your rule in config/form_validation.php.
Contents of form_validation.php
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
$config = array
(
'addProduct' => array
(
array
(
'field' => 'name',
'label' => 'Product Name',
'rules' => 'required|valid_num_products'
)
)
);
Next, set up your error message in language/english/form_validation_lang.php. Add the following line:
$lang['valid_num_products'] = "Sorry, you have exceeded your maximum number of allowable products.";
Now in the Controller, you'll want something along the lines of:
class Products extends MY_In_Controller
{
function __construct()
{
parent::__construct();
$this->load->library('form_validation');
}
function add()
{
$p = $this->input->post();
//was there even a post to the server?
if($p){
//yes there was a post to the server. run form validation.
if($this->form_validation->run('addProduct')){
//it's safe to add. grab the user, create the product and save the relationship.
$u = new User($this->data['user']['id']);
$x = new Product();
$x->name = $p['name'];
$x->save($u);
}
else{
//there was an error. should print the error message we wrote above.
echo validation_errors();
}
}
}
}
Finally, you might wonder why I've inherited from MY_In_Controller. There is an excellent article written by Phil Sturgeon over on his blog entitled Keeping It Dry. In the post he explains how to write controllers that inherit from access-controlling Controllers. By using this paradigm, controllers that inherit from MY_In_Controller can be assumed to be logged in, and the $this->data['user']['id'] stuff is therefore assumed to be available. In fact, $this->data['user']['id'] is SET in MY_In_Controller. This helps you seperate your logic in such a way that you're not checking for logged in status in the constructors of your controllers, or (even worse) in the functions of them.
Please please please can someone help me
$this->load->library('form_validation');
$this->load->helper('cookie');
$data = array();
if($_POST) {
// Set validation rules including additional validation for uniqueness
$this->form_validation->set_rules('yourname', 'Your Name', 'trim|required');
$this->form_validation->set_rules('youremail', 'Your Email', 'trim|required|valid_email');
$this->form_validation->set_rules('friendname', 'Friends Name', 'trim|required');
$this->form_validation->set_rules('friendemail', 'Friends Email', 'trim|required|valid_email');
// Run the validation and take action
if($this->form_validation->run()) {
echo 'valid;
}
}
else{
echo 'problem';
}
Form validation is coming back with no errors can cany one see why?
Is it actually echoing 'valid'? (you're missing an apostrophe there, btw)
The code you show will only echo 'problem' when $_POST is false, not when validation fails.
Without knowing more, it may be as simple as:
// Run the validation and take action
if($this->form_validation->run()) {
echo('valid');
} else {
echo('invalid');
}
Try like this without checking if $_POST is set - not really needed:
//validation rules here
//
if ($this->form_validation->run() == TRUE) {
//do whatever that shall be run on succeed
} else {
$this->load->view('form'); //load the form
}
Read more about the controller part here