dev/core#561 Convert Case date fields on search forms from jcalendar to datepicker
[civicrm-core.git] / CRM / Upgrade / Incremental / php / FiveTwenty.php
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 */
29 class CRM_Upgrade_Incremental_php_FiveTwenty extends CRM_Upgrade_Incremental_Base {
30
31 /**
32 * @var $relationshipTypes array
33 * api call result keyed on relationship_type.id
34 */
35 protected static $relationshipTypes;
36
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 // }
53 }
54
55 /**
56 * Compute any messages which should be displayed after upgrade.
57 *
58 * @param string $postUpgradeMessage
59 * alterable.
60 * @param string $rev
61 * an intermediate version; note that setPostUpgradeMessage is called repeatedly with different $revs.
62 */
63 public function setPostUpgradeMessage(&$postUpgradeMessage, $rev) {
64 // Example: Generate a post-upgrade message.
65 // if ($rev == '5.12.34') {
66 // $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'.");
67 // }
68 }
69
70 /*
71 * Important! All upgrade functions MUST add a 'runSql' task.
72 * Uncomment and use the following template for a new upgrade version
73 * (change the x in the function name):
74 */
75
76 // public static function taskFoo(CRM_Queue_TaskContext $ctx, ...) {
77 // return TRUE;
78 // }
79
80 /**
81 * Upgrade function.
82 *
83 * @param string $rev
84 */
85 public function upgrade_5_20_alpha1($rev) {
86 $this->addTask('Add frontend title column to contribution page table', 'addColumn', 'civicrm_contribution_page',
87 'frontend_title', "varchar(255) DEFAULT NULL COMMENT 'Contribution Page Public title'", TRUE, '5.20.alpha1');
88 $this->addTask('Add is_template field to civicrm_contribution', 'addColumn', 'civicrm_contribution', 'is_template',
89 "tinyint(4) DEFAULT '0' COMMENT 'Shows this is a template for recurring contributions.'", FALSE, '5.20.alpha1');
90 $this->addTask('Add order_reference field to civicrm_financial_trxn', 'addColumn', 'civicrm_financial_trxn', 'order_reference',
91 "varchar(255) COMMENT 'Payment Processor external order reference'", FALSE, '5.20.alpha1');
92 $config = CRM_Core_Config::singleton();
93 if (in_array('CiviCase', $config->enableComponents)) {
94 $this->addTask('Change direction of autoassignees in case type xml', 'changeCaseTypeAutoassignee');
95 }
96 $this->addTask(ts('Upgrade DB to %1: SQL', [1 => $rev]), 'runSql', $rev);
97 $this->addTask('Add "Template" contribution status', 'templateStatus');
98 $this->addTask('Update smart groups to rename filters on case_from and case_to to case_start_date and case_end_date', 'updateSmartGroups', [
99 'renameField' => [
100 ['old' => 'case_from_relative', 'new' => 'case_start_date_relative'],
101 ['old' => 'case_from_start_date_high', 'new' => 'case_start_date_high'],
102 ['old' => 'case_from_start_date_low', 'new' => 'case_start_date_low'],
103 ['old' => 'case_to_relative', 'new' => 'case_end_date_relative'],
104 ['old' => 'case_to_end_date_high', 'new' => 'case_end_date_high'],
105 ['old' => 'case_to_end_date_low', 'new' => 'case_end_date_low'],
106 ],
107 ]);
108 $this->addTask('Update smart groups where jcalendar fields have been converted to datepicker', 'updateSmartGroups', [
109 'datepickerConversion' => [
110 'case_start_date',
111 'case_end_date',
112 ],
113 ]);
114 }
115
116 public static function templateStatus(CRM_Queue_TaskContext $ctx) {
117 CRM_Core_BAO_OptionValue::ensureOptionValueExists([
118 'option_group_id' => 'contribution_status',
119 'name' => 'Template',
120 'label' => ts('Template'),
121 'is_active' => TRUE,
122 'component_id' => 'CiviContribute',
123 ]);
124 return TRUE;
125 }
126
127 /**
128 * Change direction of activity autoassignees in case type xml for
129 * bidirectional relationship types if they point the other way. This is
130 * mostly a visual issue on the case type edit screen and doesn't affect
131 * normal operation, but could lead to confusion and a future mixup.
132 * (dev/core#1046)
133 * ONLY for ones using database storage - don't want to "fork" case types
134 * that aren't currently forked.
135 *
136 * Earlier iterations of this used the api and array manipulation
137 * and then another iteration used SimpleXML manipulation, but both
138 * suffered from weirdnesses in how conversion back and forth worked.
139 *
140 * Here we use SQL and a regex. The thing we're changing is pretty
141 * well-defined and unique:
142 * <default_assignee_relationship>N_b_a</default_assignee_relationship>
143 *
144 * @return bool
145 */
146 public static function changeCaseTypeAutoassignee() {
147 self::$relationshipTypes = civicrm_api3('RelationshipType', 'get', [
148 'options' => ['limit' => 0],
149 ])['values'];
150
151 // Get all case types definitions that are using db storage
152 $dao = CRM_Core_DAO::executeQuery("SELECT id, definition FROM civicrm_case_type WHERE definition IS NOT NULL AND definition <> ''");
153 while ($dao->fetch()) {
154 self::processCaseTypeAutoassignee($dao->id, $dao->definition);
155 }
156 return TRUE;
157 }
158
159 /**
160 * Process a single case type
161 *
162 * @param $caseTypeId int
163 * @param $definition string
164 * xml string
165 */
166 public static function processCaseTypeAutoassignee($caseTypeId, $definition) {
167 $isDirty = FALSE;
168 // find the autoassignees
169 preg_match_all('/<default_assignee_relationship>(.*?)<\/default_assignee_relationship>/', $definition, $matches);
170 // $matches[1][n] has the text inside the xml tag, e.g. 2_a_b
171 foreach ($matches[1] as $index => $match) {
172 if (empty($match)) {
173 continue;
174 }
175 // parse out existing id and direction
176 list($relationshipTypeId, $direction1) = explode('_', $match);
177 // we only care about ones that are b_a
178 if ($direction1 === 'b') {
179 // we only care about bidirectional
180 if (self::isBidirectionalRelationship($relationshipTypeId)) {
181 // flip it to be a_b
182 // $matches[0][n] has the whole match including the xml tag
183 $definition = str_replace($matches[0][$index], "<default_assignee_relationship>{$relationshipTypeId}_a_b</default_assignee_relationship>", $definition);
184 $isDirty = TRUE;
185 }
186 }
187 }
188
189 if ($isDirty) {
190 $sqlParams = [
191 1 => [$definition, 'String'],
192 2 => [$caseTypeId, 'Integer'],
193 ];
194 CRM_Core_DAO::executeQuery("UPDATE civicrm_case_type SET definition = %1 WHERE id = %2", $sqlParams);
195 //echo "UPDATE civicrm_case_type SET definition = '" . CRM_Core_DAO::escapeString($sqlParams[1][0]) . "' WHERE id = {$sqlParams[2][0]}\n";
196 }
197 }
198
199 /**
200 * Check if this is bidirectional, based on label. In the situation where
201 * we're using this we don't care too much about the edge case where name
202 * might not also be bidirectional.
203 *
204 * @param $relationshipTypeId int
205 *
206 * @return bool
207 */
208 private static function isBidirectionalRelationship($relationshipTypeId) {
209 if (isset(self::$relationshipTypes[$relationshipTypeId])) {
210 if (self::$relationshipTypes[$relationshipTypeId]['label_a_b'] === self::$relationshipTypes[$relationshipTypeId]['label_b_a']) {
211 return TRUE;
212 }
213 }
214 return FALSE;
215 }
216
217 }