2f0af4cc349aa838f867681135782f4588877faa
4 * Page callback for context_ui admin landing page.
6 function context_ui_admin() {
7 drupal_add_css(drupal_get_path("module", "context_ui") .
"/context_ui.css");
12 // rebuild default contexts
15 // User defined contexts
16 $output = "<h3>".
t('User context definitions') .
"</h3>";
17 $contexts = context_ui_tree('ui');
19 $output .
= theme('context_ui_admin', $contexts);
22 $output .
= "<p>".
t('Please !add_context to get started.', array('!add_context' => l(t('add a context'), 'admin/build/context/add'))) .
"</p>";
25 // Module defined contexts
26 $output .
= "<h3>".
t('Module context definitions') .
"</h3>";
27 $contexts = context_ui_tree('system');
29 $output .
= theme('context_ui_admin', $contexts);
32 $output .
= "<p>".
t('There are currently no module defined contexts.') .
"</p>";
39 * Generates the omnibus context definition editing form.
40 * Note: submission and validation handlers are in context_ui_admin.inc
43 * The type of form to build. Either "add", "view" or "edit"
45 * The db context identifier - required when $op == "edit"
48 * A Drupal form array.
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");
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.'));
61 $context->system = false
;
65 if (is_numeric($cid) && $context = context_ui_context('load', $cid)) {
66 drupal_set_title(t('View %title', array('%title' => $context->value
)));
69 drupal_goto('admin/build/context'); return;
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
)));
78 drupal_goto('admin/build/context'); return;
84 // Core context definition
85 $form['#theme'] = 'context_ui_form';
88 $form['space'] = array(
89 '#type' => 'textfield',
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>');
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>');
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>');
106 $form['items'] = array(
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;
117 // Control block visibility
118 init_theme(); // we need to initialize theme in order to deal with blocks
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)";
130 ksort($block_options);
132 $form['block'] = array(
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.'),
140 '#prefix' => '<div class="context-ui-block-selector">',
141 '#suffix' => '</div>',
146 '#title' => t('Blocks'),
147 '#options' => $block_options,
151 '#title' => t('Regions'),
152 '#options' => $regions,
156 '#value' => "<input id='edit-block-selector-add' class='form-submit' type='button' value='+ ".
t('Add') .
"'/>",
159 $form['block']['regions'] = array(
162 '#prefix' => '<div class="context-ui-block-regions">',
163 '#suffix' => '</div>',
164 '#value' => theme('context_ui_block_ui', $regions, $context),
166 foreach (array_keys($regions) as
$region) {
169 foreach (_context_ui_get_blocks($region, $context) as
$block) {
170 if ($block->type
== 'context_ui') {
171 $defaults[] = $block->bid
;
173 else if (!$midpoint) {
175 $defaults[] = 'system';
179 $defaults = array('system');
181 $defaults = implode(',', $defaults);
182 $form['block']['regions'][$region] = array(
184 '#default_value' => $defaults,
189 $form['back'] = array(
191 '#value' => l(t('Back'), 'admin/build/context'),
196 $form['submit'] = array(
198 '#value' => t('Save'),
203 $form['delete'] = array(
205 '#value' => t('Delete'),
209 if ($op == 'view' || $op == 'edit' || ($op == 'add' && $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(
218 $form['system'] = array(
220 '#value' => $context->system,
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
;
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
)) {
234 foreach ($context->{$type} as
$id) {
235 $defaults[$id] = $id;
239 $defaults = current($context->{$type});
241 $form['items'][$type]['#default_value'] = $defaults;
243 $form['items'][$type]['#disabled'] = $op == 'view' ? true
: false
;
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])) {
250 foreach ($form['block'][$region]['#options'] as
$block => $label) {
251 if (array_search($block, $context->block
) !== false
) {
252 $defaults[$block] = $block;
255 $form['block'][$region]['#default_value'] = $defaults;
257 $form['block'][$region]['#disabled'] = $op == 'view' ? true
: false
;
262 return drupal_goto('admin/build/context');
270 * Theme function for context_ui_form()
272 function theme_context_ui_form($form) {
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']);
282 drupal_render($form['space']),
283 drupal_render($form['ckey']),
284 drupal_render($form['value']),
287 $output .
= theme('table', $header, $rows, array('class' => 'context-ui-3col'));
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]);
297 $setters .
= drupal_render($form['items'][$type]);
302 array('data' => $setters, 'class' => 'setters left'),
303 array('data' => $getters, 'class' => 'getters right'),
306 $output .
= theme('table', $header, $rows, array('class' => 'context-ui-2col'));
309 $header = array(t('Blocks'), t('Regions'));
312 array('data' => drupal_render($form['block']['selector']), 'class' => 'left'),
313 array('data' => drupal_render($form['block']['regions']), 'class' => 'right'),
316 $output .
= theme('table', $header, $rows, array('id' => 'context-ui-blocks', 'class' => 'context-ui-2col'));
318 $output .
= drupal_render($form);
323 * Provide a form to confirm deletion of a context definition.
325 function context_ui_delete_confirm(&$form_state, $cid) {
326 $context = context_ui_context('load', $cid);
328 return drupal_goto('admin/build/context');
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')
341 * Submit hook for context_ui delete confirmation form.
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';
350 * Page callback for import form. Switches form output to context form
351 * if import submission has occurred.
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');
357 return drupal_get_form('context_ui_import');
361 * Import form. Provides simple helptext instructions and textarea for
362 * pasting a context definition.
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.');
368 $form['help'] = array(
372 $form['import'] = array(
373 '#title' => t('Context Object'),
374 '#type' => 'textarea',
378 $form['submit'] = array(
380 '#value' => t('Import'),
387 * Import form submit handler. Evaluates import code and transfers to
388 * context definition form.
390 function context_ui_import_submit($form, &$form_state) {
392 if ($import = $form_state['values']['import']) {
397 if (is_array($items) && count($items)) {
398 $context = current($items);
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';
408 drupal_set_title(t('Add context'));
409 $output = drupal_get_form('context_ui_form', 'add', null
, (object) $context);
410 print theme('page', $output);
415 drupal_set_message(t('An error occurred while importing. Please check your context definition.', 'error'));
416 $form_state['redirect'] = 'admin/build/context';
421 * Provides a form with an exported context definition for use in modules.
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
)));
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>.');
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;
443 foreach ($context['block'] as
$bid => $block) {
445 $context['block'][$bid] = (array) $block;
449 $export = '$items[] = '.
var_export($context, true
) .
';';
453 $form['help'] = array(
457 $form['export'] = array(
458 '#type' => 'textarea',
460 '#default_value' => $export,
465 drupal_goto('admin/build/context'); return;
470 * Generates an array tree representation of available space/key/value context definitions.
472 function context_ui_tree($op = '') {
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;
492 return $tree['system'];
499 * Cache system contexts
501 function context_ui_rebuild() {
502 $default_contexts = context_ui_defaults();
503 $types = context_ui_types();
505 // Grab existing user defined contexts
506 $ui = context_ui_tree('ui');
508 // Retrieve existing system contexts
510 $result = db_query("SELECT * FROM {context_ui} WHERE system = 1");
511 while ($existing = db_fetch_object($result)) {
512 $system[$existing->cid
] = true
;
515 // Insert or update system contexts
516 foreach ($default_contexts as
$c) {
517 // flag this context's type + status
519 $c->status
= isset($ui[$c->space
][$c->ckey
][$c->value
]) ?
0 : 1;
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
527 context_ui_context('insert', $c);
531 // Remove any unused contexts
532 foreach ($system as
$c => $dummy) {
533 context_ui_context('delete', $c);
538 * Generates the main context_ui admin page with a tiered context listing.
540 function theme_context_ui_admin($context_tree) {
541 foreach ($context_tree as
$space => $keys) {
543 "<span class='context-space'>".
$space .
"</span>",
546 foreach ($keys as
$key => $contexts) {
547 if (is_array($contexts)) {
549 "<span class='context-key'>".
$key .
"</span>",
552 foreach ($contexts as
$value => $context) {
555 if ($context->system) {
556 $links[] = l(t('View'), "admin/build/context/view/$context->cid");
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
);
563 if (!$context->status
) {
564 $class = 'overridden';
565 $value = "$value (".
t('Overridden') .
")";
568 "<span class='context-value $class'>".
$value .
"</span>",
569 implode(' | ', $links),
576 if ($contexts->system) {
577 $links[] = l(t('View'), "admin/build/context/view/$contexts->cid");
580 $links[] = l(t('Edit'), 'admin/build/context/edit/'.
$contexts->cid
);
581 $links[] = l(t('Delete'), 'admin/build/context/delete/'.
$contexts->cid
);
583 if ($contexts->overridden
) {
584 $class = 'overridden';
585 $key = "$key (".
t('Overridden') .
")";
588 "<span class='context-key'>".
$key .
"</span>",
589 implode(' | ', $links),
594 return theme('table', array(t('Context'), t('Actions')), $rows, array('class' => 'context-ui'));
598 * Generates the AJAX enabled block administration portion of the context_ui admin form.
600 function theme_context_ui_block_ui($regions, $context = null
) {
603 $tools = "<div class='tools'><span class='up'></span><span class='down'></span><span class='remove'></span></div>";
604 foreach ($regions as
$region => $label) {
607 $system = _context_ui_get_blocks($region);
608 $system_item = array();
609 foreach ($system as
$block) {
610 $system_item[] = $block->label .
" ($block->bid)";
612 $system_item = implode("<br/>", $system_item);
614 $options = _context_ui_get_blocks($region, $context);
617 foreach ($options as
$block) {
618 if ($block->type
== 'context_ui' && !$context->system) {
620 'data' => $tools .
$block->label .
" ($block->bid)",
621 'title' => $block->bid
,
624 else if ($block->type
== 'context_ui' && $context->system) {
626 'data' => $block->label .
" ($block->bid)",
627 'title' => $block->bid
,
628 'class' => 'default',
631 else if (!$midpoint) {
634 'data' => $system_item,
636 'class' => 'disabled',
641 else if ($system_item) {
643 'data' => $system_item,
645 'class' => 'disabled',
654 $output .
= theme('item_list', $items, $label, 'ul', array('class' => $region));
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)));
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.'));
685 * Produces a context object from submitted form values.
688 * A form array with submitted values
693 function context_ui_form_process($form) {
694 $context = new
stdClass();
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
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) {
710 $context->{$element_id}[] = $option;
714 else if (isset($form['items'][$element_id])) {
715 $context->{$element_id}[] = $form['items'][$element_id];
719 // Blocks must be done by region
720 $context->block
= array();
722 // Get list of "valid" available blocks
723 $valid = _context_ui_get_blocks();
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;
745 * Submit handler for main context_ui form.
747 function context_ui_form_submit($form, &$form_state) {
748 switch (t($form_state['values']['op'])) {
749 // Send user to delete confirmation page
751 $form_state['redirect'] = 'admin/build/context/delete/'.
$form_state['values']['cid'];
753 // Process form values and save and/or update the context in the db
755 $context = context_ui_form_process($form_state['values']);
756 if (!$context->cid
) {
757 $result = context_ui_context('insert', $context);
759 drupal_set_message(t('The context %title was saved successfully.', array('%title' => $context->value
)));
763 else if (context_ui_context('load', $context->cid
)) {
764 $result = context_ui_context('update', $context);
766 drupal_set_message(t('The context %title was saved successfully.', array('%title' => $context->value
)));
770 drupal_set_message(t('An error occurred while attempting to save your context information.'), 'error');
774 context_ui_rebuild();
775 $form_state['redirect'] = 'admin/build/context';
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.
784 * The string identifier for a theme region. e.g. "left"
789 * A keyed (by "module_delta" convention) array of blocks.
791 function _context_ui_get_blocks($region = null
, $context = null
) {
793 static
$block_info, $valid, $system_blocks;
794 // we don't static cache context blocks
795 $context_blocks = $blocks = array();
797 if (!$system_blocks) {
798 // initialize regions
799 foreach (system_region_list($theme_key) as
$r => $l) {
800 $system_blocks[$r] = array();
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)) {
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;
815 $system_blocks[0][$block->bid
] = $block;
817 // mark block as available in DB
818 $valid[$block->module .
"_".
$block->delta
] = true
;
822 // load system blocks into main block array
823 $blocks = $system_blocks;
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)) {
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;
844 $blocks[0][$block->bid
] = $block;
851 foreach ($blocks as
$r => &$sort_region) {
853 uasort($sort_region, "_context_ui_block_compare");
857 return $region ?
$blocks[$region] : $blocks;