niobi-8.x-2.0-alpha4/modules/niobi_form/modules/niobi_app/src/NiobiAppUtilities.php
modules/niobi_form/modules/niobi_app/src/NiobiAppUtilities.php
<?php
namespace Drupal\niobi_app;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Link;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\niobi_app\Entity\NiobiApplicationInterface;
use Drupal\niobi_app\Entity\NiobiApplicationWorkflow;
use Drupal\niobi_app\Entity\NiobiApplicationWorkflowStage;
use Drupal\niobi_app\Plugin\task\Bundle\ApplicationReviewTask;
use Drupal\niobi_app\Entity\NiobiApplication;
use Drupal\niobi_form\Entity\NiobiForm;
use Drupal\node\Entity\Node;
use Drupal\task\Entity\Task;
use Drupal\user\UserInterface;
class NiobiAppUtilities {
const EVENT_APPLICATION_SUBMITTED = 'application_submitted';
/**
* @param UserInterface $reviewer
* @param NiobiApplication $niobi_application
* @param NiobiForm $review_form|NULL
* @return bool
* FALSE means they are not excluded, and OK to assign.
* TRUE means they are excluded, and should not be assigned.
*/
public static function excludedAsReviewer(UserInterface $reviewer, NiobiApplication $niobi_application, NiobiForm $review_form = NULL) {
$plugin_manager = \Drupal::service('plugin.manager.niobi_app');
$plugin_definitions = $plugin_manager->getDefinitions();
// If the user meets an exclusion rule, return that they are excluded.
foreach ($plugin_definitions as $plugin_definition) {
if ($plugin_definition['class']::isExcluded($reviewer, $niobi_application, $review_form)) {
return TRUE;
}
}
// Reviewer was not excluded by any plugin.
return FALSE;
}
/**
* @return array
*/
public static function getDecisionsAsOptions() {
$plugin_manager = \Drupal::service('plugin.manager.niobi_app_decision');
$plugin_definitions = $plugin_manager->getDefinitions();
$ret = [];
foreach ($plugin_definitions as $pd) {
if(isset($pd['id'])) {
$ret[$pd['id']] = $pd['label'];
}
}
return $ret;
}
/**
* @param $workflow_stage_id
* @param string $context
* @return \Drupal\Core\Entity\EntityInterface[]|Node[]
*/
public static function getEmailTemplates($workflow_stage_id, $context = 'review') {
$query = \Drupal::entityQuery('node');
$query->condition('type', 'niobi_app_email_templates');
$query->condition('field_niobi_app_stages', $workflow_stage_id, 'IN');
$query->condition('field_niobi_app_context', $context, 'IN');
$result = $query->execute();
return Node::loadMultiple($result);
}
/**
* @param NiobiApplicationWorkflowStage|NULL $workflow_stage
* @return array
*/
public static function generateStageListForWorkflow(NiobiApplicationWorkflowStage $workflow_stage = NULL) {
$stages = [
'nomination' => t('Nomination'),
'nomination_claim' => t('Claim Nomination'),
'application' => t('Application'),
'review' => t('In Review'),
'decision' => t('Decision Pending'),
'complete' => t('Complete'),
];
if ($workflow_stage) {
if (empty($workflow_stage->getNominationForm())) {
unset($stages['nomination']);
unset($stages['nomination_claim']);
}
if (empty($workflow_stage->getApplicationForm())) {
unset($stages['application']);
}
foreach ($stages as $key => $label) {
$field = 'field_label_for_' . $key;
$val = $workflow_stage->get($field)->getValue();
if (isset($val[0]['value']) && !empty($val[0]['value'])) {
$stages[$key] = $val[0]['value'];
}
}
}
return $stages;
}
/**
* @param NiobiApplicationWorkflowStage|NULL $workflow_stage
* @return array
*/
public static function generateStageListForChecklists(NiobiApplicationWorkflowStage $workflow_stage = NULL) {
$stages = NiobiAppUtilities::generateStageListForWorkflow($workflow_stage);
if (!empty($workflow_stage->getRequiredAddendaForms())) {
$stages['required_addenda'] = t('Required Addenda');
}
if (!empty($workflow_stage->getOptionalAddendaForms())) {
$stages['optional_addenda'] = t('Optional Addenda');
}
$support = $workflow_stage->getSupportLetterInformation();
$support_name = t('Support Letters');
if (!empty($support['name'])) {
$support_name = $support['name'];
}
$labels['support'] = $support_name;
$labels['support_request'] = t('Request for %letter', ['%letter' => $support_name]);
return $stages;
}
/**
* @param $status
* @param NiobiApplicationInterface $application
* @return string
*/
public static function generateStageList($status, NiobiApplicationInterface $application) {
$ret = '<div class="btn-group">';
$stages = NiobiAppUtilities::generateStageListForWorkflow($application->getCurrentApplicationStage());
$stage_identified = FALSE;
foreach ($stages as $stage => $label) {
if ($stage === $status) {
$ret .= '<div class="btn btn-primary">' . $label . '</div>';
$stage_identified = TRUE;
}
else {
if ($stage_identified) {
$ret .= '<div class="btn btn-default">' . $label . '</div>';
}
else {
$ret .= '<div class="btn btn-info">' . $label . '</div>';
}
}
}
$ret .= '</div>';
return $ret;
}
/**
* @param $status
* @param NiobiApplicationWorkflowStage|NULL $workflow_stage
* @return mixed
*/
public static function getStageName($status, NiobiApplicationWorkflowStage $workflow_stage = NULL) {
$stages = NiobiAppUtilities::generateStageListForWorkflow($workflow_stage);
return $stages[$status];
}
/**
* @param NiobiApplication $application
* @param NiobiApplicationWorkflow $workflow
* @return array
* @throws \Drupal\Core\Entity\EntityMalformedException
*/
public static function generateReviewAssignmentRenderArray (NiobiApplication $application, NiobiApplicationWorkflow $workflow) {
if ($workflow->isReadyToUse()) {
$account = \Drupal::currentUser();
$status = $application->get('field_application_status')->getValue()[0]['value'];
$status_name = t('Current Status') . ': ' . NiobiAppUtilities::getStageName($status);
if (!$application->isApplicationAdmin() && $workflow->isOnViewAccessTeam()) {
$conflicts = \Drupal::entityTypeManager()
->getStorage('niobi_conflict_of_interest')
->loadByProperties([
'type' => 'conflict_with_another_user',
'field_applicant' => $application->getOwnerId(),
'field_reviewer' => $account->id()
]);
}
if (!empty($conflicts)) {
$output = [
'#type' => 'html_tag',
'#tag' => 'p',
'value' => [
'#type' => 'html_tag',
'#tag' => 'strong',
'#value' => t('Conflict of interest'),
],
];
} else {
$output = [
'header' => [
'#type' => 'html_tag',
'#tag' => 'p',
'value' => [
'#type' => 'html_tag',
'#tag' => 'strong',
'#value' => t($status_name),
],
],
];
$query = \Drupal::entityQuery('task');
$query->condition('type', 'application_review_task');
$query->condition('field_application', $application->id());
$result = $query->execute();
if (count($result)) {
foreach ($result as $assignment) {
$task = Task::load($assignment);
if ($task) {
$task_status = ApplicationReviewTask::getReviewTaskStatus($task, $application);
if ($task_status === 'not under review') {
$task_url = Url::fromUserInput('#');
}
else {
$assigneeId = current($task->assigned_to->getValue());
// the current user is the task assignee, then get task url
if (!empty($assigneeId['target_id']) && $assigneeId['target_id'] === $account->id()) {
$task_url = $task->toUrl();
} else {
$application = current($task->field_application->referencedEntities());
if (!empty($application)) {
if ($application->isApplicationAdmin()) {
$task_url = $task->toUrl();
}
else {
if ($task_status === 'complete') {
if (!empty($workflow) && $workflow->isOnViewAccessTeam()) {
$review_sub = ApplicationReviewTask::getReviewTaskSubmission($task, $application);
$task_url = $review_sub->toUrl();
}
}
else {
$task_url = Url::fromUserInput('#');
}
}
}
}
}
$add = [
'#type' => 'html_tag',
'#tag' => 'div',
];
$attributes = ['class' => 'btn btn-xs btn-default'];
switch ($task_status) {
case 'complete':
$attributes['class'] = 'btn btn-xs btn-success';
break;
case 'draft':
$attributes['class'] = 'btn btn-xs btn-warning';
break;
case 'not started':
$attributes['class'] = 'btn btn-xs btn-danger';
break;
case 'not under review':
$attributes['class'] = 'btn btn-xs btn-default';
}
$task_url->setOption('attributes', $attributes);
$task_label = $task_status === 'not under review' ? t('%label (Not Under Review)', ['%label' => $task->label()]) : $task->label();
$task_link = Link::fromTextAndUrl($task_label, $task_url);
$add['assignment'] = $task_link->toRenderable();
$output[$task->id()] = $add;
}
}
}
}
}
else {
\Drupal::messenger()->addError('The application has not been fully set up. Please contact the form administrator.');
$output = '<p><em>' . t('The application system is not fully set up.') . '</em></p>';
return ['#type' => 'markup', '#markup' => $output];
}
return [$output];
}
/**
* @param $workflow_id
* @param AccountInterface|NULL $account
* @return bool
*/
public static function hasViewAccess($workflow_id, AccountInterface $account = NULL) {
$account = $account ? $account : \Drupal::currentUser();
$workflow_admin = NiobiAppUtilities::isWorkflowAdmin($workflow_id, $account);
$workflow = NiobiApplicationWorkflow::load($workflow_id);
$view_team = $workflow->isOnViewAccessTeam($account->id());
return $workflow_admin || $view_team;
}
/**
* @param $workflow_id
* @param AccountInterface|NULL $account
* @return bool
*/
public static function isWorkflowAdmin($workflow, AccountInterface $account = NULL) {
$account = $account ? $account : \Drupal::currentUser();
if (is_numeric($workflow)) {
$workflow = NiobiApplicationWorkflow::load($workflow);
}
$workflow_author = $workflow->getOwner();
$is_author = $workflow_author->id() === $account->id();
$permission = $account->hasPermission('administer niobi_app applications');
$admin_team = $workflow->isOnAdminTeam($account->id());
return $is_author || $permission || $admin_team;
}
}
