2f0af4cc349aa838f867681135782f4588877faa
[project/context.git] / context_ui / context_ui_admin.inc
1 <?php
2 // $Id$
3 /**
4 * Page callback for context_ui admin landing page.
5 */
6 function context_ui_admin() {
7 drupal_add_css(drupal_get_path("module", "context_ui") ."/context_ui.css");
8
9 // rebuild blocks
10 _block_rehash();
11
12 // rebuild default contexts
13 context_ui_rebuild();
14
15 // User defined contexts
16 $output = "<h3>". t('User context definitions') ."</h3>";
17 $contexts = context_ui_tree('ui');
18 if ($contexts) {
19 $output .= theme('context_ui_admin', $contexts);
20 }
21 else {
22 $output .= "<p>". t('Please !add_context to get started.', array('!add_context' => l(t('add a context'), 'admin/build/context/add'))) ."</p>";
23 }
24
25 // Module defined contexts
26 $output .= "<h3>". t('Module context definitions') ."</h3>";
27 $contexts = context_ui_tree('system');
28 if ($contexts) {
29 $output .= theme('context_ui_admin', $contexts);
30 }
31 else {
32 $output .= "<p>". t('There are currently no module defined contexts.') ."</p>";
33 }
34
35 return $output;
36 }
37
38 /**
39 * Generates the omnibus context definition editing form.
40 * Note: submission and validation handlers are in context_ui_admin.inc
41 *
42 * @param $op
43 * The type of form to build. Either "add", "view" or "edit"
44 * @param $cid
45 * The db context identifier - required when $op == "edit"
46 *
47 * @return
48 * A Drupal form array.
49 */
50 function context_ui_form(&$form_state, $op, $cid = NULL, $context = NULL) {
51 drupal_add_css(drupal_get_path("module", "context_ui") ."/context_ui.css");
52 drupal_add_js(drupal_get_path("module", "context_ui") ."/context_ui.js");
53
54 switch ($op) {
55 case 'add':
56 if (is_object($context)) {
57 $context->system = true;
58 if ($exists = context_ui_context('load', $context)) {
59 drupal_set_message(t('A module is already providing a context with this space/key/value identifier. Your context definition will override its settings.'));
60 }
61 $context->system = false;
62 }
63 break;
64 case 'view':
65 if (is_numeric($cid) && $context = context_ui_context('load', $cid)) {
66 drupal_set_title(t('View %title', array('%title' => $context->value)));
67 }
68 else {
69 drupal_goto('admin/build/context'); return;
70 }
71 break;
72 case 'edit':
73 if (is_numeric($cid) && $context = context_ui_context('load', $cid)) {
74 if (!$context->system) {
75 drupal_set_title(t('Edit context: %title', array('%title' => $context->value)));
76 }
77 else {
78 drupal_goto('admin/build/context'); return;
79 }
80 }
81 break;
82 }
83
84 // Core context definition
85 $form['#theme'] = 'context_ui_form';
86 $form['value'] =
87 $form['ckey'] =
88 $form['space'] = array(
89 '#type' => 'textfield',
90 '#required' => true,
91 '#maxlength' => 64,
92 '#size' => 20,
93 );
94
95 $form['value']['#title'] = t('Value');
96 $form['value']['#description'] = t('A system name for this context. May only contain lowercase letters, underscores, and numbers. Example: <b>science_blog</b>');
97
98 $form['ckey']['#title'] = t('Key');
99 $form['ckey']['#default_value'] = 'section';
100 $form['ckey']['#description'] = t('The type of context information provided in this namespace. Example: <b>section</b>');
101
102 $form['space']['#title'] = t('Namespace');
103 $form['space']['#default_value'] = 'context_ui';
104 $form['space']['#description'] = t('The namespace for this context definition. Example: <b>context_ui</b>');
105
106 $form['items'] = array(
107 '#tree' => true,
108 );
109
110 // Generate settings for context item associations
111 foreach (context_ui_types('full') as $type => $item) {
112 if (in_array($item['#type'], array('select', 'radios', 'checkboxes', 'textfield'))) {
113 $form['items'][$type] = $item;
114 }
115 }
116
117 // Control block visibility
118 init_theme(); // we need to initialize theme in order to deal with blocks
119 global $theme_key;
120 $block_options =
121 $block_defaults = array();
122 $blocks = _context_ui_get_blocks();
123 $regions = system_region_list($theme_key);
124 // $blocks in [0] have not been assigned a region
125 foreach ($blocks[0] as $block) {
126 if (!isset($context->block[$block->bid])) {
127 $block_options[$block->module][$block->bid] = $block->label ." ($block->bid)";
128 }
129 }
130 ksort($block_options);
131
132 $form['block'] = array(
133 '#tree' => true,
134 );
135
136 $form['block']['selector'] = array(
137 '#description' => t('Control block visibility using context. Selected blocks will be shown when this context is set provided that custom block visibility settings and/or throttling do not hide them. Grayed out blocks are those provided by Drupal\'s standard block settings. These settings apply to the current theme and any enabled themes with regions in common.'),
138 '#type' => 'item',
139 '#tree' => true,
140 '#prefix' => '<div class="context-ui-block-selector">',
141 '#suffix' => '</div>',
142 'blocks' => array(
143 '#type' => 'select',
144 '#multiple' => true,
145 '#size' => 15,
146 '#title' => t('Blocks'),
147 '#options' => $block_options,
148 ),
149 'regions' => array(
150 '#type' => 'select',
151 '#title' => t('Regions'),
152 '#options' => $regions,
153 ),
154 'add' => array(
155 '#type' => 'markup',
156 '#value' => "<input id='edit-block-selector-add' class='form-submit' type='button' value='+ ". t('Add') ."'/>",
157 ),
158 );
159 $form['block']['regions'] = array(
160 '#type' => 'item',
161 '#tree' => true,
162 '#prefix' => '<div class="context-ui-block-regions">',
163 '#suffix' => '</div>',
164 '#value' => theme('context_ui_block_ui', $regions, $context),
165 );
166 foreach (array_keys($regions) as $region) {
167 $defaults = array();
168 $midpoint = false;
169 foreach (_context_ui_get_blocks($region, $context) as $block) {
170 if ($block->type == 'context_ui') {
171 $defaults[] = $block->bid;
172 }
173 else if (!$midpoint) {
174 $midpoint = true;
175 $defaults[] = 'system';
176 }
177 }
178 if (!$defaults) {
179 $defaults = array('system');
180 }
181 $defaults = implode(',', $defaults);
182 $form['block']['regions'][$region] = array(
183 '#type' => 'hidden',
184 '#default_value' => $defaults,
185 );
186 }
187
188 if ($op == 'view') {
189 $form['back'] = array(
190 '#type' => 'item',
191 '#value' => l(t('Back'), 'admin/build/context'),
192 );
193 }
194
195 if ($op != 'view') {
196 $form['submit'] = array(
197 '#type' => 'submit',
198 '#value' => t('Save'),
199 );
200 }
201
202 if ($op == 'edit') {
203 $form['delete'] = array(
204 '#type' => 'submit',
205 '#value' => t('Delete'),
206 );
207 }
208
209 if ($op == 'view' || $op == 'edit' || ($op == 'add' && $context)) {
210 if ($context) {
211 $form['value']['#default_value'] = $context->value;
212 $form['ckey']['#default_value'] = $context->ckey;
213 $form['space']['#default_value'] = $context->space;
214 $form['cid'] = array(
215 '#type' => 'value',
216 '#value' => $cid,
217 );
218 $form['system'] = array(
219 '#type' => 'value',
220 '#value' => $context->system,
221 );
222 if ($op == 'view' || $context->system) {
223 $form['value']['#disabled'] =
224 $form['ckey']['#disabled'] =
225 $form['space']['#disabled'] =
226 $form['block']['selector']['blocks']['#disabled'] =
227 $form['block']['selector']['regions']['#disabled'] = true;
228 }
229 // Set default values for each item type (except blocks)
230 foreach (context_ui_types('full') as $type => $item) {
231 if (is_array($context->{$type})) {
232 if ($item['#type'] == 'checkboxes' || ($item['#type'] == 'select' && $item['#multiple'] == true)) {
233 $defaults = array();
234 foreach ($context->{$type} as $id) {
235 $defaults[$id] = $id;
236 }
237 }
238 else {
239 $defaults = current($context->{$type});
240 }
241 $form['items'][$type]['#default_value'] = $defaults;
242 }
243 $form['items'][$type]['#disabled'] = $op == 'view' ? true : false;
244 }
245 // Blocks must be selected by region
246 if (is_array($context->block)) {
247 foreach ($regions as $region => $label) {
248 if (isset($form['block'][$region]) && is_array($form['block'][$region])) {
249 $defaults = array();
250 foreach ($form['block'][$region]['#options'] as $block => $label) {
251 if (array_search($block, $context->block) !== false) {
252 $defaults[$block] = $block;
253 }
254 }
255 $form['block'][$region]['#default_value'] = $defaults;
256 }
257 $form['block'][$region]['#disabled'] = $op == 'view' ? true : false;
258 }
259 }
260 }
261 else {
262 return drupal_goto('admin/build/context');
263 }
264 }
265
266 return $form;
267 }
268
269 /**
270 * Theme function for context_ui_form()
271 */
272 function theme_context_ui_form($form) {
273 $output = '';
274
275 // Render space / key / value trio in a 3-column table
276 $header = array(t('Namespace'), t('Key'), t('Value'));
277 unset($form['space']['#title']);
278 unset($form['ckey']['#title']);
279 unset($form['value']['#title']);
280 $rows = array(
281 array(
282 drupal_render($form['space']),
283 drupal_render($form['ckey']),
284 drupal_render($form['value']),
285 ),
286 );
287 $output .= theme('table', $header, $rows, array('class' => 'context-ui-3col'));
288
289 // Render setters / getters as a two column split
290 $header = array(t('Set context'), t('Respond to context'));
291 $setters = $getters = '';
292 foreach (context_ui_types('full') as $type => $item) {
293 if ($item['#context_ui'] == 'getter') {
294 $getters .= drupal_render($form['items'][$type]);
295 }
296 else {
297 $setters .= drupal_render($form['items'][$type]);
298 }
299 }
300 $rows = array(
301 array(
302 array('data' => $setters, 'class' => 'setters left'),
303 array('data' => $getters, 'class' => 'getters right'),
304 ),
305 );
306 $output .= theme('table', $header, $rows, array('class' => 'context-ui-2col'));
307
308 // Block visibility
309 $header = array(t('Blocks'), t('Regions'));
310 $rows = array(
311 array(
312 array('data' => drupal_render($form['block']['selector']), 'class' => 'left'),
313 array('data' => drupal_render($form['block']['regions']), 'class' => 'right'),
314 ),
315 );
316 $output .= theme('table', $header, $rows, array('id' => 'context-ui-blocks', 'class' => 'context-ui-2col'));
317
318 $output .= drupal_render($form);
319 return $output;
320 }
321
322 /**
323 * Provide a form to confirm deletion of a context definition.
324 */
325 function context_ui_delete_confirm(&$form_state, $cid) {
326 $context = context_ui_context('load', $cid);
327 if (!$context) {
328 return drupal_goto('admin/build/context');
329 }
330 $form['cid'] = array('#type' => 'value', '#value' => $cid);
331 $form = confirm_form($form,
332 t('Are you sure you want to delete %title?', array('%title' => $context->value)),
333 'admin/build/context',
334 t('This action cannot be undone.'),
335 t('Delete'), t('Cancel')
336 );
337 return $form;
338 }
339
340 /**
341 * Submit hook for context_ui delete confirmation form.
342 */
343 function context_ui_delete_confirm_submit($form, &$form_state) {
344 context_ui_context('delete', $form_state['values']['cid']);
345 context_ui_rebuild();
346 $form_state['redirect'] = 'admin/build/context';
347 }
348
349 /**
350 * Page callback for import form. Switches form output to context form
351 * if import submission has occurred.
352 */
353 function context_ui_import_page() {
354 if (!empty($_POST) && $_POST['form_id'] == 'context_ui_form') {
355 return drupal_get_form('context_ui_form', 'add');
356 }
357 return drupal_get_form('context_ui_import');
358 }
359
360 /**
361 * Import form. Provides simple helptext instructions and textarea for
362 * pasting a context definition.
363 */
364 function context_ui_import() {
365 drupal_set_title(t('Import context'));
366 $help = t('You can import a context definition by pasting the exported context object code into the field below.');
367 $form = array();
368 $form['help'] = array(
369 '#type' => 'item',
370 '#value' => $help,
371 );
372 $form['import'] = array(
373 '#title' => t('Context Object'),
374 '#type' => 'textarea',
375 '#rows' => 10,
376 '#required' => true,
377 );
378 $form['submit'] = array(
379 '#type' => 'submit',
380 '#value' => t('Import'),
381 );
382
383 return $form;
384 }
385
386 /**
387 * Import form submit handler. Evaluates import code and transfers to
388 * context definition form.
389 */
390 function context_ui_import_submit($form, &$form_state) {
391 $items = array();
392 if ($import = $form_state['values']['import']) {
393 ob_start();
394 eval($import);
395 ob_end_clean();
396 }
397 if (is_array($items) && count($items)) {
398 $context = current($items);
399 }
400 if (is_array($context)) {
401 $context = (object) $context;
402 $context->system = FALSE;
403 if ($exists = context_ui_context('load', $context)) {
404 drupal_set_message(t('A user-defined context definition with this space/key/value identifier already exists. Please remove the existing context before importing this definition.'), 'error');
405 $form_state['redirect'] = 'admin/build/context';
406 }
407 else {
408 drupal_set_title(t('Add context'));
409 $output = drupal_get_form('context_ui_form', 'add', null, (object) $context);
410 print theme('page', $output);
411 exit;
412 }
413 }
414 else {
415 drupal_set_message(t('An error occurred while importing. Please check your context definition.', 'error'));
416 $form_state['redirect'] = 'admin/build/context';
417 }
418 }
419
420 /**
421 * Provides a form with an exported context definition for use in modules.
422 *
423 * @param $cid
424 * A context id.
425 *
426 * @return
427 * A FormAPI array.
428 */
429 function context_ui_export(&$form_state, $cid = NULL) {
430 if (is_numeric($cid) && $context = context_ui_context('load', $cid)) {
431 drupal_set_title(t('Export %title', array('%title' => $context->value)));
432
433 // help text -- too bad the help module in 5 doesn't take wildcards
434 $help = t('You can use exported contexts in your modules by returning an array of defined contexts in <code>hook_context_define()</code>.');
435
436 // prune system specific information and cast for Drupal's AOP (array oriented programming)
437 unset($context->cid);
438 unset($context->status);
439 unset($context->system);
440 $context = (array) $context;
441
442 // clean up blocks
443 foreach ($context['block'] as $bid => $block) {
444 unset($block->bid);
445 $context['block'][$bid] = (array) $block;
446 }
447
448 // export
449 $export = '$items[] = '. var_export($context, true) .';';
450
451 // build the form
452 $form = array();
453 $form['help'] = array(
454 '#type' => 'item',
455 '#value' => $help,
456 );
457 $form['export'] = array(
458 '#type' => 'textarea',
459 '#rows' => 24,
460 '#default_value' => $export,
461 );
462 return $form;
463 }
464 else {
465 drupal_goto('admin/build/context'); return;
466 }
467 }
468
469 /*
470 * Generates an array tree representation of available space/key/value context definitions.
471 */
472 function context_ui_tree($op = '') {
473 static $tree;
474 if (!$tree) {
475 $tree = array(
476 'system' => array(),
477 'ui' => array(),
478 );
479 $result = db_query("
480 SELECT *
481 FROM {context_ui}
482 ORDER BY system ASC, space ASC, ckey ASC, value ASC");
483 while ($context = db_fetch_object($result)) {
484 $branch = $context->system ? 'system' : 'ui';
485 $tree[$branch][$context->space][$context->ckey][$context->value] = $context;
486 }
487 }
488 switch ($op) {
489 case 'ui':
490 return $tree['ui'];
491 case 'system':
492 return $tree['system'];
493 default:
494 return $tree;
495 }
496 }
497
498 /**
499 * Cache system contexts
500 */
501 function context_ui_rebuild() {
502 $default_contexts = context_ui_defaults();
503 $types = context_ui_types();
504
505 // Grab existing user defined contexts
506 $ui = context_ui_tree('ui');
507
508 // Retrieve existing system contexts
509 $system = array();
510 $result = db_query("SELECT * FROM {context_ui} WHERE system = 1");
511 while ($existing = db_fetch_object($result)) {
512 $system[$existing->cid] = true;
513 }
514
515 // Insert or update system contexts
516 foreach ($default_contexts as $c) {
517 // flag this context's type + status
518 $c->system = 1;
519 $c->status = isset($ui[$c->space][$c->ckey][$c->value]) ? 0 : 1;
520
521 if ($context = context_ui_context('load', $c)) {
522 $c->cid = $context->cid;
523 context_ui_context('update', $c);
524 unset($system[$c->cid]); // remove this context from unused list
525 }
526 else {
527 context_ui_context('insert', $c);
528 }
529 }
530
531 // Remove any unused contexts
532 foreach ($system as $c => $dummy) {
533 context_ui_context('delete', $c);
534 }
535 }
536
537 /**
538 * Generates the main context_ui admin page with a tiered context listing.
539 */
540 function theme_context_ui_admin($context_tree) {
541 foreach ($context_tree as $space => $keys) {
542 $rows[] = array(
543 "<span class='context-space'>". $space ."</span>",
544 null
545 );
546 foreach ($keys as $key => $contexts) {
547 if (is_array($contexts)) {
548 $rows[] = array(
549 "<span class='context-key'>". $key ."</span>",
550 null
551 );
552 foreach ($contexts as $value => $context) {
553 $links = array();
554 $class = '';
555 if ($context->system) {
556 $links[] = l(t('View'), "admin/build/context/view/$context->cid");
557 }
558 else {
559 $links[] = l(t('Edit'), 'admin/build/context/edit/'. $context->cid);
560 $links[] = l(t('Export'), "admin/build/context/export/$context->cid");
561 $links[] = l(t('Delete'), 'admin/build/context/delete/'. $context->cid);
562 }
563 if (!$context->status) {
564 $class = 'overridden';
565 $value = "$value (". t('Overridden') .")";
566 }
567 $rows[] = array(
568 "<span class='context-value $class'>". $value ."</span>",
569 implode(' | ', $links),
570 );
571 }
572 }
573 else {
574 $links = array();
575 $class = '';
576 if ($contexts->system) {
577 $links[] = l(t('View'), "admin/build/context/view/$contexts->cid");
578 }
579 else {
580 $links[] = l(t('Edit'), 'admin/build/context/edit/'. $contexts->cid);
581 $links[] = l(t('Delete'), 'admin/build/context/delete/'. $contexts->cid);
582 }
583 if ($contexts->overridden) {
584 $class = 'overridden';
585 $key = "$key (". t('Overridden') .")";
586 }
587 $rows[] = array(
588 "<span class='context-key'>". $key ."</span>",
589 implode(' | ', $links),
590 );
591 }
592 }
593 }
594 return theme('table', array(t('Context'), t('Actions')), $rows, array('class' => 'context-ui'));
595 }
596
597 /**
598 * Generates the AJAX enabled block administration portion of the context_ui admin form.
599 */
600 function theme_context_ui_block_ui($regions, $context = null) {
601 $output = '';
602
603 $tools = "<div class='tools'><span class='up'></span><span class='down'></span><span class='remove'></span></div>";
604 foreach ($regions as $region => $label) {
605 $items = array();
606
607 $system = _context_ui_get_blocks($region);
608 $system_item = array();
609 foreach ($system as $block) {
610 $system_item[] = $block->label ." ($block->bid)";
611 }
612 $system_item = implode("<br/>", $system_item);
613
614 $options = _context_ui_get_blocks($region, $context);
615 $midpoint = false;
616 if ($options) {
617 foreach ($options as $block) {
618 if ($block->type == 'context_ui' && !$context->system) {
619 $items[] = array(
620 'data' => $tools . $block->label ." ($block->bid)",
621 'title' => $block->bid,
622 );
623 }
624 else if ($block->type == 'context_ui' && $context->system) {
625 $items[] = array(
626 'data' => $block->label ." ($block->bid)",
627 'title' => $block->bid,
628 'class' => 'default',
629 );
630 }
631 else if (!$midpoint) {
632 $midpoint = true;
633 $items[] = array(
634 'data' => $system_item,
635 'title' => 'system',
636 'class' => 'disabled',
637 );
638 }
639 }
640 }
641 else if ($system_item) {
642 $items[] = array(
643 'data' => $system_item,
644 'title' => 'system',
645 'class' => 'disabled',
646 );
647 }
648 else {
649 $items[] = array(
650 'data' => '',
651 'class' => 'dummy',
652 );
653 }
654 $output .= theme('item_list', $items, $label, 'ul', array('class' => $region));
655 }
656 return $output;
657 }
658
659 /**
660 * hook_validate()
661 */
662 function context_ui_form_validate($form, &$form_state) {
663 if ($form_state['clicked_button']['#id'] == 'edit-submit' && $form_state['values']['value']) {
664 // Check for string identifier sanity
665 foreach (array('value', 'ckey', 'space') as $elem) {
666 if (!preg_match('!^[a-z0-9_]+$!', $form_state['values'][$elem])) {
667 form_set_error($elem, t('The context !elem can only consist of lowercase letters, underscores, and numbers.', array('!elem' => $elem)));
668 }
669 }
670 if (!isset($form_state['values']['cid'])) {
671 // Check that no other user-defined context definition has taken this identifier already
672 $context = new stdClass();
673 $context->space = $form_state['values']['space'];
674 $context->ckey = $form_state['values']['ckey'];
675 $context->value = $form_state['values']['value'];
676 $context->system = 0;
677 if ($exists = context_ui_context('load', $context)) {
678 form_set_error($form_state['values']['value'], t('A user-defined context with this space/key/value identifier already exists. Please delete the existing definition before creating a new one.'));
679 }
680 }
681 }
682 }
683
684 /**
685 * Produces a context object from submitted form values.
686 *
687 * @param $form
688 * A form array with submitted values
689 *
690 * @return
691 * A context object
692 */
693 function context_ui_form_process($form) {
694 $context = new stdClass();
695
696 // Context space/key/value definition
697 $context->cid = isset($form['cid']) ? $form['cid'] : null;
698 $context->system = isset($form['system']) ? $form['system'] : null;
699 $context->space = $form['space'] ? $form['space'] : null;
700 $context->ckey = $form['ckey'] ? $form['ckey'] : null;
701 $context->value = $form['value'] ? $form['value'] : null;
702 $context->status = 1; // all user defined contexts have status 1
703
704 // Values for most item types
705 $item_types = context_ui_types();
706 foreach ($item_types as $element_id) {
707 if (is_array($form['items'][$element_id])) {
708 foreach ($form['items'][$element_id] as $option => $value) {
709 if ($value) {
710 $context->{$element_id}[] = $option;
711 }
712 }
713 }
714 else if (isset($form['items'][$element_id])) {
715 $context->{$element_id}[] = $form['items'][$element_id];
716 }
717 }
718
719 // Blocks must be done by region
720 $context->block = array();
721 global $theme_key;
722 // Get list of "valid" available blocks
723 $valid = _context_ui_get_blocks();
724 $valid = $valid[0];
725 foreach (system_region_list($theme_key) as $region => $label) {
726 if ($blocks = $form['block']['regions'][$region]) {
727 $blocks = explode(',', $blocks);
728 $midpoint = array_search('system', $blocks);
729 foreach ($blocks as $position => $bid) {
730 if ($bid != 'system') {
731 $block = $valid[$bid];
732 $modifier = $position < $midpoint ? -10 : 10;
733 $block->weight = $position - $midpoint + $modifier;
734 $block->region = $region;
735 $block->type = 'context_ui';
736 $context->block[$block->bid] = $block;
737 }
738 }
739 }
740 }
741 return $context;
742 }
743
744 /**
745 * Submit handler for main context_ui form.
746 */
747 function context_ui_form_submit($form, &$form_state) {
748 switch (t($form_state['values']['op'])) {
749 // Send user to delete confirmation page
750 case 'Delete':
751 $form_state['redirect'] = 'admin/build/context/delete/'. $form_state['values']['cid'];
752 return;
753 // Process form values and save and/or update the context in the db
754 case 'Save':
755 $context = context_ui_form_process($form_state['values']);
756 if (!$context->cid) {
757 $result = context_ui_context('insert', $context);
758 if ($result) {
759 drupal_set_message(t('The context %title was saved successfully.', array('%title' => $context->value)));
760 break;
761 }
762 }
763 else if (context_ui_context('load', $context->cid)) {
764 $result = context_ui_context('update', $context);
765 if ($result) {
766 drupal_set_message(t('The context %title was saved successfully.', array('%title' => $context->value)));
767 break;
768 }
769 }
770 drupal_set_message(t('An error occurred while attempting to save your context information.'), 'error');
771 break;
772 }
773 // rebuild cache
774 context_ui_rebuild();
775 $form_state['redirect'] = 'admin/build/context';
776 }
777
778 /**
779 * Helper function to generate a list of blocks from a specified region. If provided a context object,
780 * will generate a full list of blocks for that region distinguishing between system blocks and
781 * context-provided blocks.
782 *
783 * @param $region
784 * The string identifier for a theme region. e.g. "left"
785 * @param $context
786 * A context object.
787 *
788 * @return
789 * A keyed (by "module_delta" convention) array of blocks.
790 */
791 function _context_ui_get_blocks($region = null, $context = null) {
792 global $theme_key;
793 static $block_info, $valid, $system_blocks;
794 // we don't static cache context blocks
795 $context_blocks = $blocks = array();
796
797 if (!$system_blocks) {
798 // initialize regions
799 foreach (system_region_list($theme_key) as $r => $l) {
800 $system_blocks[$r] = array();
801 }
802 // load blocks from database
803 $result = db_query("SELECT module, delta, weight, region, status FROM {blocks} WHERE theme = '%s' ORDER BY weight, module, delta", $theme_key);
804 while ($block = db_fetch_object($result)) {
805 // load block info
806 $block_info[$block->module] = isset($block_info[$block->module]) ? $block_info[$block->module] : module_invoke($block->module, 'block', 'list');
807 $block->label = $block_info[$block->module][$block->delta]['info'];
808 $block->type = 'system';
809 $block->bid = $block->module .'_'. $block->delta;
810 // add block to region
811 if ($block->region && $block->status) {
812 $system_blocks[$block->region][$block->bid] = $block;
813 }
814 else {
815 $system_blocks[0][$block->bid] = $block;
816 }
817 // mark block as available in DB
818 $valid[$block->module ."_". $block->delta] = true;
819 }
820 }
821
822 // load system blocks into main block array
823 $blocks = $system_blocks;
824
825 // load context blocks if provided
826 if (is_object($context) && is_array($context->block)) {
827 // iterate over context-associated blocks
828 foreach ($context->block as $block) {
829 $block = (object) $block;
830 // check that this is a valid block
831 if ($valid[$block->module ."_". $block->delta]) {
832 // if region has been specified, ensure that block belongs to it
833 if (!$region || (isset($region) && $block->region == $region)) {
834 // load block info
835 $block_info[$block->module] = $block_info[$block->module] ? $block_info[$block->module] : module_invoke($block->module, 'block', 'list');
836 $block->label = $block_info[$block->module][$block->delta]['info'];
837 $block->type = 'context_ui';
838 $block->bid = $block->module .'_'. $block->delta;
839 // add block to region
840 if ($block->region) {
841 $blocks[$block->region][$block->bid] = $block;
842 }
843 else {
844 $blocks[0][$block->bid] = $block;
845 }
846 }
847 }
848 }
849 }
850
851 foreach ($blocks as $r => &$sort_region) {
852 if ($r !== 0) {
853 uasort($sort_region, "_context_ui_block_compare");
854 }
855 }
856
857 return $region ? $blocks[$region] : $blocks;
858 }