about hook: What is the role of hook_*() - drupal

For example in the user module there is a hook_user_login hook
When a user logs in in function user_login_finalize() will be called, then user_login_finalize will call user_module_invoke('login', $edit, $user);
that will call system_user_login (and others module's function[moudulename_user_login] that implements hook_user_login());
I am puzzled at which function will call hook_user_login() and when it will be Invoked. What is the role of this function?

As you mentioned, the user_login_finalize will call user_module_invoke('login', $edit, $user).
The user_module_invoke function will then look at the first argument of the function (login) and based on that value it will call the hook_user_login() function.
The main goal for a module to implement the hook_user_login() function is to be notified that a user just logged in, so it can take additional actions: add additional information to the database, write a special message to the screen if it is the user his/her birthday, etc ...

Related

Where to keep "currentUser" globally accessible

Almost every object in my state tree needs to have the following fields:
createdByGuid
createdAt
modifiedAt
The date fields are easy to add in the action creators. There seems to be consensus that action creators are the place where impureness are allowed, i.e. new Date().
But the currently logged in user is not easily fetched since this data lives in another slice of the state.
Example state:
profile
data
guid
firstname
...
media
items
0: guid, createdByGuid, ...
1: guid, createdByGuid, ...
drawings
items
...
When a MEDIA_ADD action is dispatched I want the action creator to augment the dispatched data with createdById. Current user needs to be fetched from profile.data.guid.
I don't want to bring the state into my action creator. Instead I can use a thunk to get hold of the state via getState(). But this seems to be a clumsy way of getting hold of a simple guid constant (constant for this session). It becomes more clumsy when essentially all of my action creators for adding data to the state needs to be thunks.
I'm inclined to create a separate global singleton object to hold this data and bring this dependency into all of my action creator modules. This seems to be a lot less disturbing dependency in terms of for example testing.
I suppose most Redux users has about the same question regarding current user. What is a good solution?
I'm working in react-native, but I suppose the question applies to most Redux applications.
If someone is interested, I went the singleton way with this. Not a true singleton per definition, but it suits my needs.
When a user logs in I handle this in an asynchronous action creator (a thunk). The thunk calls setGlobalCurrentUser() after successfully authenticating the user with the server.
To get hold of the current user I only have to import currentUserGuid() from currentUser.js and I don't end up in a dependency hell.
currentUser.js:
let _currentUserGuid;
export function currentUserGuid() {
if(!_currentUserGuid) throw new Error('currentUserGuid:: No logged in user')
return _currentUserGuid;
}
export function setGlobalCurrentUser(user) {
if(user) {
_currentUserGuid = user.get('guid')
} else {
_currentUserGuid = null
}
}

How to trigger a single initial action in many redux reducers at once?

I am refactoring my app to use redux, and it's great.
One thing I'd like to do is to dispatch an initial action at the beginning, and every reducer would manage to initialize themselves at that moment.
Let's say i have a main.js that create the stores, the routes, etc. In that file, I could do:
store.dispatch({ type: 'app/init' });
If I do this, the action type app/init can be intercepted in each reducer which needs to initialize itself.
An example use case (among others)
When the app is launched, a third party library must be called to see if a user is currently authenticated. If so, a LOGIN_SUCCESS action must be triggered with that user data.
I'd like to see this code in the same file as the authentication reducer, triggered by a global init action (which would mean the store is created).
The problem
In the reducer (where init action is managed), other actions cannot be dispatched.
The advised way of implementing actions is by defining action creators, which is indeed very clean, and let us use middleware like thunks to dispatch other actions.
I could use init() action creators for each reducer (I define related actions and reducer in the same "ducks" file), but that means importing/calling each of them in main.js, which is what I was trying to avoid by dispatching the action directly.
How to get the best of all worlds by having one single app/init action dispatched, and being able to intercept it in each store and dispatch other actions?
Note: I thougth of just implementing those initialization code in each reducer, inline, but I do not have standard access to the dispatcher that way?
The reducer just calculates the next state based on an action. In Redux, it’s not the right place to put side effects like calling an API.
If you want to orchestrate an asynchronous workflow of actions, I suggest you to look at Redux Saga. It lets you define long-running functions (“sagas”) that can “wait” for specific actions, execute some side effects, and dispatch more actions.

drupal :: order complete hook and upgrade user permission/roles

I want to be able to upgrade user's permission after the order status shows complete.
I figured out that I should use hook_order hook in order to achieve that. But how do I get to know which user has created that order and how do go about updating the permissions as well as setting up the expire time for that role automatically.
I want this hook to be called as soon as the payment is made and the order is completed.
Any pointers will be valuable.
In the hook_order, 3 parameters are passed. Third parameter depends on the first one. When the first parameter is 'update', third parameter is the status to which the order is going.
hook_order($op, &$order, $arg2){
switch($op){
case 'update':
if($arg2 === 'completed'){
// This order got marked completed
}
}
}
$order->uid will give you the user that created the order. You can do something like the following
$user = user_load(array('uid' => $order->uid));
// update the roles assigned to user
user_save($user);
For expiring the role, you will need to write a module that will keep track of the duration and will do something like above when the time expires. Or you can use role_expire module and see if that helps.

What's the point to have hook_mail_alter if I already have hook_mail?

What's the point to have hook_mail_alter if I already have hook_mail?
For example, I saw that hook_mail_alter is used to add a footer to my mail message. But I could use hook_mail() to add it, instead of using 2 functions… What am I missing?
Maybe it is done to add the footer after some other function is invoked?
hook_mail() should be used from a module to alter its own mail message, while hook_mail_alter() should be used from a module to alter the message sent by other modules.
This is clear from the following code taken from drupal_mail():
// Build the e-mail (get subject and body, allow additional headers) by
// invoking hook_mail() on this module. We cannot use module_invoke() as
// we need to have $message by reference in hook_mail().
if (function_exists($function = $module .'_mail')) {
$function($key, $message, $params);
}
// Invoke hook_mail_alter() to allow all modules to alter the resulting e-mail.
drupal_alter('mail', $message);
$module is the first parameter passed to drupal_mail().
It's clear the function doesn't invoke the implementation of hook_mail() of every module implementing it, but it invokes the hook just for the module calling the function.
There are other differences, such as when the two hooks are invoked (hook_mail_alter() cannot set the language for the message, which is set before hook_mail_alter() is invoked), and the parameters they get (hook_mail($key, &$message, $params) versus hook_mail_alter(&$message)).

javascript events and callback

I am working on a website, where we want user to login using Javascript and not using
postback. I have few pages which user can view without logging in, but on these pages
if he wants to do something like "Add to favourite" or "Report abuse" or similar, he has to log in. I can display a div where he can log in. But I want the system to perform the task
he initially tried to do. So say if the user wants to perform "Add to favourite", he should first log in and on success othere function "Add to favourite" should be called. So logic
should know where to delegate once user is logged in.
As this loging stuff is required for many other purposes too, so I can hard code one function once log on is successful. I need something like delegation which Login Routine
should know so that it calls it back.
Help will be appritiated.
Regards
Parminder
This assumes you have some basic experience with AJAX and callbacks...
// When the user submits the login form, call the login function with
// the original call as the third parameter
function login(username, password, callback) {
// Perform AJAX call with username and password.
// Your AJAX utility should call loginResult as its callback
// Store the callback parameter on your object somewhere
}
function loginResult(result, callback) {
if (/* Check if the result contains a valid user or sessionID, etc. */) {
// Logged in, yay. Do stuff to the UI to show this.
if (callback) callback();
} else {
// Error logging in, oh no. Display error.
}
}
You could store the lastAttemptedAction in the session, and always check this upon a successful login. So the order of events would be:
User accesses site anonymously
User clicks "add to favorite"
"Add to favorite" is added to Session.lastAttemptedAction
User is asked to login
User successfully logs in
Session.lastAttemptedAction is performed/cleared
If nothing is stored in the lastAttemptedAction, then nothing will be ran. The user will silently login, and continue on his or her merry way.

Resources