Open Journal Systems  3.3.0
PKPUserService.inc.php
1 <?php
15 namespace PKP\Services;
16 
17 use \Application;
18 use \DBResultRange;
19 use \DAOResultFactory;
20 use \DAORegistry;
21 use \Services;
22 use \PKP\Services\interfaces\EntityPropertyInterface;
23 use \PKP\Services\interfaces\EntityReadInterface;
24 use \PKP\Services\QueryBuilders\PKPUserQueryBuilder;
25 
26 class PKPUserService implements EntityPropertyInterface, EntityReadInterface {
27 
31  public function get($userId) {
32  $userDao = DAORegistry::getDAO('UserDAO'); /* @var $userDao UserDAO */
33  return $userDao->getById($userId);
34  }
35 
39  public function getCount($args = []) {
40  return $this->getQueryBuilder($args)->getCount();
41  }
42 
46  public function getIds($args = []) {
47  return $this->getQueryBuilder($args)->getIds();
48  }
49 
71  public function getMany($args = []) {
72  $range = null;
73  if (isset($args['count'])) {
74  import('lib.pkp.classes.db.DBResultRange');
75  $range = new \DBResultRange($args['count'], null, isset($args['offset']) ? $args['offset'] : 0);
76  }
77  // Pagination is handled by the DAO, so don't pass count and offset
78  // arguments to the QueryBuilder.
79  if (isset($args['count'])) unset($args['count']);
80  if (isset($args['offset'])) unset($args['offset']);
81  $userListQO = $this->getQueryBuilder($args)->getQuery();
82  $userDao = DAORegistry::getDAO('UserDAO'); /* @var $userDao UserDAO */
83  $result = $userDao->retrieveRange($userListQO->toSql(), $userListQO->getBindings(), $range);
84  $queryResults = new DAOResultFactory($result, $userDao, '_returnUserFromRowWithData');
85 
86  return $queryResults->toIterator();
87  }
88 
92  public function getMax($args = []) {
93  // Don't accept args to limit the results
94  if (isset($args['count'])) unset($args['count']);
95  if (isset($args['offset'])) unset($args['offset']);
96  return $this->getQueryBuilder($args)->getCount();
97  }
98 
103  public function getQueryBuilder($args = []) {
104  $defaultArgs = array(
105  'contextId' => CONTEXT_ID_NONE,
106  'orderBy' => 'id',
107  'orderDirection' => 'DESC',
108  'roleIds' => null,
109  'assignedToSubmission' => null,
110  'assignedToSubmissionStage' => null,
111  'registeredAfter' => '',
112  'registeredBefore' => '',
113  'includeUsers' => null,
114  'excludeUsers' => null,
115  'status' => 'active',
116  'searchPhrase' => null,
117  );
118 
119  $args = array_merge($defaultArgs, $args);
120 
121  $userListQB = new PKPUserQueryBuilder();
122  $userListQB
123  ->filterByContext($args['contextId'])
124  ->orderBy($args['orderBy'], $args['orderDirection'])
125  ->filterByRoleIds($args['roleIds'])
126  ->assignedToSubmission($args['assignedToSubmission'], $args['assignedToSubmissionStage'])
127  ->registeredAfter($args['registeredAfter'])
128  ->registeredBefore($args['registeredBefore'])
129  ->includeUsers($args['includeUsers'])
130  ->excludeUsers($args['excludeUsers'])
131  ->filterByStatus($args['status'])
132  ->searchPhrase($args['searchPhrase']);
133 
134  if (isset($args['count'])) {
135  $userListQB->limitTo($args['count']);
136  }
137 
138  if (isset($args['offset'])) {
139  $userListQB->offsetBy($args['count']);
140  }
141 
142  if (isset($args['assignedToSection'])) {
143  $userListQB->assignedToSection($args['assignedToSection']);
144  }
145 
146  if (isset($args['assignedToCategory'])) {
147  $userListQB->assignedToCategory($args['assignedToCategory']);
148  }
149 
150  \HookRegistry::call('User::getMany::queryBuilder', array($userListQB, $args));
151 
152  return $userListQB;
153  }
154 
162  public function getReviewers($args = []) {
163  $range = null;
164  if (isset($args['count'])) {
165  import('lib.pkp.classes.db.DBResultRange');
166  $range = new \DBResultRange($args['count'], null, isset($args['offset']) ? $args['offset'] : 0);
167  }
168  // Pagination is handled by the DAO, so don't pass count and offset
169  // arguments to the QueryBuilder.
170  if (isset($args['count'])) unset($args['count']);
171  if (isset($args['offset'])) unset($args['offset']);
172  $userListQO = $this->getReviewersQueryBuilder($args)->getQuery();
173  $userDao = DAORegistry::getDAO('UserDAO'); /* @var $userDao UserDAO */
174  $result = $userDao->retrieveRange($userListQO->toSql(), $userListQO->getBindings(), $range);
175  $queryResults = new DAOResultFactory($result, $userDao, '_returnUserFromRowWithReviewerStats');
176 
177  return $queryResults->toIterator();
178  }
179 
186  public function getReviewersMax($args = []) {
187  // Don't accept args to limit the results
188  if (isset($args['count'])) unset($args['count']);
189  if (isset($args['offset'])) unset($args['offset']);
190  return $this->getReviewersQueryBuilder($args)->getCount();
191  }
192 
199  public function getReviewersQueryBuilder($args = []) {
200 
201  $defaultArgs = array(
202  'contextId' => CONTEXT_ID_NONE,
203  'reviewStage' => null,
204  'reviewsCompleted' => null,
205  'reviewsActive' => null,
206  'daysSinceLastAssignment' => null,
207  'averageCompletion' => null,
208  'reviewerRating' => null,
209  );
210 
211  $args = array_merge($defaultArgs, $args);
212  $args['roleIds'] = [ROLE_ID_REVIEWER];
213 
214  $reviewerListQB = $this->getQueryBuilder($args);
215  $reviewerListQB
216  ->getReviewerData(true)
217  ->filterByReviewStage($args['reviewStage'])
218  ->filterByReviewerRating($args['reviewerRating'])
219  ->filterByReviewsCompleted($args['reviewsCompleted'])
220  ->filterByReviewsActive($args['reviewsActive'])
221  ->filterByDaysSinceLastAssignment($args['daysSinceLastAssignment'])
222  ->filterByAverageCompletion($args['averageCompletion']);
223 
224  \HookRegistry::call('User::getReviewers::queryBuilder', array($reviewerListQB, $args));
225 
226  return $reviewerListQB;
227  }
228 
232  public function getProperties($user, $props, $args = null) {
233  $request = $args['request'];
234  $context = $request->getContext();
235  $dispatcher = $request->getDispatcher();
236 
237  $values = array();
238  foreach ($props as $prop) {
239  switch ($prop) {
240  case 'id':
241  $values[$prop] = (int) $user->getId();
242  break;
243  case 'userName':
244  $values[$prop] = $user->getUserName();
245  break;
246  case 'fullName':
247  $values[$prop] = $user->getFullName();
248  break;
249  case 'givenName':
250  $values[$prop] = $user->getGivenName(null);
251  break;
252  case 'familyName':
253  $values[$prop] = $user->getFamilyName(null);
254  break;
255  case 'affiliation':
256  $values[$prop] = $user->getAffiliation(null);
257  break;
258  case 'country':
259  $values[$prop] = $user->getCountry();
260  break;
261  case 'url':
262  $values[$prop] = $user->getUrl();
263  break;
264  case 'email':
265  $values[$prop] = $user->getEmail();
266  break;
267  case 'orcid':
268  $values[$prop] = $user->getOrcid();
269  break;
270  case 'biography':
271  $values[$prop] = $user->getBiography(null);
272  break;
273  case 'signature':
274  $values[$prop] = $user->getSignature(null);
275  break;
276  case 'authId':
277  $values[$prop] = $user->getAuthId();
278  break;
279  case 'authString':
280  $values[$prop] = $user->getAuthStr();
281  break;
282  case 'phone':
283  $values[$prop] = $user->getPhone();
284  break;
285  case 'mailingAddress':
286  $values[$prop] = $user->getMailingAddress();
287  break;
288  case 'billingAddress':
289  $values[$prop] = $user->getBillingAddress();
290  break;
291  case 'gossip':
292  if ($this->canCurrentUserGossip($user->getId())) {
293  $values[$prop] = $user->getGossip();
294  }
295  break;
296  case 'reviewsActive':
297  $values[$prop] = $user->getData('incompleteCount');
298  break;
299  case 'reviewsCompleted':
300  $values[$prop] = $user->getData('completeCount');
301  break;
302  case 'reviewsDeclined':
303  $values[$prop] = $user->getData('declinedCount');
304  break;
305  case 'reviewsCancelled':
306  $values[$prop] = $user->getData('cancelledCount');
307  break;
308  case 'averageReviewCompletionDays':
309  $values[$prop] = $user->getData('averageTime');
310  break;
311  case 'dateLastReviewAssignment':
312  $values[$prop] = $user->getData('lastAssigned');
313  break;
314  case 'reviewerRating':
315  $values[$prop] = $user->getData('reviewerRating');
316  break;
317  case 'disabled':
318  $values[$prop] = (boolean) $user->getDisabled();
319  break;
320  case 'disabledReason':
321  $values[$prop] = $user->getDisabledReason();
322  break;
323  case 'dateRegistered':
324  $values[$prop] = $user->getDateRegistered();
325  break;
326  case 'dateValidated':
327  $values[$prop] = $user->getDateValidated();
328  break;
329  case 'dateLastLogin':
330  $values[$prop] = $user->getDateLastLogin();
331  break;
332  case 'mustChangePassword':
333  $values[$prop] = (boolean) $user->getMustChangePassword();
334  break;
335  case '_href':
336  $values[$prop] = null;
337  if (!empty($args['slimRequest'])) {
338  $route = $args['slimRequest']->getAttribute('route');
339  $arguments = $route->getArguments();
340  $values[$prop] = $dispatcher->url(
341  $args['request'],
342  ROUTE_API,
343  $arguments['contextPath'],
344  'users/' . $user->getId()
345  );
346  }
347  break;
348  case 'groups':
349  $values[$prop] = null;
350  if ($context) {
351  import('lib.pkp.classes.security.UserGroupDAO');
352  $userGroupDao = DAORegistry::getDAO('UserGroupDAO'); /* @var $userGroupDao UserGroupDAO */
353  $userGroups = $userGroupDao->getByUserId($user->getId(), $context->getId());
354  $values[$prop] = array();
355  while ($userGroup = $userGroups->next()) {
356  $values[$prop][] = array(
357  'id' => (int) $userGroup->getId(),
358  'name' => $userGroup->getName(null),
359  'abbrev' => $userGroup->getAbbrev(null),
360  'roleId' => (int) $userGroup->getRoleId(),
361  'showTitle' => (boolean) $userGroup->getShowTitle(),
362  'permitSelfRegistration' => (boolean) $userGroup->getPermitSelfRegistration(),
363  'permitMetadataEdit' => (boolean) $userGroup->getPermitMetadataEdit(),
364  'recommendOnly' => (boolean) $userGroup->getRecommendOnly(),
365  );
366  }
367  }
368  break;
369  case 'interests':
370  $values[$prop] = [];
371  if ($context) {
372  import('lib.pkp.classes.user.InterestDAO');
373  $interestDao = DAORegistry::getDAO('InterestDAO'); /* @var $interestDao InterestDAO */
374  $interestEntryIds = $interestDao->getUserInterestIds($user->getId());
375  if (!empty($interestEntryIds)) {
376  import('lib.pkp.classes.user.InterestEntryDAO');
377  $interestEntryDao = DAORegistry::getDAO('InterestEntryDAO'); /* @var $interestEntryDao InterestEntryDAO */
378  $results = $interestEntryDao->getByIds($interestEntryIds);
379  $values[$prop] = array();
380  while ($interest = $results->next()) {
381  $values[$prop][] = array(
382  'id' => (int) $interest->getId(),
383  'interest' => $interest->getInterest(),
384  );
385  }
386  }
387  }
388  break;
389  }
390 
391  $values = Services::get('schema')->addMissingMultilingualValues(SCHEMA_USER, $values, $context->getSupportedFormLocales());
392 
393  \HookRegistry::call('User::getProperties::values', array(&$values, $user, $props, $args));
394 
395  ksort($values);
396  }
397 
398  return $values;
399  }
400 
404  public function getSummaryProperties($user, $args = null) {
405  $props = array (
406  'id','_href','userName','email','fullName','orcid','groups','disabled',
407  );
408 
409  \HookRegistry::call('User::getProperties::summaryProperties', array(&$props, $user, $args));
410 
411  return $this->getProperties($user, $props, $args);
412  }
413 
417  public function getFullProperties($user, $args = null) {
418  $props = array (
419  'id','userName','fullName','givenName','familyName','affiliation','country','email','url',
420  'orcid','groups','interests','biography','signature','authId','authString','phone',
421  'mailingAddress','billingAddress','gossip','disabled','disabledReason',
422  'dateRegistered','dateValidated','dateLastLogin','mustChangePassword',
423  );
424 
425  \HookRegistry::call('User::getProperties::fullProperties', array(&$props, $user, $args));
426 
427  return $this->getProperties($user, $props, $args);
428  }
429 
438  public function getReviewerSummaryProperties($user, $args = null) {
439  $props = array (
440  'id','_href','userName','fullName','affiliation','biography','groups','interests','gossip',
441  'reviewsActive','reviewsCompleted','reviewsDeclined','reviewsCancelled','averageReviewCompletionDays',
442  'dateLastReviewAssignment','reviewerRating', 'orcid','disabled',
443  );
444 
445  \HookRegistry::call('User::getProperties::reviewerSummaryProperties', array(&$props, $user, $args));
446 
447  return $this->getProperties($user, $props, $args);
448  }
449 
458  public function userHasRole($userId, $roleIds, $contextId) {
459  $roleDao = DAORegistry::getDAO('RoleDAO'); /* @var $roleDao RoleDAO */
460  return $roleDao->userHasRole($contextId, $userId, $roleIds);
461  }
462 
469  public function canCurrentUserGossip($userId) {
470  $request = Application::get()->getRequest();
471  $context = $request->getContext();
472  $contextId = $context ? $context->getId() : CONTEXT_ID_NONE;
473  $currentUser = $request->getUser();
474 
475  // Logged out users can never view gossip fields
476  if (!$currentUser) {
477  return false;
478  }
479 
480  // Users can never view their own gossip fields
481  if ($currentUser->getId() === $userId) {
482  return false;
483  }
484 
485  // Only reviewers have gossip fields
486  if (!$this->userHasRole($userId, ROLE_ID_REVIEWER, $contextId)) {
487  return false;
488  }
489 
490  // Only admins, editors and subeditors can view gossip fields
491  if (!$this->userHasRole($currentUser->getId(), array(ROLE_ID_MANAGER, ROLE_ID_SITE_ADMIN, ROLE_ID_SUB_EDITOR), $contextId)) {
492  return false;
493  }
494 
495  return true;
496  }
497 
511  public function canUserAccessStage($stageId, $workflowType, $userAccessibleStages, $userRoles) {
512  $workflowRoles = Application::get()->getWorkflowTypeRoles()[$workflowType];
513 
514  if (array_key_exists($stageId, $userAccessibleStages)
515  && !empty(array_intersect($workflowRoles, $userAccessibleStages[$stageId]))) {
516  return true;
517  }
518  if (empty($userAccessibleStages) && in_array(ROLE_ID_MANAGER, $userRoles)) {
519  return true;
520  }
521  return false;
522  }
523 
532  public function getAccessibleStageRoles($userId, $contextId, &$submission, $stageId) {
533 
534  $stageAssignmentDao = DAORegistry::getDAO('StageAssignmentDAO'); /* @var $stageAssignmentDao StageAssignmentDAO */
535  $stageAssignmentsResult = $stageAssignmentDao->getBySubmissionAndUserIdAndStageId($submission->getId(), $userId, $stageId);
536 
537  $accessibleStageRoles = array();
538 
539  // If unassigned, only managers and admins have access
540  if ($stageAssignmentsResult->wasEmpty()) {
541  $roleDao = DAORegistry::getDAO('RoleDAO'); /* @var $roleDao RoleDAO */
542  $userRoles = $roleDao->getByUserId($userId, $contextId);
543  foreach ($userRoles as $userRole) {
544  if (in_array($userRole->getId(), array(ROLE_ID_SITE_ADMIN, ROLE_ID_MANAGER))) {
545  $accessibleStageRoles[] = $userRole->getId();
546  }
547  }
548  $accessibleStageRoles = array_unique($accessibleStageRoles);
549  // Assigned users have access based on their assignment
550  } else {
551  $userGroupDao = DAORegistry::getDAO('UserGroupDAO'); /* @var $userGroupDao UserGroupDAO */
552  while ($stageAssignment = $stageAssignmentsResult->next()) {
553  $userGroup = $userGroupDao->getById($stageAssignment->getUserGroupId(), $contextId);
554  $accessibleStageRoles[] = $userGroup->getRoleId();
555  }
556  $accessibleStageRoles = array_unique($accessibleStageRoles);
557  }
558 
559  return $accessibleStageRoles;
560  }
561 
567  public function count($args = []) {
568  $qb = $this->getQueryBuilder($args);
569  return $qb->getQuery()->get()->count();
570  }
571 
579  public function getRolesOverview($args = []) {
580  \AppLocale::requireComponents(LOCALE_COMPONENT_PKP_USER, LOCALE_COMPONENT_PKP_MANAGER, LOCALE_COMPONENT_APP_MANAGER);
581 
582  // Ignore roles because we'll get all roles in the application
583  if (isset($args['roleIds'])) {
584  unset($args['roleIds']);
585  }
586 
587  $result = [
588  [
589  'id' => 'total',
590  'name' => 'stats.allUsers',
591  'value' => $this->count($args),
592  ],
593  ];
594 
595  $roleNames = Application::get()->getRoleNames();
596 
597  // Don't include the admin user if we are limiting the overview to one context
598  if (!empty($args['contextId'])) {
599  unset($roleNames[ROLE_ID_SITE_ADMIN]);
600  }
601 
602  foreach ($roleNames as $roleId => $roleName) {
603  $result[] = [
604  'id' => $roleId,
605  'name' => $roleName,
606  'value' => $this->count(array_merge($args, ['roleIds' => $roleId])),
607  ];
608  }
609 
610  return $result;
611  }
612 }
PKP\Services
AppLocale\requireComponents
static requireComponents()
Definition: env1/MockAppLocale.inc.php:56
PKP\Services\PKPUserService\getRolesOverview
getRolesOverview($args=[])
Definition: PKPUserService.inc.php:579
DAOResultFactory
Wrapper around ADORecordSet providing "factory" features for generating objects from DAOs.
Definition: DAOResultFactory.inc.php:21
PKP\Services\PKPUserService\count
count($args=[])
Definition: PKPUserService.inc.php:567
DAORegistry\getDAO
static & getDAO($name, $dbconn=null)
Definition: DAORegistry.inc.php:57
PKP\Services\PKPUserService\getReviewers
getReviewers($args=[])
Definition: PKPUserService.inc.php:162
PKP\Services\PKPUserService
Definition: PKPUserService.inc.php:26
PKP\Services\PKPUserService\getReviewersQueryBuilder
getReviewersQueryBuilder($args=[])
Definition: PKPUserService.inc.php:199
PKP\Services\PKPUserService\userHasRole
userHasRole($userId, $roleIds, $contextId)
Definition: PKPUserService.inc.php:458
PKP\Services\PKPUserService\getQueryBuilder
getQueryBuilder($args=[])
Definition: PKPUserService.inc.php:103
PKP\Services\PKPUserService\canUserAccessStage
canUserAccessStage($stageId, $workflowType, $userAccessibleStages, $userRoles)
Definition: PKPUserService.inc.php:511
PKP\Services\PKPUserService\getFullProperties
getFullProperties($user, $args=null)
Definition: PKPUserService.inc.php:417
PKP\Services\PKPUserService\getIds
getIds($args=[])
Definition: PKPUserService.inc.php:46
PKP\Services\SCHEMA_USER
const SCHEMA_USER
Definition: PKPSchemaService.inc.php:30
PKP\Services\PKPUserService\getAccessibleStageRoles
getAccessibleStageRoles($userId, $contextId, &$submission, $stageId)
Definition: PKPUserService.inc.php:532
PKP\Services\PKPUserService\getReviewerSummaryProperties
getReviewerSummaryProperties($user, $args=null)
Definition: PKPUserService.inc.php:438
PKP\Services\PKPUserService\getMax
getMax($args=[])
Definition: PKPUserService.inc.php:92
PKP\Services\PKPUserService\canCurrentUserGossip
canCurrentUserGossip($userId)
Definition: PKPUserService.inc.php:469
PKP\Services\PKPUserService\getCount
getCount($args=[])
Definition: PKPUserService.inc.php:39
PKP\Services\PKPUserService\getSummaryProperties
getSummaryProperties($user, $args=null)
Definition: PKPUserService.inc.php:404
PKP\Services\PKPUserService\getReviewersMax
getReviewersMax($args=[])
Definition: PKPUserService.inc.php:186
PKP\Services\PKPUserService\getProperties
getProperties($user, $props, $args=null)
Definition: PKPUserService.inc.php:232
PKPApplication\get
static get()
Definition: PKPApplication.inc.php:235
HookRegistry\call
static call($hookName, $args=null)
Definition: HookRegistry.inc.php:86
PKP\Services\PKPUserService\getMany
getMany($args=[])
Definition: PKPUserService.inc.php:71
PKP\Services\QueryBuilders\PKPUserQueryBuilder
Definition: PKPUserQueryBuilder.inc.php:20
PKPServices\get
static get($service)
Definition: PKPServices.inc.php:49