Drupal 6 - ignore required form field - forms

I need to ignore the validation of two form field while creating a user in Drupal 6 but I don't know at all how to do :
$userinfo = array(
'name' => $login,
'init' => $mail,
'mail' => $mail,
'pass' => $password,
'status' => 1,
'lastname' => "", //how to ignore those required fields that invalidate the form
'surname' => "" //how to ignore those required fields that invalidate the form
);
// register a new user
$form_state = array();
$form_state['values'] = $userinfo;
drupal_execute('user_register', $form_state);
$errors = form_get_errors(); // getting 2 required field errors
Note that I can't supress the "required" property as it is used elsewhere in a more "complex" form.
Thanks

I haven't got a D6 site handy to test this on but I think it'll work...
Since drupal_execute() pushes you through the whole form build process you can take advantage of hook_form_alter() to remove the required status, but only in a context you pass along in the $form_state. For example
function MYMODULE_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'user_register' && !empty($form_state['custom_execution'])) {
$form['lastname']['#required'] = FALSE;
// etc...
}
}
...
$form_state = array();
$form_state['values'] = $userinfo;
$form_state['custom_execution'] = TRUE;
drupal_execute('user_register', $form_state);

Can't you use hook_form_alter to supress the "required" property, only when the from is not used in its "complex" form?
For instance, if you know what paths the "complex" form is used, you can check if that paths is being served with arg.
Better checks may be available...

Related

How to disable filter of a field in Zend Framework 2 in the controller?

Form to add/edit user I get from service manager with already installed filter, which is the test password. But this password is not needed when the user is edited. Can I somehow disabled password field validation in the controller?
In the getServiceConfig function of the module:
// ....
'UserCRUDFilter' => function($sm)
{
return new \Users\Form\UserCRUDFilter();
},
'UserCRUDForm' => function($sm, $param, $param1)
{
$form = new \Users\Form\UserCRUDForm();
$form->setInputFilter($sm->get('UserCRUDFilter'));
return $form;
},
// ....
In the controller I first of all getting a form object from service manager:
$form = $this->getServiceLocator()->get('UserCRUDForm');
Then disable user password validation and requirements, when user is edited and password not specified:
if ($user_id > 0 && $this->request->getPost('password') == '') {
$form->.... // Someway gained access to the filter class and change the password field validation
}
And after this i make a validation:
$form->isValid();
I found it!
// If user is editted - clear password requirement
if ($user_id > 0) {
$form->getInputFilter()->get('password')->setRequired(false);
$form->getInputFilter()->get('confirm_password')->setRequired(false);
}
This lines is disables requirement of input form fields :)
if you like to set all validators by yourself, call inside your form class
$this->setUseInputFilterDefaults(false);
to disable auto element validations/filter added from zend.
if you like to remove filter from elements call in your controller after your form object this
$form->getInputFilter()->remove('InputFilterName');
$form->get('password')->removeValidator('VALIDATOR_NAME'); should do the trick.
Note that you may have to iterate trough the Validatorchain when using Fieldsets.
$inputFilter->add(array(
'name' => 'password',
'required' => true,
'allow_empty' => true,
));
And on ModeleTable: saveModule:
public function saveAlbum(Album $album)
{
$data = array(
'name' => $album->name,
);
if (isset($album->password)){
$data['password'] = $album->password;
}

How to use form validation in Drupal 7

I am trying to edit the checkout form in Drupal Commerce, to require a user to enter their email address twice. When they submit their form, Drupal should check to see if the emails match, and call form_set_error() if they don't. For now, I am just trying to attach a custom validation function to the form, which I can't get to work. (My module is called checkout_confirm_email. This module is only for our own use, so I didn't put much effort into the name).
function checkout_confirm_email_form_alter(&$form, &$form_state, $form_id) {
if($form_id == 'commerce_checkout_form_checkout') {
$form['#validate'][] = 'checkout_confirm_email_form_validate';
dprint_r($form['#validate']);
dsm("I printed");
}
}
function checkout_confirm_email_form_validate($form, &$form_state) {
dsm("Never prints...");
}
The dprint_r statment outputs Array ([0] => checkout_confirm_email_form_validate). So the function is part of the form array, but the dsm statement in the validation function never prints.
I've actually been stuck for a while. I've looked up examples, and I can't see what I'm doing wrong. Anyone?
You need to attach the #validate property to the form submit button like this:
$form['submit']['#validate'][] = 'checkout_confirm_email_form_validate'
And it'll work then it's not necessary that my example is identical match to your form tree you should search for the submit button array and apply this example to it
Instead of form_set_error() I would use form_error($form, t('Error message.'));
function checkout_confirm_email_form_alter(&$form, &$form_state, $form_id) {
if($form_id == 'commerce_checkout_form_checkout') {
$form['#validate'][] = 'checkout_confirm_email_form_validate';
dpm($form['#validate']);
dsm("I printed");
}
}
function checkout_confirm_email_form_validate(&$form, &$form_state) {
// Not sure the exact email field
if(empty($form['submitted']['mail']['#value'])){
dsm("Should see me now and return to the form for re-submission.");
form_error($form, t('Username or email address already in use.'));
}
}
You could use any validate function here
https://api.drupal.org/api/drupal/includes!form.inc/7
The listed validations would be
date_validate - Validates the date type to prevent invalid dates
(e.g., February 30, 2006).
element_validate_integer -Form element validation handler for
integer elements.
element_validate_integer_positive - Form element validation handler
for integer elements that must be positive
element_validate_number - Form element validation handler for
number elements.
password_confirm_validate - Validates a password_confirm element.
Ex of usage
$form['my_number_field'] = array(
'#type' => 'textfield',
'#title' => t('Number'),
'#default_value' => 0,
'#size' => 20,
'#maxlength' => 128,
'#required' => TRUE,
'#element_validate' => array('element_validate_number')
);
You can use _form_validate().
function my_form_form_validate($form, &$form_state) {
if ((valid_email_address($form_state['values']['field_candid_email'])) === FALSE) {
form_set_error('field_candid_email', t('The email address is not valid.'));
}
if (!(is_numeric($form_state ['values']['field_candid_montant']))) {
form_set_error('field_candid_montant', t('The field value must be numeric.'));
}
}
I changed this line:
$form['submit']['#validate'][] = 'checkout_confirm_email_form_validate'
to this:
$form['actions']['submit']['#validate'][] = 'checkout_confirm_email_form_validate';
And it's works !
Use the following code:
$form['submit']['#validate'][] = 'checkout_confirm_email_form_validate'

How to add validators on the fly in Symfony2?

I've a password form field (not mapped to User password) to be used in a change password form, along with two other (mapped) fields, first and last.
I've to add validators on the fly: if value for password is blank then no validation should occur. Otherwise a new MinLength and MaxLength validators should be added.
Here is what i've done so far: create the repeated password field, add a CallbackValidator and return if $form->getData() is null.
Then, how can i add validators for minimum and maximum length to $field?
$builder = $this->createFormBuilder($user);
$field = $builder->create('new_password', 'repeated', array(
'type' => 'password',
'first_name' => 'Password',
'second_name' => 'Confirm password',
'required' => false,
'property_path' => false // Not mapped to the entity password
));
// Add a callback validator the the password field
$field->addValidator(new Form\CallbackValidator(function($form) {
$data = $form->getData();
if(is_null($data)) return; // Field is blank
// Here password is provided and match confirm, check min = 3 max = 10
}));
// Add fields to the form
$form = $builder
->add('first', 'text', array('required' => false)) // Mapped
->add('last', 'text', array('required' => false)) // Mapped
->add($field) // Not mapped
->getForm();
Oh well, found a solution myself after a few experiments.
I'm going to leave this question unanswered for a couple of days as one can post a better solution, that would be really really welcome :)
In particular, i found the new FormError part redundat, don't know if there is a better way to add the error to the form. And honestly, don't know why new Form\CallbackValidator works while new CallbackValidator won't.
So, don't forget to add use statements like these:
use Symfony\Component\Form as Form, // Mendatory
Symfony\Component\Form\FormInterface,
Symfony\Component\Validator\Constraints\MinLength,
Symfony\Component\Validator\Constraints\MinLengthValidator;
And the callback is:
$validation = function(FormInterface $form) {
// If $data is null then the field was blank, do nothing more
if(is_null($data = $form->getData())) return;
// Create a new MinLengthValidator
$validator = new MinLengthValidator();
// If $data is invalid against the MinLength constraint add the error
if(!$validator->isValid($data, new MinLength(array('limit' => 3)))) :
$template = $validator->getMessageTemplate(); // Default error msg
$parameters = $validator->getMessageParameters(); // Default parameters
// Add the error to the form (to the field "password")
$form->addError(new Form\FormError($template, $parameters));
endif;
};
Well, and this is the part i can't understand (why i'm forced to prefix with Form), but it's fine:
$builder->get('password')->addValidator(new Form\CallbackValidator($validation));
addValidator was deprecated and completly removed since Symfony 2.3.
You can do that by listening to the POST_SUBMIT event
$builder->addEventListener(FormEvents::POST_SUBMIT, function ($event) {
$data = $event->getData();
$form = $event->getForm();
if (null === $data) {
return;
}
if ("Your logic here") {
$form->get('new_password')->addError(new FormError());
}
});

form with no form_id(Drupal 6.x)

I have this form placed inside a block and it is assigned to right region of my site. Form is displayed just fine. But the submit button doesn't work as intended - to call submit function. So, I did some debugging and found an anomaly that there is no essential data - such as form_id and tokens - drupal normally injected to every form. As I can't figure out the root cause of this, I'm here for pointers of friends from here. Here's an excerpt of my code -
function mymodule_block($op = 'list', $delta = '', $edit = array()) {
switch ($op) {
case 'list':
$blocks['quick_search'] = array(
'info' => t('Quick Search'),
);
return $blocks;
case 'view':
switch ($delta) {
case 'quick_search':
$block['subject'] = t('Quick Search');
$block['content'] = drupal_get_form("block_quick_search");
break;
}
return $block;
}
}
function block_quick_search(&$form_state){
$form = array();
.
.
.
$form['quick_search_submit'] = array(
'#type' => 'submit',
'#value' => t('Search'),
'#submit' => array('mymodule_quick_search'),
);
return $form;
}
function mymodule_quick_search($form, &$form_state){
drupal_goto($base_path,"..............");
}
Thanks in advance
there is no essential data - such as form_id and tokens
This is indeed the reason why form submissions are not processed correctly. Check whether drupal_prepare_form is called on your form and whether it adds those items correctly. It is called by drupal_get_form if he form is not posted (and thusly not retrieved from the cache).
If $form['#token'] and $form['form_id'] are added correctly, I suspect something is wrong with translating the form to HTML. Do you use any custom theming for the form?
Try to pass your submit handler to the main form and not on the item submit like that:
$form['#submit'][] = 'mymodule_quick_search';
it should work.

Drupal - Include more than one user_profile_form on a page

Edit:
I think it is because the action is the same or something. I tried to modify the action using this:
function mytheme_user_profile_form($form) {
global $user;
$uid = $user->uid;
//print '<pre>'; print_r($form); print '</pre>';
$category = $form['_category']['#value'];
switch($category) {
case 'account':
$form['#action'] = '/user/'.$uid.'/edit?destination=user/'.$uid;
break;
case 'education':
$form['#action'] = '/user/'.$uid.'/edit/education?destination=user/'.$uid;
break;
case 'experience':
$form['#action'] = '/user/'.$uid.'/edit/experience?destination=user/'.$uid;
break;
case 'publications':
$form['#action'] = '/user/'.$uid.'/edit/publications?destination=user/'.$uid;
break;
case 'conflicts':
$form['#action'] = '/user/'.$uid.'/edit/conflicts?destination=user/'.$uid;
break;
}
//print '<pre>'; print_r($form); print '</pre>';
//print $form['#action'];
$output .= drupal_render($form);
return $output;
}
But, the form action, when the form is actually rendered is unchanged. They're all /user/%uid
Can I modify the form action?
I am including several different "categories" of the user profile form on one page, and the code will correctly output the forms I'm specifying. Each form is in a separate collapsible div.
My problem is twofold.
(1) The existing values for the fields aren't pre-populated and
(2) Clicking on "Save" for one section will result in a warning: Email field is required, regardless of which form you're actually saving
I am pretty sure that for problem #2, it is because the name of the button is the same in all cases, as is the form id.
print '<h3>– Account Settings</h3>';
print '<div class="expand">';
print(drupal_get_form('user_profile_form', $user, 'account'));
print '</div>';
print '<h3>– My Info</h3>';
print '<div class="expand">';
print(drupal_get_form('user_profile_form', $user, 'Personal'));
print '</div>';
print '<h3>– Experience</h3>';
print '<div class="expand">';
print(drupal_get_form('user_profile_form', $user, 'experience'));
print '</div>';
print '<h3>– Education</h3>';
print '<div class="expand">';
print(drupal_get_form('user_profile_form', $user, 'education'));
print '</div>';
Problem #1: ? Could you post the html source?
For problem #2:
OK, I'll step through the code here:
The validation handler for the user profile form (user_profile_form_validate()) calls
user_module_invoke('validate', $form_state['values'], $form_state['values']['_account'], $form_state['values']['_category']);
Which looks like
<?php
/**
* Invokes hook_user() in every module.
*
* We cannot use module_invoke() for this, because the arguments need to
* be passed by reference.
*/
function user_module_invoke($type, &$array, &$user, $category = NULL) {
foreach (module_list() as $module) {
$function = $module .'_user';
if (function_exists($function)) {
$function($type, $array, $user, $category);
}
}
}
?>
So, the validation handler for this form is going through every module looking for user hook functions and calling them with $type = 'validate'. (Note that 'category' param is optional here - contrib modules are not required to use it)
Let's look at user.module's user hook as an example to see what happens:
function user_user($type, &$edit, &$account, $category = NULL) {
if ($type == 'view') {
$account->content['user_picture'] = array(
'#value' => theme('user_picture', $account),
'#weight' => -10,
);
if (!isset($account->content['summary'])) {
$account->content['summary'] = array();
}
$account->content['summary'] += array(
'#type' => 'user_profile_category',
'#attributes' => array('class' => 'user-member'),
'#weight' => 5,
'#title' => t('History'),
);
$account->content['summary']['member_for'] = array(
'#type' => 'user_profile_item',
'#title' => t('Member for'),
'#value' => format_interval(time() - $account->created),
);
}
if ($type == 'form' && $category == 'account') {
$form_state = array();
return user_edit_form($form_state, (isset($account->uid) ? $account->uid : FALSE), $edit);
}
//<-- LOOK HERE -->
if ($type == 'validate' && $category == 'account') {
return _user_edit_validate((isset($account->uid) ? $account->uid : FALSE), $edit);
}
if ($type == 'submit' && $category == 'account') {
return _user_edit_submit((isset($account->uid) ? $account->uid : FALSE), $edit);
}
if ($type == 'categories') {
return array(array('name' => 'account', 'title' => t('Account settings'), 'weight' => 1));
}
}
So, it is only supposed to validate if the category == 'account'
In the function _use_edit_validate, we find:
// Validate the e-mail address:
if ($error = user_validate_mail($edit['mail'])) {
form_set_error('mail', $error);
}
There's your error message.
Since that form is only supposed to validate when the category == 'account', and your problem (#2) seems to be that it always validates regardless of the category, maybe your forms are not being rendered as unique form instances? Drupal might be rendering a complete form each time, and just setting a hidden form value to whatever the category is (like in this form's definition function in user_pages.inc $form['_category'] = array('#type' => 'value', '#value' => $category);)
It would be helpful to see the actual html source output.
==EDIT 10-15-09 in response to updated question===
OK, it looks like your method (editing $form['#action'] manually in the theme layer) may not be possible (see this post for reference). If you want to alter the form action you need to write a custom module that implements hook_form_alter() (it won't work in a theme template file). This function allows you to modify how a form is rendered, in your case the user modification form. There are more details on form modification here.
I am not 100% sure that's what you want to do though; (since it looks like you already must create a module) perhaps you want to hook into hook_user() instead; this function "... allows modules to react when operations are performed on user accounts.". You may be able to react to the category in this function and block/allow whichever user changes you like.
However, if it's just email address validation that is the problem, and if you are dealing with existing users, why don't you just make sure the email address is set before you save?