Drupal hook_form_alter anonymous user can't see the fields - drupal

I created a small module for altering forms called "form_mods". The form I'm altering is the "user_profile_form". I added a category for extra fields called "Profile".
I created a select field in the Drupal admin called "profile_state" and I'm altering it in my module to have a key => value list of states and It's working for me when logged in as an admin but an anonymous user that's trying to register sees an empty states select field. Is there a permissions issue here? I tried to add 'access' => user_access('access content') to the field but that didn't work. Here is my code:
function form_mods_form_alter($form, $form_state, $form_id) {
switch ($form_id) {
## user_profile_form ###################################################################################
case 'user_profile_form': // This is our form ID.
//echo '###'.$form['_category']['#value'].'###';
if($form['_category']['#value'] == 'Profile'){
// Modify the states dropdown list
$states = load_states_list();
$form['Profile']['profile_state'] = array(
'#type' => 'select',
'#title' => t('State'),
'#options' => $states,
'#required' => TRUE,
'#default_value' => isset($form['Profile']['profile_state']['#default_value']) ? $form['Profile']['profile_state']['#default_value'] : '',
'#element_validate' => array('profile_state_validate')
);
}
####################################################################################
break;
}
}
function load_states_list() {
$states = array('' => '-- Select a state'); // add a default empty value
$results = db_query("SELECT * FROM {states_list} ORDER BY name ASC");
while ($state = db_fetch_array($results)) {
$states[$state['code']] = $state['name'];
}
return $states;
}
Thanks

First of all, are you sure you're function ever gets run? Having the function named the way you do, I don't think it is. If the module name is "form_mods", your function should be called
function form_mods_form_alter
Or...since you're only modifying the user_profile_form form, you could use the function name
function form_mods_user_profile_form_alter
Now, the reason it isn't working is because you don't have the & in front of the $form in the parameter list. The & basically passes the variable as reference, and so any changes you make to the $form variable will be saved and passed back to the calling function. So, your function should look like
function form_mods_form_alter(&$form, &$form_state, $form_id) {
OR
function form_mods_user_profile_form_alter(&$form, &$form_state) {
Reference: http://api.drupal.org/api/drupal/developer--hooks--core.php/function/hook_form_alter/6

Thank you mikesir87 for the reference link. I figured out my problem.
There are 2 different forms that are using those fields I created. They have different form id's. I have to look for "user_profile_form" and "user_register" form id's.
Here is my new code that works:
function form_mods_form_alter($form, $form_state, $form_id) {
if( (($form_id == 'user_profile_form') && ($form['_category']['#value'] == 'Profile')) || ($form_id == 'user_register') ){
// Modify the states dropdown list
$states = form_mods_load_states_list();
$form['Profile']['profile_state'] = array(
'#type' => 'select',
'#title' => t('State'),
'#options' => $states,
'#required' => TRUE,
'#default_value' => isset($form['Profile']['profile_state']['#default_value']) ? $form['Profile']['profile_state']['#default_value'] : ''
);
}
}
thanks

Related

Adding elements to a field widget in Drupal 8

What I need to accomplish is adding a link to a node to field widgets (the node contains the formatted instructions to properly compile the field).
So far I've been able to add the node reference field in the field config form, using Third Party Settings:
function mymodule_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
if ($form_id === 'field_config_edit_form' && $form_state->getFormObject()->getEntity()->get('entity_type') == 'myentity') {
$field = $form_state->getFormObject()->getEntity();
$help_page_id = $field->getThirdPartySetting('mymodule', 'help_page_id');
$form['help_page_id'] = array(
'#type' => 'entity_autocomplete',
'#title' => t('Help page'),
'#target_type' => 'node',
'#selection_handler' => 'default',
'#selection_settings' => array(
'target_bundles' => array('help_page'),
),
'#default_value' => $help_page_id ? Node::load($help_page_id) : NULL,
'#weight' => 100,
);
$form['#entity_builders'][] = 'mymodule_form_field_config_edit_form_builder';
}
}
Now I'm having troubles retrieving this information when showing the form, and altering the field widget in order to display the link.
Using hook_field_widget_form_alter, I cannot get the custom configuration value from the arguments I have:
function mymodule_field_widget_form_alter(&$element, \Drupal\Core\Form\FormStateInterface $form_state, $context) {
}
I guess I have to load the field configuration entity, but I don't know how.
I didn't test it, but something like this should work:
function mymodule_field_widget_form_alter(&$element, \Drupal\Core\Form\FormStateInterface $form_state, $context) {
// Add a suffix to widget form elements for all fields of type entity_reference.
$field_definition = $context['items']->getFieldDefinition();
if ($field_definition->getType() == 'entity_reference') {
// TODO: Render the node link to $link
$element['#suffix'] = $link;
}
}

Check if form failed validation

I added a validation hook to a node creation form.
For my project, i need this validation only ONE time: basically i just check if a value already exists in the DB and i notify it to the user. If the user still submits the form, i must add it anyway.
i would like to do something like that:
if (form_did_not_fail_validation_before) {
$form['#validate'][] = 'my_module_validation_hook';
}
in my hook_form_alter, so that validation hook is only called the first time.
I can't find a way to check if the form already failed validation, any ideas?
Here is one way of solving this issue your issue. But if you using some form input like text form I suggest that you use Ajax callback since it will feel more dynamic. Let me know if you want an example of how to solve it with Ajax callback?
I guess the key here is that I use $form_state['rebuild'] = true; so that form is rebuilt and than it easy to get the value from the $form_state['values']
Here is the code:
function example_form(array $form, array &$form_state)
{
$form['temp'] = array(
'#type' => 'value',
'#value' => array_key_exists('values', $form_state) ? $form_state['values']['temp'] + 1 : 1,
);
if (array_key_exists('values', $form_state) && $form_state['values']['temp'] == 1)
{
$form['message'] = array(
'#markup' => t('I only give you one warning'),
'#prefix' => '<p>',
'#suffix' => '</p>',
);
}
$form['submit_button'] = array(
'#type' => 'submit',
'#value' => t('Click Here!'),
);
return $form;
}
function example_form_validate(array $form, array &$form_state)
{
$form_state['rebuild'] = true;
}
function example_form_submit(array $form, array &$form_state)
{
if($form_state['values']['temp'] == 1) {
// I will not store anything
} else {
// now I will store it :)
}
}

Using Drupal's node form in a new page

In a custom module I want to have a page defined in hook_menu, that shows the add form for a specific content type, with some modifications to the form.
So far it's working, and even saving the new node, but only with the default values I'm setting in the code, i.e. it's not picking up anything the user types into the form. I checked and $form_state['input'] contains the inputted values, but $form_state['values'] doesn't, so the new node gets saved wrong.
Here's the relevant code:
function mymodule_menu() {
return array(
'admin/content/myadd/%' => array(
'title' => 'my custom add page',
'page callback' => 'mymodule_node_add',
'page arguments' => array(3),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
),
);
}
function mymodule_node_add() {
module_load_include('inc', 'node', 'node.pages');
//I'm doing a print here instead of returning because I'm calling this page
//in an AJAX popup, so I don't want the whole page to output, only the form.
print render(drupal_get_form('mymodule_node_add_form'));
}
function mymodule_node_add_form($form, &$form_state) {
if (!isset($form_state['node']) {
global $user;
$node = (object) array(
'uid' => $user->uid,
'type' => 'mycontenttype',
'language' => LANGUAGE_NONE,
);
//this is setting a default value
$node->myfield = array(LANGUAGE_NONE => array(array('value' => arg(3))));
$form_state['build_info']['args'] = array($node);
$form = drupal_build_form('mycontenttype_node_form', $form_state);
$form['actions']['submit']['#submit'][0] = 'mymodule_node_add_form_submit';
//there's a lot more customization of the form here, like adding fields, etc.
}
return $form;
}
function mymodule_node_add_form_submit($form, &$form_state) {
//here's where $form_state['input'] is correct but $form_state['values'] isn't.
$node = node_form_submit_build_node($form, $form_state);
node_save($node);
$form_state['values']['nid'] = $node->nid;
$form_state['nid'] = $node->nid;
$form_state['redirect'] = 'some/other/page';
}
So, am I doing something wrong here? Should I be concerned about form ids being wrong? (my form's id is mymodule_node_add_form, but the actual form might output mycontenttype_node_form), would this affect me?
You want hook_form_alter() (see api.drupal.org). I would try to use the existing content type's form and simply alter it with hook_form_alter(). I would also try to first get it working as a standard, non-AJAX page, so you can get all the advantages of dpm() and other debugging techniques. When you have it down solid, then modify it to take advantage of the AJAX techniques.
mymodule_form_alter(&$form, &$form_state, $form_id) {
// use this with your devel module turned on to verify
// your $form_id and contents of all forms that load on a given page
dpm($form);
// once you verify your $form_id, you can begin accessing your form and altering it
switch( $form_id ) {
case 'my_target_form_id' :
// this part is just pseudocode, I haven't memorized the $form structure,
// you can get it from your dpm().
if( $form['node']->type == 'my_target_content_type' ) {
$form['actions']['submit']['#submit'][0] = 'mymodule_node_add_form_submit';
}
break;
}
}

Drupal add an action on the content listing

Is it possible to add an action on the /admin/content page. We got "publish selected content" or "delete selected content" etc etc...
http://screencast.com/t/v2ZMedCqy3g
I'm trying to add an action here from a module installation.
Thanks
You need to implement hook_node_operations(). You can look at the pathauto_node_operations() as example.
function pathauto_node_operations() {
$operations['pathauto_update_alias'] = array(
'label' => t('Update URL alias'),
'callback' => 'pathauto_node_update_alias_multiple',
'callback arguments' => array('bulkupdate', array('message' => TRUE)),
);
return $operations;
}
Notices that the callback specified takes an array of node ids, plus the additional callback arguments as you specified in your hook implementation (see above example).
// The call back specified above ^
function pathauto_node_update_alias_multiple(array $nids, $op, array $options = array()) {
$options += array('message' => FALSE);
$nodes = node_load_multiple($nids);
foreach ($nodes as $node) {
pathauto_node_update_alias($node, $op, $options);
}
if (!empty($options['message'])) {
drupal_set_message(format_plural(count($nids), 'Updated URL alias for 1 node.', 'Updated URL aliases for #count nodes.'));
}
}

How can I combine fields to generate a username during registration?

In a custom module "nade_reg" I have changed the registration form to include two fields to collect the first and last-name of the user, while hiding the username field. I don't know if it's relevant to this, but I do have the login toboggan module enabled.
On submit, I want to the username to become Firstname Lastname (with the space)
function nade_reg_form_alter(&$form, &$form_state, $form_id) {
switch ($form_id) {
// This is our form ID.
case 'user_register':
$form['name']['#type'] = 'hidden';
$form['field_uprofile_first_name1'] = array(
'#type' => 'textfield',
'#title' => t('First Name'),
'#weight' => -40,
'#required' => TRUE,
);
$form['field_uprofile_last_name1'] = array(
'#type' => 'textfield',
'#title' => t('Last Name'),
'#weight' => -35,
'#required' => TRUE,
);
break;
}
}
I've been trying to do this with a submission handler, but it seems that my function isn't being recognized by the system (even after much cache clearing), so can't tell where my errors are.
Is the code below correct, or do I need to do some wrangling with arrays?
Any ideas why this wouldn't be seen by the system?
function nade_reg_user_register_submit($form, &$form_state) {
drupal_set_message(t('function redlemonade_register_user_register_submit sucessfully called.'));
$name = $form_state['values']['field_uprofile_first_name1'] . ' ' . $form_state['values']['field_uprofile_last_name1'];
}
I had a similar requirement where I wanted the username to always be equal to the email. Which I accomplished by hiding the username from the registration form as you are, and then using the user_presave() hook.
For you, it would look something like this;
function nade_reg_user_presave (&$edit, $account, $category) {
// check that the names are being edited, or else you will overwrite
// with a blank username
if (array_key_exists('first_name', $edit) &&
array_key_exists('last_name', $edit)) {
$edit['name'] = $edit['first_name'] . ' ' . $edit['last_name'];
}
}
EDIT: for Drupal 6 per the comment (I think this will do the trick), I have used hook_user() to accomplish what I did above in D7, although it's a bit messier.
function nade_reg_user($op, &$edit, &$account, $category = NULL) {
if (($op == 'insert' || $op == 'edit') // if its the right operation
&& array_key_exists('first_name', $edit) // and the right edits
&& array_key_exists('last_name', $edit)) {
$name = $edit['first_name'] . ' ' . $edit['last_name'];
$qry = "UPDATE {users} SET name = '%s' WHERE uid = %d";
if (db_query($qry, $name, $account->uid)) {
$edit['name'] = $name; // update in the user array for access by other modules
}
}
}
Your submission handler doesn't work for existing forms, unless you specifiy an extra submit handler.
This can be achieved with :
$form['#submit'][] = 'my_very_own_custom_submit_handler';
It's the same for adding extra validation handlers.
Alternatively, you could catch the user being inserted, through hook_user - as listed in a previous answer - which is the equivalent of hook_nodeapi, but for users. Changing the $edit variable should be enough during 'insert' op.
You need to set $form_state['values']['name'], not just $name.

Resources