Hooking user registration in Drupal - drupal

I have a site where some users will be registered by our staff, and won't have emails associated with them. I would like to keep the email field a required field, so I devised a random email generator.
function generateRandomEmail() {
$email = 'noemail'. rand(0,1000000) . '#noemail.com';
return $email;
}
So, I attached that to the user register form alter, and it worked nicely, effectively generating an email for these users.
However, in the process, all the other fields associated with the main account section (password, username, notify, etc.) disappeared. My question, is there a quick way to populate the rest of the fields that I don't want to alter? I've used drupal_render($form); in a tpl.php, but it didn't work in the form alter.
Here is where I'm altering the form:
function accountselect_user($op, &$edit, &$account, $category) {
if ($op == 'register') {
$fields['account']['mail'] = array(
'#type' => 'textfield',
'#default_value' => generateRandomEmail(),
);

You are currently using hook_user for your manipulation, but that is the wrong place. On $op 'registration', you can return additional fields you want to inject to the registration process, but not alter existing fields. Use hook_form_alter() or hook_form_FORM_ID_alter() for that, e.g.:
function yourModule_form_user_register_alter(&$form, &$form_state) {
$form['account']['mail']['#default_value'] = generateRandomEmail();
}
You probably want to add a check that the request is in fact coming from the staff, since the above code would prepopulate the email field for the normal registration form also!
Also, please do not generate 'random' mail addresses using existing third party domains (like 'nomail.com'). Use the reserved 'example.com', or better yet, one that you own yourself!

Related

Send a custom email from sonata admin using variables

I have a list view in sonata admin. I want to add a column that will allow me to click on a link to send an email. The link action will know variables from that row in the table so that it can fill in the email. I was able to add the column and can visualize a twig template. I've added the following function to the Admin Class:
public function sendEmail( \Swift_Mailer $mailer)
{
$message = (new \Swift_Message('some email'))
->setFrom('contact#example.com')
->setTo('contact#example.com')
->setBody(
$this->renderView(
'emails/response.html.twig',
array('manufacturer' => $manuvalue, 'modelnum' => $modelnumvalue, 'email' => $email)
),
'text/html');
$mailer->send($message);
}
I'm stuck on how to connect these pieces together so that when I click on the link the email is sent and includes the params from the row. I have email working on form submit in other areas of the site, but need help figuring out the way to do this manually.
As you mentioned in the comments, what you want to do is typically a Custom Action
In order to ensure that this action can not be accessed via direct request and can only be performed by admin, you could do use a template like this for your customAction :
...
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
...
//AuthorizationCheckerInterface injected as authorizationChecker
public function customAction($id){
$object = $this->admin->getSubject();
if (!$object) {
throw new NotFoundHttpException(sprintf('unable to find the object with id: %s', $id));
}
// Check access with role of your choice
$access = $this->authorizationChecker->isGranted('ROLE_ADMIN');
if($access){
//Do your action
} else {
throw $this->createAccessDeniedException("You don't have the rights to do that!");
}
}
I ended up doing a custom route and protected it with security settings that #dirk mentioned.

WordPress: get all meta data when user registers

I have a user registration form in the front end (in the Users admin section as well) with three extra fields (apart from default ones): birthday, country, language. their values are stored in usermeta table.
I have this action hook to retireve all meta data for the registered user:
add_action('user_register', 'new_user_func');
// user registration callback function
function new_user_func($userID) {
$newUser = get_user_meta( $userID );
$userMeta = array();
foreach ($newUser as $key => $value) {
$userMeta[$key] = $value[0];
}
//do something with $userMeta...
}
var_dump($userMeta) after submit doesn't give me the extra fields value though.. only defaults (first name, last name etc)
Anyone know what might be the case?
Did you try getting the values with:
$meta = get_the_author_meta($meta_key, $user_id);
Perhaps the meta values you add yourself isn't supported by get_user_meta() .
If this don't work either, perhaps you need to look on how you went about creating the new meta fields. Theres a pretty decent tutorial on how to do it here:
http://justintadlock.com/archives/2009/09/10/adding-and-using-custom-user-profile-fields
Read de Codex entry for user_register action, it says:
Not all user metadata has been stored in the database when this action is triggered.

Need advice to get my logic correct in d7

Goal: Is to save information of a node which gets updated. We need to gather the node id of the node which is updated and also the user names of people who have bookmarked it.
Implementation:
I have managed to get the both this detail using flags and rules module. I made a custom module which implemented the hook to get this info.
I am getting stuck here:
Now I need to save the user name and the node id. I am still deciding if I want to use fields or the db layer.
One username can have multiple node id saved.
Now the problem is I don't know for sure how many nodes will be enough. It depends on the user. It can be 5 can be 500 or even 5000 node ids that might need to be saved for one user.
So how do I make provision for this ?
So I am stuck with the logic. How should I use the db layer or the fields in custom content type to save this ? and how should I do it ?
Please advice. I am using d7.
custom module code
/*
* Implementation of the hook_rules_action_info()
*
*/
function customvishal_rules_action_info()
{
$actions = array(
'customvishal_action_userdetail' => array(
'label' =>t('Custom function to send notifications'),
'group'=>t('Cusotm Code for sending notifications'),
'parameter'=> array(
'account'=> array(
'type'=>'user',
'label'=>t('Going to get user list'),
),
// for the node
'productdetail'=> array(
'type'=>'node',
'label'=>t('Passding the node data'),
),
)
),
);
return $actions;
}
/*
* The action function for the rules exampled hello world
*
*/
function customvishal_action_userdetail($account,$productdetail)
{
drupal_set_message(t('This user #username! has flagged it',
array('#username' => $account->mail)));
drupal_set_message(t('This node #nid has got updated',
array('#nid' => $productdetail->nid)));
// The above takes care of the node and the user information later I will put
// it in a db or something like that.
// end of the function customvishal_action_userdetail
}
It really seems like you should be using hook_node_update() and hook_node_insert() to for access to nodes that have just been added or updated.
If you wanted access to the node data just before it was saved, then hook_node_presave() would be the one to use.
I don't think you need presave though because you mentioned you needed the node ID, and presave does not have that for new nodes yet.
Here's a way to process new and updated nodes. The first 2 functions just hook into the right place and route the node to the 3rd function.
<?php
// hook into node inserts
function customvishal_node_insert($node) {
if ($node->type == 'mynodetype') {
customvishal_handle_data($node);
}
}
// hook into node updates
function customvishal_node_update($node) {
if ($node->type == 'mynodetype') {
customvishal_handle_data($node);
}
}
// custom handler for the nodes
function customvishal_handle_data($node) {
// load a user object of the node's author
$author = user_load($node->uid);
// now do what we need to do with $node and $user data
}
Remember you need to clear the Drupal cache for new hooks in your module to work in D7.

How to manually register a user in Drupal 6.x?

The website has a normal registration form which allows users to register and the likes.
I have created a new custom form in which I am capturing the username/password etc. How do I manually register the user in Drupal system?
Thank You
Check out hook_user and user_save().
http://api.drupal.org/api/function/hook_user
http://api.drupal.org/api/function/user_save/6
Just expanding on Kevin's suggestion of hook_user and user_save here, the code might look something like:
// store user name
$user_name = "user123";
// store user email
$email = "user123#gmail.com";
// set up the user fields, use user_password function for 8 character password
$fields = array(
'name' => $user_name,
'mail' => $email,
'pass' => user_password(8),
'status' => 1,
);
// give new user roles if needed, as shown below
$fields['roles'] = array('new_role');
// pass the fields to user_save() and leave first param empty to create new user
$account = user_save('', $fields);
It's not the answer you want, but you'd save yourself a lot of trouble by using hook_form_alter to change the current registration form:
http://www.lullabot.com/articles/modifying-forms-drupal-5-and-6

Preventing form_token from rendering in Drupal "GET" forms

Drupal inserts a form_token as a hidden field when it renders forms. The form_token is then checked on form submission to prevent cross-site request forgery attacks. The form data that is submitted is guaranteed to have come from the original form rendered by Drupal.
However, forms using the "GET" method shouldn't need this token. All it does is lengthen and uglify the resulting URL.
Is there any way of suppressing it?
Yes, there is a way, but use it consciously (see warning below):
If you create the form yourself, adding
$form['#token'] = FALSE;
to the form definition array should prevent a token from being generated in the first place.
If you are dealing with an existing form, you can bypass the token validation process by unsetting the '#token' element on hook_form_alter:
// Example for removal of token validation from login (NOTE: BAD IDEA!)
function yourmodule_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'user_login_block') {
unset($form['#token']);
}
}
Warning: Given your question, I think there is a slight misconception concerning the difference (better, the lack of a difference) between GET and POST requests.
... on forms using the "GET" method
shouldn't need this token. All it does
is lengthen and uglify the resulting
URL.
This is wrong! GET and POST are just two different, but mostly equivalent methods of transmitting data from the client to the server. Since POST is better suited to transfer large amounts of data (or difficult formatted data), it is the established standard for submitting forms, but it is in no way safer/unsafer or more/less secure than GET requests. Both type of requests can be tampered with by malicious users in the same ways, hence both types should use the same protection mechanisms.
With a GET request, the token does exactly the same as with a POST request - it proves to the server that the submitted data comes from the same Browser on the same machine as the request he build the form for! So you should only remove it if you are sure that the request can not be misused via XSRF.
This worked for me. I had to unset all the form api elements and set the #token property to false. Notice the after_build function for unsetting the other properties.
function mymodule_form(&$form_state){
$form['name'] = array(
'#type' => 'textfield',
'#title' => 'name',
'#value' => 'name',
);
$form['#method'] = 'get';
$form['#action'] = url('someurl');
$form['submit'] = array('#type' => 'submit', '#value' => 'go');
$form['#token'] = false;
$form['#after_build'] = array('mymodule_unset_default_form_elements');
return $form;
}
function mymodule_unset_default_form_elements($form){
unset($form['#build_id'], $form['form_build_id'], $form['form_id']);
return $form;
}
The site I work on uses the Drupal 6 form API for custom search forms, so by removing the token and build id we were able to cache the results in memcache. Now we've moved to Acquia hosting, it's cached using Varnish.
To remove the form_token and form_build_id from your form and submit it as a GET request, use the following method:
<?php
function module_example_form($form_state, $form_id = NULL) {
// Form root settings.
$form = array();
// Set the submission callback for this form.
$form['#submit'][] = __FUNCTION__ . '_submit';
// Set the request method for this form to GET instead of the default
// of POST.
$form['#method'] = 'get';
// Remove unique form token so request can be cached. This is accompanied by
// code in hook_form_alter to ignore the token and remove the build_id.
$form['#token'] = FALSE;
// Submit button.
$form['go'] = array(
'#type' => 'submit',
'#value' => t('Go!'),
);
return $form;
}
/**
* Implements hook_form_alter().
*/
function module_form_alter(&$form, $form_state, $form_id) {
// Changes to the 'module_example_form' form.
if ($form_id == 'module_example_form') {
// Unset the hidden token field and form_build_id field.
unset($form['#token'], $form['form_build_id'], $form['#build_id']);
}
}
?>
I find that simply throwing away the CSRF token is not an option. We solved it using hook_theme_registry_alter() to overwrite the Drupal core theme_hidden() function so that the hidden form element 'form_token' is rendered as an <esi /> tag. The tag will cause Varnish to make a call to a PHP file which we allow to pass through the cache. This file will calculate the proper form token for the current user and will then output the HTML code for the hidden field. You can calculate this token without a Drupal bootstrap, but you will need a single DB query to fetch the *drupal_private_key* for your site, which is stored in the variable table.

Resources