Notify users of unmigrated keys when migrating contexts.
[project/context.git] / context.install
1 <?php
2 // $Id$
3
4 /**
5 * Implementation of hook_install().
6 */
7 function context_install() {
8 drupal_install_schema('context');
9 }
10
11 /**
12 * Implementation of hook_uninstall().
13 */
14 function context_uninstall() {
15 drupal_uninstall_schema('context');
16 variable_del('context_ui_show_empty_regions');
17 variable_del('context_reaction_block_disable_core');
18 variable_del('context_reaction_block_all_regions');
19 }
20
21 /**
22 * Implementation of hook_schema().
23 */
24 function context_schema() {
25 $schema = array();
26 $schema['context'] = array(
27 'description' => 'Storage for normal (user-defined) contexts.',
28 'export' => array(
29 'key' => 'name',
30 'identifier' => 'context',
31 'default hook' => 'context_default_contexts', // Function hook name.
32 'status' => 'context_status',
33 'api' => array(
34 'owner' => 'context',
35 'api' => 'context', // Base name for api include files.
36 'minimum_version' => 3,
37 'current_version' => 3,
38 ),
39 'export callback' => 'context_export',
40 ),
41 'fields' => array(
42 'name' => array(
43 'description' => 'The primary identifier for a context.',
44 'type' => 'varchar',
45 'length' => 255,
46 'not null' => TRUE,
47 'default' => '',
48 ),
49 'description' => array(
50 'description' => 'Description for this context.',
51 'type' => 'varchar',
52 'length' => 255,
53 'not null' => TRUE,
54 'default' => '',
55 ),
56 'tag' => array(
57 'description' => 'Tag for this context.',
58 'type' => 'varchar',
59 'length' => 255,
60 'not null' => TRUE,
61 'default' => '',
62 ),
63 'conditions' => array(
64 'description' => 'Serialized storage of all context condition settings.',
65 'type' => 'text',
66 'serialize' => TRUE,
67 ),
68 'reactions' => array(
69 'description' => 'Serialized storage of all context reaction settings.',
70 'type' => 'text',
71 'serialize' => TRUE,
72 ),
73 'condition_mode' => array(
74 'description' => 'Condition mode for this context.',
75 'type' => 'int',
76 'default' => 0,
77 ),
78 ),
79 'primary key' => array('name'),
80 );
81 return $schema;
82 }
83
84 /**
85 * Update script for context that installs the context schema and migrates
86 * any existing context data from deprecated context_ui tables.
87 */
88 function context_update_6001() {
89 $ret = array();
90
91 if (!db_table_exists('context')) {
92 drupal_install_schema('context');
93 }
94
95 if (db_table_exists('context_ui')) {
96 // Clear the schema cache and rebuild
97 drupal_get_schema(NULL, TRUE);
98
99 // Migrate existing contexts to context table
100 $result = db_query("SELECT * FROM {context_ui}");
101 while ($context = db_fetch_object($result)) {
102 // Load setters
103 $setter_result = db_query("SELECT * FROM {context_ui_setter} WHERE cid = %d", $context->cid);
104 while ($row = db_fetch_object($setter_result)) {
105 $context->{$row->type}[$row->id] = $row->id;
106 }
107 // Load getters
108 $getter_result = db_query("SELECT * FROM {context_ui_getter} WHERE cid = %d", $context->cid);
109 while ($row = db_fetch_object($getter_result)) {
110 $context->{$row->type} = unserialize($row->data);
111 }
112 // Load blocks
113 $block_result = db_query("SELECT module, delta, region, weight FROM {context_ui_block} WHERE cid = %d", $context->cid);
114 while ($block = db_fetch_object($block_result)) {
115 if (!isset($context->block)) {
116 $context->block = array();
117 }
118 $block->bid = $block->module ."_". $block->delta;
119 $context->block[$block->bid] = $block;
120 }
121 // Clear out identifier
122 unset($context->cid);
123 context_save_context($context);
124 }
125 }
126
127 module_enable(array('context_contrib'));
128
129 return $ret;
130 }
131
132 /**
133 * Update script for API change in path condition.
134 */
135 function context_update_6002() {
136 define('CONTEXT_STORAGE_DEFAULT', 0);
137 define('CONTEXT_STORAGE_OVERRIDDEN', 1);
138 define('CONTEXT_STORAGE_NORMAL', 2);
139
140 // Iterate through all DB-stored contexts and incorporate path
141 // wildcards into their path conditions. Any exported/default
142 // contexts will need to be updated by hand.
143 $contexts = context_enabled_contexts();
144 foreach ($contexts as $context) {
145 if (($context->type == CONTEXT_STORAGE_NORMAL || $context->type == CONTEXT_STORAGE_OVERRIDDEN) && (!empty($context->path) && is_array($context->path))) {
146 $changed = FALSE;
147 foreach ($context->path as $k => $v) {
148 if ($v != '<front>' && strpos($v, '*') === FALSE) {
149 $changed = TRUE;
150 $context->path[$k] = "{$v}*";
151 }
152 }
153 if ($changed) {
154 context_save_context($context);
155 }
156 }
157 }
158 return array();
159 }
160
161 /**
162 * Remove deprecated tables from context_ui.
163 */
164 function context_update_6003() {
165 $ret = array();
166 $tables = array('context_ui', 'context_ui_setter', 'context_ui_getter', 'context_ui_block');
167 foreach ($tables as $table) {
168 if (db_table_exists($table)) {
169 db_drop_table($ret, $table);
170 }
171 }
172 return $ret;
173 }
174
175 /**
176 * Update 6301: Update schema.
177 */
178 function context_update_6301() {
179 // Install CTools.
180 drupal_install_modules(array('ctools'));
181
182 $schema = array(
183 'fields' => array(
184 'name' => array(
185 'description' => 'The primary identifier for a context.',
186 'type' => 'varchar',
187 'length' => 255,
188 'not null' => TRUE,
189 'default' => '',
190 ),
191 'description' => array(
192 'description' => 'Description for this context.',
193 'type' => 'varchar',
194 'length' => 255,
195 'not null' => TRUE,
196 'default' => '',
197 ),
198 'tag' => array(
199 'description' => 'Tag for this context.',
200 'type' => 'varchar',
201 'length' => 255,
202 'not null' => TRUE,
203 'default' => '',
204 ),
205 'conditions' => array(
206 'description' => 'Serialized storage of all context condition settings.',
207 'type' => 'text',
208 'serialize' => TRUE,
209 ),
210 'reactions' => array(
211 'description' => 'Serialized storage of all context reaction settings.',
212 'type' => 'text',
213 'serialize' => TRUE,
214 ),
215 ),
216 'primary key' => array('name'),
217 );
218 $ret = array();
219 if (db_table_exists('context')) {
220 $result = db_query("SELECT * FROM {context}");
221
222 // Migrate old contexts into new table.
223 $contexts = array();
224 while ($context = db_fetch_object($result)) {
225 $data = unserialize($context->data);
226 unset($context->data);
227 foreach ($data as $k => $v) {
228 $context->{$k} = $v;
229 }
230 $contexts["{$context->namespace}-{$context->attribute}-{$context->value}"] = $context;
231 }
232
233 // Drop the existing context table and create one using the new schema.
234 db_drop_table($ret, 'context');
235 db_create_table($ret, 'context', $schema);
236
237 // Migrate objects.
238 context_migrate_api_3($ret, $contexts);
239 }
240 return $ret;
241 }
242
243 /**
244 * Update 6302: Update old context exportables. This update script may be
245 * re-run at any time to update context 2 objects that have been exported.
246 */
247 function context_update_6302() {
248 $contexts = array();
249 // Invoke context 2 default hooks so that the contexts can be migrated.
250 foreach (module_invoke_all('context_default_contexts') as $context) {
251 $context = (object) $context;
252 if (!isset($context->api_version)) {
253 $contexts["{$context->namespace}-{$context->attribute}-{$context->value}"] = $context;
254 }
255 }
256 // Migrate objects.
257 $ret = array();
258 context_migrate_api_3($ret, $contexts);
259 return $ret;
260 }
261
262 /**
263 * Update 6303: Add field for context condition mode.
264 */
265 function context_update_6303() {
266 $ret = array();
267 $spec = array(
268 'description' => 'Condition mode for this context.',
269 'type' => 'int',
270 'default' => 0,
271 );
272 db_add_field($ret, 'context', 'condition_mode', $spec);
273 return $ret;
274 }
275
276 /**
277 * Update 6304: Rename variable 'context_ui_show_empty_regions'.
278 */
279 function context_update_6304() {
280 if (!db_result(db_query("SELECT name FROM {variable} WHERE name = 'context_reaction_block_all_regions'"))) {
281 db_query("UPDATE {variable} SET name = 'context_reaction_block_all_regions' WHERE name = 'context_ui_show_empty_regions'");
282 return array(array('success' => TRUE, 'query' => 'Variable renamed successfully.'));
283 }
284 return array();
285 }
286
287 /**
288 * Helper function to update context 2 objects to context 3.
289 */
290 function context_migrate_api_3(&$ret, $contexts) {
291 foreach ($contexts as $context) {
292 if (!db_result(db_query("SELECT name FROM {context} WHERE name = '%s'", "{$context->namespace}-{$context->attribute}-{$context->value}"))) {
293 $new = array(
294 'name' => "{$context->namespace}-{$context->attribute}-{$context->value}",
295 'description' => isset($context->description) ? $context->description : '',
296 'tag' => '',
297 'conditions' => array(),
298 'reactions' => array(),
299 );
300 // Migration condition/reaction settings.
301 // Some have been renamed. Map them.
302 $conditions = array(
303 'node' => 'node',
304 'user' => 'user',
305 'book' => 'book',
306 'sitewide' => 'sitewide',
307 'path' => 'path',
308 'menu_trail' => 'menu',
309 'views' => 'views',
310 'nodequeue' => 'nodequeue'
311 );
312 foreach ($conditions as $old_key => $new_key) {
313 if (isset($context->{$old_key})) {
314 $values = $context->{$old_key};
315 $new['conditions'][$new_key] = array(
316 'values' => is_array($values) ? $values : array($values),
317 'options' => array()
318 );
319 }
320 }
321 $reactions = array(
322 'menu' => 'menu',
323 'theme_section' => 'theme',
324 'css_injector' => 'css_injector',
325 'block' => 'block',
326 );
327 foreach ($reactions as $old_key => $new_key) {
328 if (isset($context->{$old_key})) {
329 // Special treatment for blocks.
330 if ($old_key === 'block') {
331 foreach ($context->block as $block) {
332 $block = (array)$block;
333 $new['reactions']['block']['blocks'][$block['module'] .'-'. $block['delta']] = $block;
334 }
335 }
336 else {
337 $new['reactions'][$new_key] = $context->{$old_key};
338 }
339 }
340 }
341 $new['conditions'] = serialize($new['conditions']);
342 $new['reactions'] = serialize($new['reactions']);
343
344 // Update_sql does not escape strings properly.
345 db_query("INSERT INTO {context} (name,description,tag,conditions,reactions) VALUES ('%s', '%s', '%s', '%s', '%s')", $new['name'], $new['description'], $new['tag'], $new['conditions'], $new['reactions']);
346
347 // Notify the user of any keys that were not migrated.
348 $known_keys = array_merge(array_keys($conditions), array_keys($reactions), array('cid', 'system', 'namespace', 'attribute', 'value', 'description'));
349 $unmigrated = array_diff(array_keys((array) $context), $known_keys);
350 if (!empty($unmigrated)) {
351 $unmigrated = implode(', ', $unmigrated);
352 $ret[] = array(
353 'success' => TRUE,
354 'query' => "Updated context: {$new['name']}. The following properties could not be migrated: {$unmigrated}."
355 );
356 }
357 else {
358 $ret[] = array(
359 'success' => TRUE,
360 'query' => "Updated context: {$new['name']}."
361 );
362 }
363 }
364 }
365 }