Add in routine to convert custom date fields in smart groups to datepicker format
[civicrm-core.git] / CRM / Upgrade / Incremental / php / FiveTwenty.php
CommitLineData
187fc9e9
C
1<?php
2/*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License along with this program; if not, contact CiviCRM LLC |
21 | at info[AT]civicrm[DOT]org. If you have questions about the |
22 | GNU Affero General Public License or the licensing of CiviCRM, |
23 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
24 +--------------------------------------------------------------------+
25 */
26
27/**
28 * Upgrade logic for FiveTwenty */
29class CRM_Upgrade_Incremental_php_FiveTwenty extends CRM_Upgrade_Incremental_Base {
30
400db156
D
31 /**
32 * @var $relationshipTypes array
33 * api call result keyed on relationship_type.id
34 */
35 protected static $relationshipTypes;
36
187fc9e9
C
37 /**
38 * Compute any messages which should be displayed beforeupgrade.
39 *
40 * Note: This function is called iteratively for each upcoming
41 * revision to the database.
42 *
43 * @param string $preUpgradeMessage
44 * @param string $rev
45 * a version number, e.g. '4.4.alpha1', '4.4.beta3', '4.4.0'.
46 * @param null $currentVer
47 */
48 public function setPreUpgradeMessage(&$preUpgradeMessage, $rev, $currentVer = NULL) {
49 // Example: Generate a pre-upgrade message.
50 // if ($rev == '5.12.34') {
51 // $preUpgradeMessage .= '<p>' . ts('A new permission, "%1", has been added. This permission is now used to control access to the Manage Tags screen.', array(1 => ts('manage tags'))) . '</p>';
52 // }
81633334
TO
53 if ($rev == '5.20.alpha1') {
54 if (CRM_Core_DAO::checkTableExists('civicrm_persistent') && CRM_Core_DAO::checkTableHasData('civicrm_persistent')) {
55 $preUpgradeMessage .= '<br/>' . ts("WARNING: The table \"<code>civicrm_persistent</code>\" is flagged for removal because all official records show it being unused. However, the upgrader has detected data in this copy of \"<code>civicrm_persistent</code>\". Please <a href='%1' target='_blank'>report</a> anything you can about the usage of this table. In the mean-time, the data will be preserved.", [
56 1 => 'https://civicrm.org/bug-reporting',
57 ]);
58 }
59 }
187fc9e9
C
60 }
61
62 /**
63 * Compute any messages which should be displayed after upgrade.
64 *
65 * @param string $postUpgradeMessage
66 * alterable.
67 * @param string $rev
68 * an intermediate version; note that setPostUpgradeMessage is called repeatedly with different $revs.
69 */
70 public function setPostUpgradeMessage(&$postUpgradeMessage, $rev) {
71 // Example: Generate a post-upgrade message.
72 // if ($rev == '5.12.34') {
73 // $postUpgradeMessage .= '<br /><br />' . ts("By default, CiviCRM now disables the ability to import directly from SQL. To use this feature, you must explicitly grant permission 'import SQL datasource'.");
74 // }
75 }
76
77 /*
78 * Important! All upgrade functions MUST add a 'runSql' task.
79 * Uncomment and use the following template for a new upgrade version
80 * (change the x in the function name):
81 */
82
187fc9e9
C
83 // public static function taskFoo(CRM_Queue_TaskContext $ctx, ...) {
84 // return TRUE;
85 // }
86
6489e3de
SL
87 /**
88 * Upgrade function.
89 *
90 * @param string $rev
91 */
92 public function upgrade_5_20_alpha1($rev) {
93 $this->addTask('Add frontend title column to contribution page table', 'addColumn', 'civicrm_contribution_page',
94 'frontend_title', "varchar(255) DEFAULT NULL COMMENT 'Contribution Page Public title'", TRUE, '5.20.alpha1');
dc396835
AS
95 $this->addTask('Add is_template field to civicrm_contribution', 'addColumn', 'civicrm_contribution', 'is_template',
96 "tinyint(4) DEFAULT '0' COMMENT 'Shows this is a template for recurring contributions.'", FALSE, '5.20.alpha1');
1f34d30a
AS
97 $this->addTask('Add order_reference field to civicrm_financial_trxn', 'addColumn', 'civicrm_financial_trxn', 'order_reference',
98 "varchar(255) COMMENT 'Payment Processor external order reference'", FALSE, '5.20.alpha1');
400db156
D
99 $config = CRM_Core_Config::singleton();
100 if (in_array('CiviCase', $config->enableComponents)) {
101 $this->addTask('Change direction of autoassignees in case type xml', 'changeCaseTypeAutoassignee');
102 }
6489e3de 103 $this->addTask(ts('Upgrade DB to %1: SQL', [1 => $rev]), 'runSql', $rev);
f831ac20 104 $this->addTask('Add "Template" contribution status', 'templateStatus');
7d832c0c
SL
105 $this->addTask('Update smart groups to rename filters on case_from and case_to to case_start_date and case_end_date', 'updateSmartGroups', [
106 'renameField' => [
107 ['old' => 'case_from_relative', 'new' => 'case_start_date_relative'],
108 ['old' => 'case_from_start_date_high', 'new' => 'case_start_date_high'],
109 ['old' => 'case_from_start_date_low', 'new' => 'case_start_date_low'],
110 ['old' => 'case_to_relative', 'new' => 'case_end_date_relative'],
111 ['old' => 'case_to_end_date_high', 'new' => 'case_end_date_high'],
112 ['old' => 'case_to_end_date_low', 'new' => 'case_end_date_low'],
0058ef3f
SL
113 ['old' => 'mailing_date_relative', 'new' => 'mailing_job_start_date_relative'],
114 ['old' => 'mailing_date_high', 'new' => 'mailing_job_start_date_high'],
115 ['old' => 'mailing_date_low', 'new' => 'mailing_job_start_date_low'],
41b8dd1d 116 ['old' => 'relation_start_date_low', 'new' => 'relationship_start_date_low'],
117 ['old' => 'relation_start_date_high', 'new' => 'relationship_start_date_high'],
118 ['old' => 'relation_start_date_relative', 'new' => 'relationship_start_date_relative'],
119 ['old' => 'relation_end_date_low', 'new' => 'relationship_end_date_low'],
120 ['old' => 'relation_end_date_high', 'new' => 'relationship_end_date_high'],
121 ['old' => 'relation_end_date_relative', 'new' => 'relationship_end_date_relative'],
c1436807
SL
122 ['old' => 'event_start_date_low', 'new' => 'event_low'],
123 ['old' => 'event_end_date_high', 'new' => 'event_high'],
7d832c0c
SL
124 ],
125 ]);
70e0d21f
SL
126 $this->addTask('Convert Log date searches to their final names either created date or modified date', 'updateSmartGroups', [
127 'renameLogFields' => [],
128 ]);
7d832c0c
SL
129 $this->addTask('Update smart groups where jcalendar fields have been converted to datepicker', 'updateSmartGroups', [
130 'datepickerConversion' => [
bca2ad39 131 'birth_date',
132 'deceased_date',
7d832c0c
SL
133 'case_start_date',
134 'case_end_date',
0058ef3f 135 'mailing_job_start_date',
41b8dd1d 136 'relationship_start_date',
137 'relationship_end_date',
c1436807
SL
138 'event',
139 'relation_active_period_date',
70e0d21f
SL
140 'created_date',
141 'modified_date',
7d832c0c
SL
142 ],
143 ]);
81633334 144 $this->addTask('Clean up unused table "civicrm_persistent"', 'dropTableIfEmpty', 'civicrm_persistent');
7f054690
SL
145 $this->addTask('Convert Custom data based smart groups from jcalendar to datepicker', 'updateSmartGroups', [
146 'convertCustomSmartGroups' => NULL,
147 ]);
f831ac20
EE
148 }
149
150 public static function templateStatus(CRM_Queue_TaskContext $ctx) {
151 CRM_Core_BAO_OptionValue::ensureOptionValueExists([
152 'option_group_id' => 'contribution_status',
153 'name' => 'Template',
154 'label' => ts('Template'),
155 'is_active' => TRUE,
156 'component_id' => 'CiviContribute',
157 ]);
158 return TRUE;
6489e3de
SL
159 }
160
400db156
D
161 /**
162 * Change direction of activity autoassignees in case type xml for
163 * bidirectional relationship types if they point the other way. This is
164 * mostly a visual issue on the case type edit screen and doesn't affect
165 * normal operation, but could lead to confusion and a future mixup.
166 * (dev/core#1046)
167 * ONLY for ones using database storage - don't want to "fork" case types
168 * that aren't currently forked.
169 *
170 * Earlier iterations of this used the api and array manipulation
171 * and then another iteration used SimpleXML manipulation, but both
172 * suffered from weirdnesses in how conversion back and forth worked.
173 *
174 * Here we use SQL and a regex. The thing we're changing is pretty
175 * well-defined and unique:
176 * <default_assignee_relationship>N_b_a</default_assignee_relationship>
177 *
178 * @return bool
179 */
180 public static function changeCaseTypeAutoassignee() {
181 self::$relationshipTypes = civicrm_api3('RelationshipType', 'get', [
182 'options' => ['limit' => 0],
183 ])['values'];
184
185 // Get all case types definitions that are using db storage
186 $dao = CRM_Core_DAO::executeQuery("SELECT id, definition FROM civicrm_case_type WHERE definition IS NOT NULL AND definition <> ''");
187 while ($dao->fetch()) {
188 self::processCaseTypeAutoassignee($dao->id, $dao->definition);
189 }
190 return TRUE;
191 }
192
193 /**
194 * Process a single case type
195 *
196 * @param $caseTypeId int
197 * @param $definition string
198 * xml string
199 */
200 public static function processCaseTypeAutoassignee($caseTypeId, $definition) {
201 $isDirty = FALSE;
202 // find the autoassignees
203 preg_match_all('/<default_assignee_relationship>(.*?)<\/default_assignee_relationship>/', $definition, $matches);
204 // $matches[1][n] has the text inside the xml tag, e.g. 2_a_b
205 foreach ($matches[1] as $index => $match) {
206 if (empty($match)) {
207 continue;
208 }
209 // parse out existing id and direction
210 list($relationshipTypeId, $direction1) = explode('_', $match);
211 // we only care about ones that are b_a
212 if ($direction1 === 'b') {
213 // we only care about bidirectional
214 if (self::isBidirectionalRelationship($relationshipTypeId)) {
215 // flip it to be a_b
216 // $matches[0][n] has the whole match including the xml tag
217 $definition = str_replace($matches[0][$index], "<default_assignee_relationship>{$relationshipTypeId}_a_b</default_assignee_relationship>", $definition);
218 $isDirty = TRUE;
219 }
220 }
221 }
222
223 if ($isDirty) {
224 $sqlParams = [
225 1 => [$definition, 'String'],
226 2 => [$caseTypeId, 'Integer'],
227 ];
228 CRM_Core_DAO::executeQuery("UPDATE civicrm_case_type SET definition = %1 WHERE id = %2", $sqlParams);
229 //echo "UPDATE civicrm_case_type SET definition = '" . CRM_Core_DAO::escapeString($sqlParams[1][0]) . "' WHERE id = {$sqlParams[2][0]}\n";
230 }
231 }
232
233 /**
234 * Check if this is bidirectional, based on label. In the situation where
235 * we're using this we don't care too much about the edge case where name
236 * might not also be bidirectional.
237 *
238 * @param $relationshipTypeId int
239 *
240 * @return bool
241 */
242 private static function isBidirectionalRelationship($relationshipTypeId) {
243 if (isset(self::$relationshipTypes[$relationshipTypeId])) {
244 if (self::$relationshipTypes[$relationshipTypeId]['label_a_b'] === self::$relationshipTypes[$relationshipTypeId]['label_b_a']) {
245 return TRUE;
246 }
247 }
248 return FALSE;
249 }
250
187fc9e9 251}