3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
18 use Civi\Core\ClassScanner
;
19 use Civi\UserJob\UserJobInterface
;
22 * This class contains user jobs functionality.
24 class CRM_Core_BAO_UserJob
extends CRM_Core_DAO_UserJob
implements \Civi\Core\HookInterface
{
27 * Check on the status of a queue.
29 * Queues that are attached to a UserJob are necessarily finite - so we can mark them 'completed'
30 * when the task-list reaches empty.
32 * Note that this runs after processing *every item* in *every queue* (foreground, background,
33 * import, upgrade, ad nauseum). The capacity to handle heavy tasks here is subjective (depending
34 * on the specific queue/use-case). We try to be conservative about I/O until we know that
35 * we're in a suitable context.
37 public static function on_civi_queue_check(\Civi\Core\Event\GenericHookEvent
$e) {
38 /** @var \CRM_Queue_Queue $queue */
40 $userJobId = static::findUserJobId($queue->getName());
41 if ($userJobId && $queue->numberOfItems() < 1) {
42 $queue->setStatus('completed');
47 * If the `civicrm_queue` changes status, then the `civicrm_user_job` should also change status.
49 * @param \CRM_Queue_Queue $queue
50 * @param string $status
51 * @throws \API_Exception
52 * @throws \Civi\API\Exception\UnauthorizedException
53 * @see \CRM_Utils_Hook::queueStatus()
55 public static function hook_civicrm_queueStatus(CRM_Queue_Queue
$queue, string $status) {
56 $userJobId = static::findUserJobId($queue->getName());
57 if ($userJobId && $status === 'completed') {
58 \Civi\Api4\UserJob
::update()
59 ->addWhere('id', '=', $userJobId)
60 ->setValues(['status_id' => 1])
65 private static function findUserJobId(string $queueName): ?
int {
66 if (CRM_Core_Config
::isUpgradeMode()) {
70 $key = 'userJobId_' . $queueName;
71 if (!isset(Civi
::$statics[__CLASS__
][$key])) {
72 // Part of the primary structure/purpose of the queue. Shouldn't change.
73 $userJobId = CRM_Core_DAO
::singleValueQuery('
74 SELECT uj.id FROM civicrm_queue q
75 INNER JOIN civicrm_user_job uj ON q.id = uj.queue_id
78 1 => [$queueName, 'String'],
80 Civi
::$statics[__CLASS__
][$key] = $userJobId;
82 return Civi
::$statics[__CLASS__
][$key];
86 * Restrict access to the relevant user.
88 * Note that it is likely we might want to permit other users such as
89 * sysadmins to access other people's user_jobs in future but it has been
90 * kept tightly restricted for initial simplicity (ie do we want to
91 * use an existing permission? a new permission ? do they require
92 * 'view all contacts' etc.
96 public function addSelectWhereClause(): array {
98 if (!\CRM_Core_Permission
::check('administer queues')) {
99 $clauses['created_id'] = '= ' . (int) CRM_Core_Session
::getLoggedInContactID();
101 CRM_Utils_Hook
::selectWhereClause($this, $clauses);
106 * Get the statuses for Import Jobs.
110 public static function getStatuses(): array {
114 'name' => 'completed',
115 'label' => ts('Completed'),
120 'label' => ts('Draft'),
124 'name' => 'scheduled',
125 'label' => ts('Scheduled'),
129 'name' => 'in_progress',
130 'label' => ts('In Progress'),
136 * Get the types Import Jobs.
138 * This is largely a placeholder at this stage. It will likely wind
139 * up as an option value so extensions can add different types.
141 * However, for now it just holds the one type being worked on.
145 public static function getTypes(): array {
146 $types = Civi
::cache()->get('UserJobTypes');
147 if ($types === NULL) {
149 $classes = ClassScanner
::get(['interface' => UserJobInterface
::class]);
150 foreach ($classes as $class) {
151 $declaredTypes = $class::getUserJobInfo();
152 foreach ($declaredTypes as $index => $declaredType) {
153 $declaredTypes[$index]['class'] = $class;
155 $types = array_merge($types, $declaredTypes);
157 Civi
::cache()->set('UserJobTypes', $types);
159 // Rekey to numeric to prevent https://lab.civicrm.org/dev/core/-/issues/3719
160 return array_values($types);