Merge pull request #23888 from eileenmcnaughton/user_import
[civicrm-core.git] / CRM / Core / BAO / UserJob.php
CommitLineData
a082d2df
EM
1<?php
2/*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
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 +--------------------------------------------------------------------+
10 */
11
12/**
13 *
14 * @package CRM
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
16 */
17
18/**
19 * This class contains user jobs functionality.
20 */
677170bd
TO
21class CRM_Core_BAO_UserJob extends CRM_Core_DAO_UserJob implements \Civi\Core\HookInterface {
22
23 /**
24 * Check on the status of a queue.
25 *
26 * Queues that are attached to a UserJob are necessarily finite - so we can mark them 'completed'
27 * when the task-list reaches empty.
28 *
29 * Note that this runs after processing *every item* in *every queue* (foreground, background,
30 * import, upgrade, ad nauseum). The capacity to handle heavy tasks here is subjective (depending
31 * on the specific queue/use-case). We try to be conservative about I/O until we know that
32 * we're in a suitable context.
33 */
34 public static function on_civi_queue_check(\Civi\Core\Event\GenericHookEvent $e) {
35 /** @var \CRM_Queue_Queue $queue */
36 $queue = $e->queue;
37 $userJobId = static::findUserJobId($queue->getName());
38 if ($userJobId && $queue->numberOfItems() < 1) {
39 $queue->setStatus('completed');
40 }
41 }
42
43 /**
44 * If the `civicrm_queue` changes status, then the `civicrm_user_job` should also change status.
45 *
46 * @param \CRM_Queue_Queue $queue
47 * @param string $status
48 * @throws \API_Exception
49 * @throws \Civi\API\Exception\UnauthorizedException
50 * @see \CRM_Utils_Hook::queueStatus()
51 */
52 public static function hook_civicrm_queueStatus(CRM_Queue_Queue $queue, string $status) {
53 $userJobId = static::findUserJobId($queue->getName());
54 if ($userJobId && $status === 'completed') {
55 \Civi\Api4\UserJob::update()
56 ->addWhere('id', '=', $userJobId)
57 ->setValues(['status_id' => 1])
58 ->execute();
59 }
60 }
61
62 private static function findUserJobId(string $queueName): ?int {
63 if (CRM_Core_Config::isUpgradeMode()) {
64 return NULL;
65 }
66
67 $key = 'userJobId_' . $queueName;
68 if (!isset(Civi::$statics[__CLASS__][$key])) {
69 // Part of the primary structure/purpose of the queue. Shouldn't change.
70 $userJobId = CRM_Core_DAO::singleValueQuery('
71 SELECT uj.id FROM civicrm_queue q
72 INNER JOIN civicrm_user_job uj ON q.id = uj.queue_id
73 WHERE q.name = %1
74 ', [
75 1 => [$queueName, 'String'],
76 ]);
77 Civi::$statics[__CLASS__][$key] = $userJobId;
78 }
79 return Civi::$statics[__CLASS__][$key];
80 }
a082d2df 81
e36f7ee1
EM
82 /**
83 * Restrict access to the relevant user.
84 *
85 * Note that it is likely we might want to permit other users such as
86 * sysadmins to access other people's user_jobs in future but it has been
87 * kept tightly restricted for initial simplicity (ie do we want to
88 * use an existing permission? a new permission ? do they require
89 * 'view all contacts' etc.
90 *
91 * @inheritDoc
92 */
93 public function addSelectWhereClause(): array {
9e10c913
TO
94 $clauses = [];
95 if (!\CRM_Core_Permission::check('administer queues')) {
96 $clauses['created_id'] = '= ' . (int) CRM_Core_Session::getLoggedInContactID();
97 }
98 CRM_Utils_Hook::selectWhereClause($this, $clauses);
e36f7ee1
EM
99 return $clauses;
100 }
101
a082d2df
EM
102 /**
103 * Get the statuses for Import Jobs.
104 *
105 * @return array
106 */
107 public static function getStatuses(): array {
108 return [
109 [
110 'id' => 1,
111 'name' => 'completed',
112 'label' => ts('Completed'),
113 ],
114 [
115 'id' => 2,
7b057b66
EM
116 'name' => 'draft',
117 'label' => ts('Draft'),
118 ],
119 [
120 'id' => 3,
a082d2df
EM
121 'name' => 'scheduled',
122 'label' => ts('Scheduled'),
123 ],
124 [
7b057b66 125 'id' => 4,
a082d2df
EM
126 'name' => 'in_progress',
127 'label' => ts('In Progress'),
128 ],
129 ];
130 }
131
132 /**
133 * Get the types Import Jobs.
134 *
135 * This is largely a placeholder at this stage. It will likely wind
136 * up as an option value so extensions can add different types.
137 *
138 * However, for now it just holds the one type being worked on.
139 *
140 * @return array
141 */
142 public static function getTypes(): array {
143 return [
144 [
d2b81f5a 145 'id' => 'contact_import',
a082d2df
EM
146 'name' => 'contact_import',
147 'label' => ts('Contact Import'),
08a76614
EM
148 'class' => 'CRM_Contact_Import_Parser_Contact',
149 ],
150 [
d2b81f5a 151 'id' => 'contribution_import',
08a76614
EM
152 'name' => 'contribution_import',
153 'label' => ts('Contribution Import'),
154 'class' => 'CRM_Contribute_Import_Parser_Contribution',
155 ],
156 [
d2b81f5a 157 'id' => 'membership_import',
08a76614
EM
158 'name' => 'membership_import',
159 'label' => ts('Membership Import'),
160 'class' => 'CRM_Member_Import_Parser_Membership',
161 ],
162 [
d2b81f5a 163 'id' => 'activity_import',
08a76614
EM
164 'name' => 'activity_import',
165 'label' => ts('Activity Import'),
166 'class' => 'CRM_Activity_Import_Parser_Activity',
167 ],
168 [
d2b81f5a 169 'id' => 'participant_import',
08a76614
EM
170 'name' => 'participant_import',
171 'label' => ts('Participant Import'),
172 'class' => 'CRM_Event_Import_Parser_Participant',
173 ],
174 [
d2b81f5a 175 'id' => 'custom_field_import',
08a76614
EM
176 'name' => 'custom_field_import',
177 'label' => ts('Multiple Value Custom Field Import'),
178 'class' => 'CRM_Custom_Import_Parser_Api',
a082d2df
EM
179 ],
180 ];
181 }
182
183}