Commit | Line | Data |
---|---|---|
9ea6ff40 C |
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 | * Upgrade logic for the 5.47.x series. | |
14 | * | |
15 | * Each minor version in the series is handled by either a `5.47.x.mysql.tpl` file, | |
16 | * or a function in this class named `upgrade_5_47_x`. | |
17 | * If only a .tpl file exists for a version, it will be run automatically. | |
18 | * If the function exists, it must explicitly add the 'runSql' task if there is a corresponding .mysql.tpl. | |
19 | * | |
68cc0e2e | 20 | * This class may also implement `setPreUpgradeMessage()` and `setPostUpgradeMessage()` functions. |
9ea6ff40 C |
21 | */ |
22 | class CRM_Upgrade_Incremental_php_FiveFortySeven extends CRM_Upgrade_Incremental_Base { | |
23 | ||
fe8c33a3 EM |
24 | /** |
25 | * Compute any messages which should be displayed before upgrade. | |
26 | * | |
27 | * Note: This function is called iteratively for each incremental upgrade step. | |
28 | * There must be a concrete step (eg 'X.Y.Z.mysql.tpl' or 'upgrade_X_Y_Z()'). | |
29 | * | |
30 | * @param string $preUpgradeMessage | |
31 | * @param string $rev | |
32 | * a version number, e.g. '4.4.alpha1', '4.4.beta3', '4.4.0'. | |
33 | * @param null $currentVer | |
34 | */ | |
35 | public function setPreUpgradeMessage(&$preUpgradeMessage, $rev, $currentVer = NULL): void { | |
36 | if ($rev === '5.47.alpha1') { | |
37 | $count = CRM_Core_DAO::singleValueQuery('SELECT count(*) FROM civicrm_contact WHERE preferred_mail_format != "Both"'); | |
38 | if ($count) { | |
39 | $preUpgradeMessage .= '<p>' . ts('The contact field preferred mail format is being phased out. Modern email clients can handle receiving both formats so CiviCRM is moving towards always sending both and the field will be incrementally removed from the UI.') | |
40 | . ' <a href="https://lab.civicrm.org/dev/core/-/issues/2866">' . ts('See the issue for more detail') . '</a></p>'; | |
41 | } | |
79b6ac2b CW |
42 | // Check for custom groups with duplicate names |
43 | $dupes = CRM_Core_DAO::singleValueQuery('SELECT COUNT(g1.id) FROM civicrm_custom_group g1, civicrm_custom_group g2 WHERE g1.name = g2.name AND g1.id > g2.id'); | |
44 | if ($dupes) { | |
45 | $preUpgradeMessage .= '<p>' . | |
46 | ts('Your system has custom field groups with duplicate internal names. To ensure data integrity, the internal names will be automatically changed; user-facing titles will not be affected. Please review any custom code you may be using which relies on custom field group names.') . | |
47 | '</p>'; | |
48 | } | |
fe8c33a3 EM |
49 | } |
50 | } | |
51 | ||
9ea6ff40 C |
52 | /** |
53 | * Upgrade step; adds tasks including 'runSql'. | |
54 | * | |
55 | * @param string $rev | |
56 | * The version number matching this function name | |
57 | */ | |
58 | public function upgrade_5_47_alpha1($rev): void { | |
59 | $this->addTask(ts('Upgrade DB to %1: SQL', [1 => $rev]), 'runSql', $rev); | |
df014828 | 60 | $this->addTask('Migrate CiviGrant component to an extension', 'migrateCiviGrant'); |
a0efcd4d EM |
61 | $this->addTask('Add created_date to civicrm_relationship', 'addColumn', 'civicrm_relationship', 'created_date', |
62 | "timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Relationship created date'" | |
63 | ); | |
64 | $this->addTask('Add modified_date column to civicrm_relationship', 'addColumn', | |
65 | 'civicrm_relationship', 'modified_date', | |
66 | "timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'Relationship last modified.'" | |
67 | ); | |
68 | $this->addTask('Set initial value for relationship created_date and modified_date to start_date', 'updateRelationshipDates'); | |
f61cf6ab FW |
69 | $this->addTask('core-issue#2122 - Add timezone column to Events', 'addColumn', |
70 | 'civicrm_event', 'event_tz', "text NULL DEFAULT NULL COMMENT 'Event\'s native time zone'" | |
71 | ); | |
72 | $this->addTask('core-issue#2122 - Set the timezone to the default for existing Events', 'setEventTZDefault'); | |
79b6ac2b CW |
73 | $this->addTask('Drop CustomGroup UI_name_extends index', 'dropIndex', 'civicrm_custom_group', 'UI_name_extends'); |
74 | $this->addTask('Add CustomGroup UI_name index', 'addIndex', 'civicrm_custom_group', ['name'], 'UI'); | |
df014828 CW |
75 | } |
76 | ||
77 | /** | |
78 | * @param \CRM_Queue_TaskContext $ctx | |
a0efcd4d EM |
79 | * |
80 | * @return bool | |
81 | */ | |
82 | public static function updateRelationshipDates(CRM_Queue_TaskContext $ctx): bool { | |
83 | CRM_Core_DAO::executeQuery(' | |
84 | UPDATE civicrm_relationship SET created_date = start_date, modified_date = start_date | |
85 | WHERE start_date IS NOT NULL AND start_date > "1970-01-01" | |
86 | '); | |
87 | return TRUE; | |
88 | } | |
89 | ||
90 | /** | |
91 | * @param \CRM_Queue_TaskContext $ctx | |
92 | * | |
df014828 | 93 | * @return bool |
a0efcd4d EM |
94 | * @throws \API_Exception |
95 | * @throws \CRM_Core_Exception | |
96 | * @throws \Civi\API\Exception\NotImplementedException | |
df014828 CW |
97 | */ |
98 | public static function migrateCiviGrant(CRM_Queue_TaskContext $ctx): bool { | |
99 | $civiGrantEnabled = in_array('CiviGrant', Civi::settings()->get('enable_components'), TRUE); | |
100 | if ($civiGrantEnabled) { | |
101 | CRM_Core_BAO_ConfigSetting::disableComponent('CiviGrant'); | |
102 | } | |
103 | $civiGrantId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Component', 'CiviGrant', 'id', 'name'); | |
104 | if ($civiGrantId) { | |
105 | foreach (['civicrm_menu', 'civicrm_option_value'] as $table) { | |
106 | CRM_Core_DAO::executeQuery("UPDATE $table SET component_id = NULL WHERE component_id = $civiGrantId", [], TRUE, NULL, FALSE, FALSE); | |
107 | } | |
108 | CRM_Core_DAO::executeQuery("DELETE FROM civicrm_component WHERE name = 'CiviGrant'", [], TRUE, NULL, FALSE, FALSE); | |
109 | } | |
110 | $ext = new CRM_Core_DAO_Extension(); | |
111 | $ext->full_name = 'civigrant'; | |
112 | if (!$ext->find(TRUE)) { | |
113 | $ext->type = 'module'; | |
114 | $ext->name = 'CiviGrant'; | |
115 | $ext->label = ts('CiviGrant'); | |
116 | $ext->file = 'civigrant'; | |
117 | $ext->is_active = (int) $civiGrantEnabled; | |
118 | $ext->save(); | |
119 | ||
120 | $managedItems = [ | |
121 | 'OptionGroup_advanced_search_options_OptionValue_CiviGrant' => [ | |
122 | 'entity' => 'OptionValue', | |
123 | 'values' => [ | |
124 | 'option_group_id:name' => 'advanced_search_options', | |
125 | 'name' => 'CiviGrant', | |
126 | ], | |
127 | ], | |
128 | 'OptionGroup_contact_view_options_OptionValue_CiviGrant' => [ | |
129 | 'entity' => 'OptionValue', | |
130 | 'values' => [ | |
131 | 'option_group_id:name' => 'contact_view_options', | |
132 | 'name' => 'CiviGrant', | |
133 | ], | |
134 | ], | |
135 | 'OptionGroup_mapping_type_OptionValue_Export Grant' => [ | |
136 | 'entity' => 'OptionValue', | |
137 | 'values' => [ | |
138 | 'option_group_id:name' => 'mapping_type', | |
139 | 'name' => 'Export Grant', | |
140 | ], | |
141 | ], | |
142 | 'OptionGroup_grant_status' => [ | |
143 | 'entity' => 'OptionGroup', | |
144 | 'values' => [ | |
145 | 'name' => 'grant_status', | |
146 | ], | |
147 | ], | |
148 | 'OptionGroup_grant_status_OptionValue_Submitted' => [ | |
149 | 'entity' => 'OptionValue', | |
150 | 'values' => [ | |
151 | 'option_group_id:name' => 'grant_status', | |
152 | 'name' => 'Submitted', | |
153 | ], | |
154 | ], | |
155 | 'OptionGroup_grant_status_OptionValue_Eligible' => [ | |
156 | 'entity' => 'OptionValue', | |
157 | 'values' => [ | |
158 | 'option_group_id:name' => 'grant_status', | |
159 | 'name' => 'Eligible', | |
160 | ], | |
161 | ], | |
162 | 'OptionGroup_grant_status_OptionValue_Ineligible' => [ | |
163 | 'entity' => 'OptionValue', | |
164 | 'values' => [ | |
165 | 'option_group_id:name' => 'grant_status', | |
166 | 'name' => 'Ineligible', | |
167 | ], | |
168 | ], | |
169 | 'OptionGroup_grant_status_OptionValue_Paid' => [ | |
170 | 'entity' => 'OptionValue', | |
171 | 'values' => [ | |
172 | 'option_group_id:name' => 'grant_status', | |
173 | 'name' => 'Paid', | |
174 | ], | |
175 | ], | |
176 | 'OptionGroup_grant_status_OptionValue_Awaiting Information' => [ | |
177 | 'entity' => 'OptionValue', | |
178 | 'values' => [ | |
179 | 'option_group_id:name' => 'grant_status', | |
180 | 'name' => 'Awaiting Information', | |
181 | ], | |
182 | ], | |
183 | 'OptionGroup_grant_status_OptionValue_Withdrawn' => [ | |
184 | 'entity' => 'OptionValue', | |
185 | 'values' => [ | |
186 | 'option_group_id:name' => 'grant_status', | |
187 | 'name' => 'Withdrawn', | |
188 | ], | |
189 | ], | |
190 | 'OptionGroup_grant_status_OptionValue_Approved for Payment' => [ | |
191 | 'entity' => 'OptionValue', | |
192 | 'values' => [ | |
193 | 'option_group_id:name' => 'grant_status', | |
194 | 'name' => 'Approved for Payment', | |
195 | ], | |
196 | ], | |
197 | 'OptionGroup_grant_type' => [ | |
198 | 'entity' => 'OptionGroup', | |
199 | 'values' => [ | |
200 | 'name' => 'grant_type', | |
201 | ], | |
202 | ], | |
203 | 'OptionGroup_grant_type_OptionValue_Emergency' => [ | |
204 | 'entity' => 'OptionValue', | |
205 | 'values' => [ | |
206 | 'option_group_id:name' => 'grant_type', | |
207 | 'name' => 'Emergency', | |
208 | ], | |
209 | ], | |
210 | 'OptionGroup_grant_type_OptionValue_Family Support' => [ | |
211 | 'entity' => 'OptionValue', | |
212 | 'values' => [ | |
213 | 'option_group_id:name' => 'grant_type', | |
214 | 'name' => 'Family Support', | |
215 | ], | |
216 | ], | |
217 | 'OptionGroup_grant_type_OptionValue_General Protection' => [ | |
218 | 'entity' => 'OptionValue', | |
219 | 'values' => [ | |
220 | 'option_group_id:name' => 'grant_type', | |
221 | 'name' => 'General Protection', | |
222 | ], | |
223 | ], | |
224 | 'OptionGroup_grant_type_OptionValue_Impunity' => [ | |
225 | 'entity' => 'OptionValue', | |
226 | 'values' => [ | |
227 | 'option_group_id:name' => 'grant_type', | |
228 | 'name' => 'Impunity', | |
229 | ], | |
230 | ], | |
231 | 'OptionGroup_report_template_OptionValue_CRM_Report_Form_Grant_Detail' => [ | |
232 | 'entity' => 'OptionValue', | |
233 | 'values' => [ | |
234 | 'option_group_id:name' => 'report_template', | |
235 | 'name' => 'CRM_Report_Form_Grant_Detail', | |
236 | ], | |
237 | ], | |
238 | 'OptionGroup_report_template_OptionValue_CRM_Report_Form_Grant_Statistics' => [ | |
239 | 'entity' => 'OptionValue', | |
240 | 'values' => [ | |
241 | 'option_group_id:name' => 'report_template', | |
242 | 'name' => 'CRM_Report_Form_Grant_Statistics', | |
243 | ], | |
244 | ], | |
245 | 'Navigation_Grants' => [ | |
246 | 'entity' => 'Navigation', | |
247 | 'values' => [ | |
248 | 'name' => 'Grants', | |
249 | 'domain_id' => 'current_domain', | |
250 | ], | |
251 | ], | |
252 | 'Navigation_Grants_Navigation_Dashboard' => [ | |
253 | 'entity' => 'Navigation', | |
254 | 'values' => [ | |
255 | 'name' => 'Dashboard', | |
256 | 'url' => 'civicrm/grant?reset=1', | |
257 | 'domain_id' => 'current_domain', | |
258 | ], | |
259 | ], | |
260 | 'Navigation_Grants_Navigation_New_Grant' => [ | |
261 | 'entity' => 'Navigation', | |
262 | 'values' => [ | |
263 | 'name' => 'New Grant', | |
264 | 'url' => 'civicrm/grant/add?reset=1&action=add&context=standalone', | |
265 | 'domain_id' => 'current_domain', | |
266 | ], | |
267 | ], | |
268 | 'Navigation_Grants_Navigation_Find_Grants' => [ | |
269 | 'entity' => 'Navigation', | |
270 | 'values' => [ | |
271 | 'name' => 'Find Grants', | |
272 | 'url' => 'civicrm/grant/search?reset=1', | |
273 | 'domain_id' => 'current_domain', | |
274 | ], | |
275 | ], | |
276 | 'Navigation_CiviGrant' => [ | |
277 | 'entity' => 'Navigation', | |
278 | 'values' => [ | |
279 | 'name' => 'CiviGrant', | |
280 | 'domain_id' => 'current_domain', | |
281 | ], | |
282 | ], | |
283 | 'Navigation_CiviGrant_Navigation_Grant_Types' => [ | |
284 | 'entity' => 'Navigation', | |
285 | 'values' => [ | |
286 | 'name' => 'Grant Types', | |
287 | 'domain_id' => 'current_domain', | |
288 | ], | |
289 | ], | |
290 | 'Navigation_CiviGrant_Navigation_Grant_Status' => [ | |
291 | 'entity' => 'Navigation', | |
292 | 'values' => [ | |
293 | 'name' => 'Grant Status', | |
294 | 'domain_id' => 'current_domain', | |
295 | ], | |
296 | ], | |
297 | 'Navigation_Grants_Navigation_Grant_Reports' => [ | |
298 | 'entity' => 'Navigation', | |
299 | 'values' => [ | |
300 | 'name' => 'Grant Reports', | |
301 | 'domain_id' => 'current_domain', | |
302 | ], | |
303 | ], | |
304 | ]; | |
305 | // Create an entry in civicrm_managed for each existing record that will be managed by the extension | |
306 | foreach ($managedItems as $name => $item) { | |
307 | $params = ['checkPermissions' => FALSE]; | |
308 | foreach ($item['values'] as $k => $v) { | |
309 | $params['where'][] = [$k, '=', $v]; | |
310 | } | |
311 | $record = civicrm_api4($item['entity'], 'get', $params)->first(); | |
312 | if ($record) { | |
313 | $mgd = new CRM_Core_DAO_Managed(); | |
314 | $mgd->name = $name; | |
315 | $mgd->module = 'civigrant'; | |
316 | $mgd->entity_type = $item['entity']; | |
317 | if (!$mgd->find(TRUE)) { | |
318 | $mgd->entity_id = $record['id']; | |
319 | $mgd->cleanup = 'unused'; | |
320 | $mgd->save(); | |
321 | } | |
322 | // Disable record if CiviGrant disabled | |
323 | if (!$civiGrantEnabled && !empty($record['is_active'])) { | |
324 | civicrm_api4($item['entity'], 'update', [ | |
325 | 'checkPermissions' => FALSE, | |
326 | 'values' => ['id' => $record['id'], 'is_active' => FALSE], | |
327 | ]); | |
328 | } | |
329 | } | |
330 | } | |
331 | } | |
332 | return TRUE; | |
9ea6ff40 C |
333 | } |
334 | ||
f61cf6ab FW |
335 | /** |
336 | * Set the timezone to the default for existing Events. | |
337 | * | |
338 | * @param \CRM_Queue_TaskContext $ctx | |
339 | * @return bool | |
340 | */ | |
341 | public static function setEventTZDefault(CRM_Queue_TaskContext $ctx) { | |
342 | // Set default for CiviCRM Events to user system timezone (most reasonable default); | |
343 | $defaultTZ = CRM_Core_Config::singleton()->userSystem->getTimeZoneString(); | |
344 | CRM_Core_DAO::executeQuery('UPDATE `civicrm_event` SET `event_tz` = %1 WHERE `event_tz` IS NULL;', [1 => [$defaultTZ, 'String']]); | |
345 | return TRUE; | |
346 | } | |
347 | ||
9ea6ff40 | 348 | } |