Loading users from an SQL query - the correct way - drupal

I have an SQL query that lists the uid of all users who have a certain role:
SELECT u.uid
FROM {users} as u, {users_roles} as ur
WHERE u.uid = ur.uid AND ur.rid = 10 ORDER BY u.uid DESC
I need to load them all in an array as objects for listing.
I asked a question previously that left me only with the answer that what I wanted to do would be easier done without Views - so I'm going use a template file instead.
Therefore this question.
I know how to do this, but apparently my method is worth -2
This is how I want to do it:
$research['sql'] = "SELECT u.uid FROM {users} as u, {users_roles} as ur WHERE u.uid = ur.uid AND ur.rid = 10 ORDER BY u.uid DESC";
$research['sql_result'] = db_query($alumni['sql']);
// Load user objects and store in array
while($user_array = db_fetch_array($research['sql_result'])) {
// Create user objets based on uid
$user_obj = user_load($user_array['uid']);
// Load profile
profile_load_profile($user_obj);
$research['users'][$user_obj->uid] = $user_obj;
}
Please help me with how I should do it.

Your basic approach looks fine by me, except that the call to profile_load_profile() is redundant:
The user_load() function will invoke hook_user with operation 'load', and the profile module implements hook_user and calls profile_load_profile() for the load operation itself, so by the time you call it explicitly, it has already been called implicitly and you can just drop it.

Related

Adaptive User Management

I have built a review app based on Google's "people viewer" template that allows managers to create and edit reviews for their direct reports.
The app contains the directory model as well as three roles: Admins, HR, EndUsers.
The app contains a user settings model that allows to create and store user settings similar to the "people skills" template.
The app contains a review model that will contain the reviews for every employee. As one employee can have several reviews, this will be a one-to-many relation, either linked to directory model or user settings model.
The reviews should be readable by managers chain of manager. For this I have created a server script, assuming that the EmployeeEmail will be additionally stored in the review. But maybe there is a better alternative?
function getDirectReportsChainForUser_(query) {
var userQuery = app.models.Directory.newQuery();
userQuery.filters.PrimaryEmail._equals = query.parameters.PrimaryEmail;
userQuery.prefetch.DirectReports._add();
userQuery.prefetch.DirectReports.DirectReports._add();
var users = userQuery.run();
if (users.length === 0) {
return [];
}
var user = users[0];
var directs = user.DirectReports;
var records = [];
for (var i = 0; i <= directs.length; i++) {
records.push(directs[i].PrimaryEmail);
}
// The following lines are based on the asumption that the EmployeeEmail
// will be stored in the review in case that there is no better alternative.
//The question that then remains is how to recursively add the DirectReports
//of the DirectReports to the array???
var reviewQuery = app.models.Reviews.newQuery();
reviewQuery.filters.EmployeeEmail._in = records;
return reviewQuery.run();
}
The manager should be able to define whether one or more of his deputies can read the reviews for his unit, too. My idea was to solve this issue through a many-to-many relation between the directory and review model, but I am not sure how to implement it?
Furthermore, once a manager or his deputy departures, it should be possible for the Admin to dissolve the connection and to reconnect the reviews to a successor. Therefore I was thinking about integrating a multiselect in the admin page. Would this be feasible?
Here I see at least two distinct questions:
is there better way to associate directory model's record and ordinary data model than just adding primary email field to the data model
Nope, at this time it is not possible to establish relations between data (SQL/Drive Tables) and directory models.
how to recursively get all direct reports for a user
App Maker's Directory Model is a wrapper on top of G Suit Admin SDK's Directory API that exposes just a small subset of its powerful features. When you add Directory Model App Maker automatically plugs in correspondent Apps Script advance service:
Since we already have configured Directory API we can unleash its full power and easily fetch all manger's subordinates with a single call (or multiple if you have a need to support paging). In order to do that we will use Users.List API method with managerId query parameter (the only one that allows us to query all subordinates down the tree). Here are reference for the minimal set of search query parameters quoted from the full search documentation (without those parameters query would not work or wouldn't work in a way we need):
managerId: The ID of a user's manager either directly or up the management chain.
domain: The domain name. Use this field to get fields from only one domain. To return all domains for a customer account, use the customer query parameter instead. Either the customer or the domain parameter must be provided.
viewType: Whether to fetch the administrator-only or domain-wide public view of the user. For more information, see Retrieve a user as a non-administrator (admin_view is default value so we need to override it with domain_view).
query: Query string for searching user fields. For more information on constructing user queries, see Search for Users.
/**
* Fetches all reviews associated with all subordinate employees (both direct
* and indirect reports).
*/
function getAllReportsEmails(managerId) {
var emails = [];
var result = AdminDirectory.Users.list({
domain: 'ENTER HERE YOUR DOMAIN (exapmle.com)',
query: 'managerId=' + managerId,
viewType: 'domain_public',
maxResults: 100
});
if (result.users) {
emails = result.users.map(function (user) {
return user.primaryEmail;
});
}
return emails;
}
/**
* Fetches all reviews associated with all subordinate employees (both direct
* and indirect reports).
*/
function getAllReportsReviewsForManager_(query) {
var userQuery = app.models.Directory.newQuery();
// For better security I would recommend to use
// Session.getActiveUser().getEmail() instead of parameter
// passed from the client.
userQuery.filters.PrimaryEmail._equals = Session.getActiveUser().getEmail();
var users = userQuery.run();
if (users.length === 0) {
return [];
}
var manager = users[0];
var managerId = manager._key;
var allReportsEmails = getAllReportsEmails(managerId);
var reviewQuery = app.models.Reviews.newQuery();
reviewQuery.filters.EmployeeEmail._in = allReportsEmails;
return reviewQuery.run();
}
Pavel, I tried to integrate the ideas you gave me into one server script that returns an array of the manager and his whole subordinate chains (direct reports + indirect reports), so that I can use it whenever needed. I turned into a recursive function to get the direct reports and indirect reports on the next lower level. Is there a way to get the whole chain?
function getSubordinatesChainForUser(query) {
var userQuery = app.models.Directory.newQuery();
userQuery.filters.PrimaryEmail._equals = Session.getActiveUser().getEmail();
userQuery.prefetch.DirectReports._add();
userQuery.prefetch.DirectReports.DirectReports._add();
var users = userQuery.run();
if (users.length === 0) {
return [];
}
var userEmails = users.map(function(manager){
var employeeEmails = manager.DirectReports.map(function(employee){
return employee.PrimaryEmail;
});
return manager.PrimaryEmail + ',' + employeeEmails;
});
return userEmails;
}

How do I do a Global Update in Firebase?

I'm trying to wrap my head around firebase, and one issue I can't seem to work out is how mass updates occur.
Lets say I have 1,000 users and they all have "user_role": "member"
And I decide to update all 1,000 users to "user_role":"paid-member"
in SQL I can just do UPDATE users SET user_role = 'paid-member' ... So what's the Firebase equivalent?
Or more importantly, how would I accomplish something like this in firebase...
UPDATE users SET user_role = 'paid-member' WHERE user_role = 'member'
Unfortunately, it's not possible to do this without knowing the list of users beforehand. If you had all the usernames in an array, you could do something like this:
var usernames = [...];
for (var i = 0; i < usernames.length; i++) {
var ref = new Firebase("https://myfirebase.firebaseio.com/users/" + usernames[i]);
ref.child("user_role").set("paid-member");
}
You'll have to retrieve the list of usernames first using a child_added or value event handler.

Tridion Query for component that have no exact metadata field

I have a components that based on schema that have a non mandatory metadata field ExtendedType. I can query for a component that have this field with a certain value:
new CustomMetaValueCriteria(new CustomMetaKeyCriteria("ExtendedType"), "Highlight", Criteria.Equal)))
I need to query for a components that have no this field filled in. How can I query for a that.
In SQL I can write next:
select * from t where t.ExtendedType IS NULL
How can i do this using Trdion Query? In common i need to implement query like:
select * from t where t.ExtendedType = "Highlight" OR t.ExtendedType IS NULL
You might be able to achieve this with the NotInCriteria, as follows:
new NotInCriteria
(
new CustomMetaValueCriteria
(
new CustomMetaKeyCriteria("ExtendedType"), "%", Criteria.Like
)
)
I haven't tested this, it's just a thought. Even if it works, be sure to check if it performs as well!
PS: next time, please use the tridion.stackexchange.com forum for Tridion-related questions!

asp.net entity framework - Complicated Queries with join + Membership user

I have 2 tables.
Users - have userID, userMainGroup and userMinorGroup
Tasks - TaskId, UserId
My goal is:
I have current CurrentuserId and i want to show him all the tasks that were created by users from the same MainGroup as he.
In SQL i would write:
Select *
From Tasks Left join Users on tasks.Id=users.id
Where users.MainGroup=CurrentuserMainGroup; (var)
How do i do it using entity framework?
I understood that to make a join i need to write something like:
var tasks = from t in db.tasks
from u in db.users
where t.Id=u.Id
select new {t.Id, t.name....}
but where do i put the condition Where on the MainGroup?
you can try like this
var data= (from con in db.tasks
let UserMainGroup = db.users.where(x=>x.id==con.id).FirstOrDefault()
where UserMainGroup.MainGroup=CurrentuserMainGroup
select new {
ID=con.id,
Name=con.name
}).ToList();
i think this will help you.......
It is recommended that you use navigation properties in stead of manually coded joins:
from t in db.Tasks
where t.User.MainGroup == currentuserMainGroup
select new {t.Id, t.name.... , t.User.Name, ... }

Linq to Entities: can't get collection query to work

I'm struggling to get a collection of records using L2E. Here's the model view:
http://pascalc.nougen.com/stuffs/aspnet_linq_model2.png
I have a user identifier, which is associated to 1 or many UserGroup which themselves are linked to TestCase. I would like to get all TestCases of all groups the user id X is associated to.
I also notice that I don't get all Project for users that are associated to 2 (or more).
Here's how I do so far:
QASModel.QASEntities qasEntities = new QASModel.QASEntities();
QASModel.User authenticatedUserEntity = (from u in qasEntities.Users
where u.ID.Equals(authenticatedUserId)
select u).FirstOrDefault();
// Get the authenticated user usergroups
var usergroup = authenticatedUserEntity.UserGroups.FirstOrDefault();
// Get all testcases of all user group the authenticated user is associated to
var allTestcases = usergroup.TestCases;
// Get the authenticated user projects based on it's usergroup(s)
var authenticatedUserProjects = usergroup.Projects;
authenticatedUserProjects give back only 1 project, where the user is linked to 2 projects.
And allTestcases gives back no result, although there are about 8 entries in TestCases associated to a project associated to one of the same UserGroup the user belongs to.
Thanks
I think your problem is in this line:
var usergroup = authenticatedUserEntity.UserGroups.FirstOrDefault();
Shouldn't your code get all UserGroups of that User? The above line will return only 1 UserGroup, this is, if the user belongs to more than 1 UserGroup the 2nd one won't be returned.
To correct this:
var userTestCases = new List<TestCase>();
var userProjects = new List<Project>();
foreach(UserGroup ug in authenticatedUserEntity.UserGroups)
{
userTestCases = userTestCases.Concat(ug.TestCases);
// Get the authenticated user projects based on it's usergroup(s)
userProjects = userProjects.Concat(ug.Projects);
...
}
var usergroup = authenticatedUserEntity.UserGroups.FirstOrDefault();
probably is wrong, since you want all usergroups the user is associated with.
In any case you can easily revert the query to work like this
var testcases = from tc in new QASModel.QASEntities().TestCases
where tc.UserGroup.UserId == USERID
select tc
This way you won't have to execute multiple queries to get all test cases, each FirstOrDefault or ToList or ForEach will actually execute the query.

Resources