Commit | Line | Data |
---|---|---|
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 |
21 | class 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 | } |