I was writing a simple login form, everything works fine (validation etc.) but I can't get the values, there's my code:
public function executeIndex(sfWebRequest $request)
{
$this->getUser()->clearCredentials();
$this->getUser()->setAuthenticated(false);
$this->form = new LoginForm();
if ($request->isMethod('post') && $request->hasParameter('login')) {
$this->form->bind($request->getParameter('login'));
if ($this->form->isValid()) {
$this->getUser()->setAuthenticated(true);
$this->getUser()->addCredential('user');
$this->login = $this->form->getValue('login');
}
}
}
$this->login is NULL. Now I checked almost everything, the form is valid, isBound() is true, count() returns 3, I can see the values in my request:
parameterHolder:
action: index
login: { login: foo, password: foo, _csrf_token: 53ebddee1883d7e3d6575d6fb1707a15 }
module: login
BUT getValues() returns NULL, getValue('login') etc. returns NULL as well. How can it be?
And no, I don't want to use sfGuard-Plugins ;)
What about trying something like this
$form['value_name']->getValue()
Is it still NULL?
Also is it possible that you created a custom post validator?
Callback validation must return values back to caller:
return $values;
Related
I've developed a CI site on my local machine using WAMP. I'm using CI 3 with the HMVC extension and it all works fine.
I've just uploaded the site to the production server and changed the config files etc to get it working. However, form validation callbacks are not working on the production server.
Here's an example from a login form:
// Process login form
public function submit()
{
$this->load->library('form_validation');
$username = $this->input->post('username', TRUE);
$this->form_validation->set_rules('username', 'Username', 'required');
$this->form_validation->set_rules('password', 'Password', 'required|callback_do_login');
if($this->form_validation->run($this) == FALSE)
{
$this->login();
}
else
{
// Set login session
...
}
}
This is the callback function do_login:
public function do_login($password)
{
// Get user / pass from POST
$submitted_password = $this->input->post('password', TRUE);
$username = $this->input->post('username', TRUE);
$this->crud->setTable($this->table);
$this->load->model('mdl_users');
// Check User Exists
$query = $this->mdl_users->getUser($username);
if($query->num_rows() == 1)
{
// Get stored password
$row = $query->row();
$stored_password = $row->password;
// Check password
$this->load->module('mod_security');
$result = $this->mod_security->login($username, $submitted_password, $stored_password); // Returns false if no match
return ($result) ? TRUE : FALSE;
}
else
{
return FALSE;
}
}
On my local WAMP setup, this all works fine. But on the server
$this->form_validation->run($this)
always returns false.
To eliminate any errors with the callback function itself, I changed it to the following as a test:
public function do_login($password)
{
return TRUE;
}
... which will obviously always return TRUE, however when $this->form_validation->run($this) is called, even though I changed the do_login callback function to return TRUE, $this->form_validation->run($this) still returns FALSE!!
This is driving me crazy and I have no idea why this is happening. It is as if the form validation is ignoring the callback function and just returning false.
Can anyone help me? Could it be a setting on the server causing it or something else that could have changed when I uploaded the site files to the server?
If it is relevant, on my local machine, within the do_login callback function I had originally set the callback error message like this:
$this->form_validation->set_message('do_login', 'User / Pass Incorrect');
...which worked fine, but on the production server it threw an error stating: "Unable to access an error message corresponding to your field name Password.(do_login)". I had to set the error message in the language library file to overcome this. But the fact that this happened on the production server and not on my WAMP setup makes me think there must be some setting or something on the server that is causing this.
Anyway, any help is gratefully received.
Thanks
I finally found the solution. The HMVC application requires a small library file named as MY_Form_validation.php. Seemingly everywhere on the net this file is shown to be thus:
class MY_Form_validation extends CI_Form_validation {
function run($module = '', $group = '')
{
(is_object($module)) AND $this->CI = &$module;
return parent::run($group);
}
}
However, although this worked in my WAMP setup, it did not work on my server. I found that by declaring the CI variable at the start the server problem is resolved. So the MY_Form_validation.php file finally becomes:
class MY_Form_validation extends CI_Form_validation {
public $CI;
function run($module = '', $group = '')
{
(is_object($module)) AND $this->CI = &$module;
return parent::run($group);
}
}
I have api controller and it logout method
public function logoutAction()
{
if(!$this->getRequest()->isPost())
{
$response= $this->getResponse();
$response->setHttpResponseCode(406);
return $this->_helper->json->sendJson(array('status'=>'false'));
}
else
{
$data=$this->_request->getParams();
}
}
When i posting id with some value(assume we take id= 5) then $data['id'] value showing wrong value 5id=5 instead of only 5.
But when i posting multiple parameter with value like id=5,name=abc etc then id value display true value 5.I need to post only one id.help please ...thanks
I had a small test done in PHP for a Controller I had written in Symfony2:
class DepositControllerTest extends WebTestCase {
public function testDepositSucceeds() {
$this->crawler = self::$client->request(
'POST',
'/deposit',
array( "amount" => 23),
array(),
array()
);
$this->assertEquals(
"Deposit Confirmation",
$this->crawler->filter("title")->text());
}
}
Up to here, everything was great. Problem started when I realized I wanted to disable possible re-submissions while refreshing the page. So I added a small mechanism to send nonce on every submission.
It works something like this:
class ReplayManager {
public function getNonce() {
$uid = $this->getRandomUID();
$this->session->set("nonce", $uid);
return $uid;
}
public function checkNonce($cnonce) {
$nonce = $this->session->get("nonce");
if ($cnonce !== $nonce)
return false;
$this->session->set("nonce", null);
return true;
}
}
So I had to mofidy the controller to get the nonce when displaying the form, and consume it when submitting.
But now this introduces a problem. I cant make a request to POST /deposit because I dont know what nonce to send. I thought to requesting first GET /deposit to render the form, and setting one, to use it in the POST, but I suspect Symfony2 sessions are not working in PHPUnit.
How could I solve this issue? I would not want to go to Selenium tests, since they are significant slower, not to mention that I would have to rewrite A LOT of tests.
UPDATE: I add a very simplified version of the controller code by request.
class DepositController extends Controller{
public function formAction(Request $request){
$this->replayManager = $this->getReplayManager();
$context["nonce"] = $this->replayManager->getNonce();
return $this->renderTemplate("form.twig", $context);
}
protected function depositAction(){
$this->replayManager = $this->getReplayManager();
$nonce = $_POST["nonce"];
if (!$this->replayManager->checkNonce($nonce))
return $this->renderErrorTemplate("Nonce expired!");
deposit($_POST["amount"]);
return $this->renderTemplate('confirmation.twig');
}
protected function getSession() {
$session = $this->get('session');
$session->start();
return $session;
}
protected function getReplayManager() {
return new ReplayManager($this->getSession());
}
}
I'm not sure what ReplayManager does, but it looks to me as if it is not the right class to handle the 'nonce'. As the 'nonce' is ultimately stored in and retrieved from the session it should either be handled by the controller or abstracted out into its own class which is then passed in as a dependency. This will allow you to mock the nonce (sounds like a sitcom!) for testing.
In my experience problems in testing are actually problems with code design and should be considered a smell. In this case your problem stems from handling the nonce in the wrong place. A quick refactoring session should solve your testing problems.
It is possible to access the Symfony2 session from PHPUnit via the WebTestCase client. I think something like this should work:
public function testDepositSucceeds() {
$this->crawler = self::$client->request(
'GET',
'/deposit',
);
$session = $this->client->getContainer()->get('session');
$nonce = $session->get('nonce');
$this->crawler = self::$client->request(
'POST',
'/deposit',
array("amount" => 23, "nonce" => $nonce),
array(),
array()
);
$this->assertEquals(
"Deposit Confirmation",
$this->crawler->filter("title")->text());
}
EDIT:
Alternatively, if there is a problem getting the nonce value from the session, you could try replacing the two lines between the GET and POST requests above with:
$form = $crawler->selectButton('submit');
$nonce = $form->get('nonce')->getValue(); // replace 'nonce' with the actual name of the element
I need help for this problem:
In my Drupal 7 site i need to perform a redirect to a certain page if the login form is invalid, only in this occasion, and only for login form.
What is the best way to do this? what function is called?
Thanks in advance.
You have to use hook_form_alter and add or alter the #validate options. Prefer the second method:
function MYMODULE_form_alter(&$form, $form_state, $form_id) {
if ($form_id == 'user_login') {
$form['#validate'][] = 'MYMODULE_user_login_form_validate';
}
}
function MYMODULE_user_login_form_validate($form, &$form_state) {
// Do some validation here. Better take the same codes from the validation functions below.
if (...) {
drupal_goto('CUSTOM_PATH');
}
}
You can find the validation functions inside ROOT/modules/user/user.module file line 2113:
function user_login_default_validators() {
return array('user_login_name_validate', 'user_login_authenticate_validate', 'user_login_final_validate');
}
Similar questions:
(6.x, although it is the same) Drupal Modify Login System
https://drupal.stackexchange.com/questions/22952/custom-validation-for-a-form
using hook_user_login method you can achieve the same,
/**
* Implements hook_user_login();
*/
function MODULE_NAME_user_login(&$edit, $account) {
$url = 'PAGE_TO_BE REDIRECTED';
if (isset($user->uid) && $user->uid > 0) {
drupal_goto($url);
}
}
I want to redirect people to a certain page if the form validations fails. However, I can’t quite figure out how.
If i redirect people at the REDIRECT HERE comment below, it also redirects when it loads up the form and causes a endless loop.
public function create() {
$this->form_validation->set_rules('email_adress', 'E-mail', 'required|valid_email|is_unique[users.email_adress]');
if ($this->form_validation->run() !== FALSE) {
// PASSED
}
else {
// REDIRECT HERE
}
$this->load->view('user_register_view');
}
How can I achieve this?
You would redirect like so:
redirect('insert_URI_here');
Or if you are passing it to another method in the same controller you could just do :
$this->method_name();
However, if you just drop that in your else statement, user_register_view will not load because $this->form_validation->run() will return false either on validation error or non submission of the form.
What you will have to do is add another check to look for validation errors. If validation has failed and there are no validation errors, then your form hasn't been submitted.
So you could do something like this:
public function create() {
$this->form_validation->set_rules('email_adress', 'E-mail', 'required|valid_email|is_unique[users.email_adress]');
if(($this->form_validation->run() == FALSE) && ($this->form_validation->error_string() == ''));
//form not submitted yet
$this->load->view('user_register_view');
else if ($this->form_validation->run()) {
// PASSED
} else {
//Validation errors
redirect('insert_URI_here');
}
}
You will have to play around with it. I think $this->form_validation->error_string() should return an empty string if not submitted, but it might be a null value or a false (sorry can't remember off the top of my head).