Enabled upgrader and set the latest changes to it.
[com.zyxware.civiwci.git] / CRM / Wci / Upgrader / Base.php
CommitLineData
60488185
M
1<?php
2
3// AUTO-GENERATED FILE -- Civix may overwrite any changes made to this file
4
5/**
6 * Base class which provides helpers to execute upgrade logic
7 */
8class CRM_Wci_Upgrader_Base {
9
10 /**
11 * @var varies, subclass of htis
12 */
13 static $instance;
14
15 /**
16 * @var CRM_Queue_TaskContext
17 */
18 protected $ctx;
19
20 /**
21 * @var string, eg 'com.example.myextension'
22 */
23 protected $extensionName;
24
25 /**
26 * @var string, full path to the extension's source tree
27 */
28 protected $extensionDir;
29
30 /**
31 * @var array(revisionNumber) sorted numerically
32 */
33 private $revisions;
34
35 /**
36 * Obtain a refernece to the active upgrade handler
37 */
38 static public function instance() {
39 if (! self::$instance) {
40 // FIXME auto-generate
41 self::$instance = new CRM_Wci_Upgrader(
ae48345c 42 'org.civicrm.wci',
60488185
M
43 realpath(__DIR__ .'/../../../')
44 );
45 }
46 return self::$instance;
47 }
48
49 /**
50 * Adapter that lets you add normal (non-static) member functions to the queue.
51 *
52 * Note: Each upgrader instance should only be associated with one
53 * task-context; otherwise, this will be non-reentrant.
54 *
55 * @code
56 * CRM_Wci_Upgrader_Base::_queueAdapter($ctx, 'methodName', 'arg1', 'arg2');
57 * @endcode
58 */
59 static public function _queueAdapter() {
60 $instance = self::instance();
61 $args = func_get_args();
62 $instance->ctx = array_shift($args);
63 $instance->queue = $instance->ctx->queue;
64 $method = array_shift($args);
65 return call_user_func_array(array($instance, $method), $args);
66 }
67
68 public function __construct($extensionName, $extensionDir) {
69 $this->extensionName = $extensionName;
70 $this->extensionDir = $extensionDir;
71 }
72
73 // ******** Task helpers ********
74
75 /**
76 * Run a CustomData file
77 *
78 * @param string $relativePath the CustomData XML file path (relative to this extension's dir)
79 * @return bool
80 */
81 public function executeCustomDataFile($relativePath) {
82 $xml_file = $this->extensionDir . '/' . $relativePath;
83 return $this->executeCustomDataFileByAbsPath($xml_file);
84 }
85
86 /**
87 * Run a CustomData file
88 *
89 * @param string $xml_file the CustomData XML file path (absolute path)
90 * @return bool
91 */
92 protected static function executeCustomDataFileByAbsPath($xml_file) {
93 require_once 'CRM/Utils/Migrate/Import.php';
94 $import = new CRM_Utils_Migrate_Import();
95 $import->run($xml_file);
96 return TRUE;
97 }
98
99 /**
100 * Run a SQL file
101 *
102 * @param string $relativePath the SQL file path (relative to this extension's dir)
103 * @return bool
104 */
105 public function executeSqlFile($relativePath) {
106 CRM_Utils_File::sourceSQLFile(
107 CIVICRM_DSN,
108 $this->extensionDir . '/' . $relativePath
109 );
110 return TRUE;
111 }
112
113 /**
114 * Run one SQL query
115 *
116 * This is just a wrapper for CRM_Core_DAO::executeSql, but it
117 * provides syntatic sugar for queueing several tasks that
118 * run different queries
119 */
120 public function executeSql($query, $params = array()) {
121 // FIXME verify that we raise an exception on error
122 CRM_Core_DAO::executeSql($query, $params);
123 return TRUE;
124 }
125
126 /**
127 * Syntatic sugar for enqueuing a task which calls a function
128 * in this class. The task is weighted so that it is processed
129 * as part of the currently-pending revision.
130 *
131 * After passing the $funcName, you can also pass parameters that will go to
132 * the function. Note that all params must be serializable.
133 */
134 public function addTask($title) {
135 $args = func_get_args();
136 $title = array_shift($args);
137 $task = new CRM_Queue_Task(
138 array(get_class($this), '_queueAdapter'),
139 $args,
140 $title
141 );
142 return $this->queue->createItem($task, array('weight' => -1));
143 }
144
145 // ******** Revision-tracking helpers ********
146
147 /**
148 * Determine if there are any pending revisions
149 *
150 * @return bool
151 */
152 public function hasPendingRevisions() {
153 $revisions = $this->getRevisions();
154 $currentRevision = $this->getCurrentRevision();
155
156 if (empty($revisions)) {
157 return FALSE;
158 }
159 if (empty($currentRevision)) {
160 return TRUE;
161 }
162
163 return ($currentRevision < max($revisions));
164 }
165
166 /**
167 * Add any pending revisions to the queue
168 */
169 public function enqueuePendingRevisions(CRM_Queue_Queue $queue) {
170 $this->queue = $queue;
171
172 $currentRevision = $this->getCurrentRevision();
173 foreach ($this->getRevisions() as $revision) {
174 if ($revision > $currentRevision) {
175 $title = ts('Upgrade %1 to revision %2', array(
176 1 => $this->extensionName,
177 2 => $revision,
178 ));
179
180 // note: don't use addTask() because it sets weight=-1
181
182 $task = new CRM_Queue_Task(
183 array(get_class($this), '_queueAdapter'),
184 array('upgrade_' . $revision),
185 $title
186 );
187 $this->queue->createItem($task);
188
189 $task = new CRM_Queue_Task(
190 array(get_class($this), '_queueAdapter'),
191 array('setCurrentRevision', $revision),
192 $title
193 );
194 $this->queue->createItem($task);
195 }
196 }
197 }
198
199 /**
200 * Get a list of revisions
201 *
202 * @return array(revisionNumbers) sorted numerically
203 */
204 public function getRevisions() {
205 if (! is_array($this->revisions)) {
206 $this->revisions = array();
207
208 $clazz = new ReflectionClass(get_class($this));
209 $methods = $clazz->getMethods();
210 foreach ($methods as $method) {
211 if (preg_match('/^upgrade_(.*)/', $method->name, $matches)) {
212 $this->revisions[] = $matches[1];
213 }
214 }
215 sort($this->revisions, SORT_NUMERIC);
216 }
217
218 return $this->revisions;
219 }
220
221 public function getCurrentRevision() {
222 // return CRM_Core_BAO_Extension::getSchemaVersion($this->extensionName);
223 $key = $this->extensionName . ':version';
224 return CRM_Core_BAO_Setting::getItem('Extension', $key);
225 }
226
227 public function setCurrentRevision($revision) {
228 // We call this during hook_civicrm_install, but the underlying SQL
229 // UPDATE fails because the extension record hasn't been INSERTed yet.
230 // Instead, track revisions in our own namespace.
231 // CRM_Core_BAO_Extension::setSchemaVersion($this->extensionName, $revision);
232
233 $key = $this->extensionName . ':version';
234 CRM_Core_BAO_Setting::setItem($revision, 'Extension', $key);
235 return TRUE;
236 }
237
238 // ******** Hook delegates ********
239
240 public function onInstall() {
241 $files = glob($this->extensionDir . '/sql/*_install.sql');
242 if (is_array($files)) {
243 foreach ($files as $file) {
244 CRM_Utils_File::sourceSQLFile(CIVICRM_DSN, $file);
245 }
246 }
247 $files = glob($this->extensionDir . '/xml/*_install.xml');
248 if (is_array($files)) {
249 foreach ($files as $file) {
250 $this->executeCustomDataFileByAbsPath($file);
251 }
252 }
253 if (is_callable(array($this, 'install'))) {
254 $this->install();
255 }
256 $revisions = $this->getRevisions();
257 if (!empty($revisions)) {
258 $this->setCurrentRevision(max($revisions));
259 }
260 }
261
262 public function onUninstall() {
263 if (is_callable(array($this, 'uninstall'))) {
264 $this->uninstall();
265 }
266 $files = glob($this->extensionDir . '/sql/*_uninstall.sql');
267 if (is_array($files)) {
268 foreach ($files as $file) {
269 CRM_Utils_File::sourceSQLFile(CIVICRM_DSN, $file);
270 }
271 }
272 $this->setCurrentRevision(NULL);
273 }
274
275 public function onEnable() {
276 // stub for possible future use
277 if (is_callable(array($this, 'enable'))) {
278 $this->enable();
279 }
280 }
281
282 public function onDisable() {
283 // stub for possible future use
284 if (is_callable(array($this, 'disable'))) {
285 $this->disable();
286 }
287 }
288
289 public function onUpgrade($op, CRM_Queue_Queue $queue = NULL) {
290 switch($op) {
291 case 'check':
292 return array($this->hasPendingRevisions());
293 case 'enqueue':
294 return $this->enqueuePendingRevisions($queue);
295 default:
296 }
297 }
298}