'admin/build/spaces/features', 'title' => t('Features'), 'description' => t('Page listing spaces features.'), 'callback' => 'spaces_ui_features', 'access' => user_access('administer spaces'), 'type' => MENU_LOCAL_TASK, ); $items[] = array( 'path' => 'admin/build/spaces/features/list', 'title' => t('List'), 'description' => t('Page listing spaces features.'), 'callback' => 'spaces_ui_features', 'access' => user_access('administer spaces'), 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => 0, ); $items[] = array( 'path' => 'admin/build/spaces/features/add', 'title' => t('Add'), 'description' => t('Add a new feature.'), 'callback' => 'drupal_get_form', 'callback arguments' => array('context_ui_form', 'add'), 'access' => user_access('administer spaces'), 'type' => MENU_LOCAL_TASK, 'weight' => 1, ); } return $items; } /** * Implementation of hook_context_define(). */ function spaces_ui_context_define() { $items = array(); $result = db_query('SELECT feature, value FROM {spaces_features_ui}'); while ($row = db_fetch_object($result)) { $c = new StdClass(); $c->namespace = 'spaces'; $c->attribute = 'feature'; $c->value = $row->feature; if ($c = context_ui_context('load', $c)) { $c->spaces = unserialize($row->value); // A small change in context_ui now allows modules to // set system/status explicitly -- not recommended except for // cases like this. $c->system = 0; $c->status = 1; $items[] = (array) $c; } } return $items; } /** * Implementation of hook_form_alter() */ function spaces_ui_form_alter($form_id, &$form) { switch ($form_id) { case 'context_ui_delete_confirm': $cid = $form['cid']['#value']; $context = context_ui_context('load', $cid); if ($context->namespace == 'spaces' && $context->attribute == 'feature') { $form['spaces_feature'] = array( '#type' => 'value', '#value' => $context->value, ); $form['#submit']['spaces_ui_feature_delete'] = array(); $form['#submit'] = array_reverse($form['#submit']); } break; case 'context_ui_form': // Determine whether we should treat this context as a spaces feature if ($form['namespace']['#default_value'] == 'spaces' && $form['attribute']['#default_value'] == 'feature') { $is_feature = TRUE; } else { $is_feature = FALSE; } // Load feature information: first attempt from DB, then fallback // to code definition. if (!empty($form['value']['#default_value'])) { $id = $form['value']['#default_value']; $row = db_fetch_object(db_query('SELECT * FROM {spaces_features_ui} WHERE feature = "%s"', $id)); if ($row) { $feature = unserialize($row->value); } else { $features = spaces_features(); if (isset($features[$id])) { $feature = $features[$id]->spaces; } } } // Add Feature information to context form $form['feature'] = array( '#type' => 'fieldset', '#title' => t('Spaces feature'), '#weight' => -5, '#tree' => true, ); $form['feature']['label'] = array( '#type' => 'textfield', '#title' => t('Label'), '#description' => t('Name of the feature.'), '#required' => true, '#maxlength' => 30, '#default_value' => isset($feature['label']) ? $feature['label'] : '', ); $form['feature']['description'] = array( '#type' => 'textfield', '#title' => t('Description'), '#description' => t('A brief description of the feature.'), '#required' => true, '#default_value' => isset($feature['description']) ? $feature['description'] : '', ); // Space type compatibility $options = array(0 => t('All spaces')); foreach (spaces_types() as $type => $info) { $options[$type] = $info['title']; } $form['feature']['types'] = array( '#type' => 'select', '#title' => t('Compatibility'), '#description' => t('Choose the space type compatible with this feature.'), '#required' => true, '#options' => $options, '#default_value' => isset($feature['types']) ? $feature['types'] : 0, ); // Spaces feature menu $menu_items = isset($feature['menu']) ? array_values($feature['menu']) : array(); $menu_paths = isset($feature['menu']) ? array_keys($feature['menu']) : array(); $form['feature']['menu'] = array( '#tree' => true, '#theme' => 'spaces_ui_feature_form_menu', ); $form['feature']['menu']['help'] = array( '#title' => t('Feature menu'), '#type' => 'item', '#description' => t('Define a menu for this feature. Items will be arranged into a tree based on path. Example: "gallery/browse" will become a child item of "gallery".'), ); for ($i = 0; $i < 10; $i++) { $form['feature']['menu'][$i] = array('#tree' => true); $form['feature']['menu'][$i]['path'] = $form['feature']['menu'][$i]['title'] = array( '#type' => 'textfield', '#size' => 30, ); $form['feature']['menu'][$i]['path']['#default_value'] = isset($menu_paths[$i]) ? $menu_paths[$i] : ''; $form['feature']['menu'][$i]['title']['#default_value'] = isset($menu_items[$i]['title']) ? $menu_items[$i]['title'] : ''; } // Force key and space to be 'feature', 'spaces' so that the spaces module knows what to do. $form['attribute']['#disabled'] = true; $form['attribute']['#default_value'] = 'feature'; $form['namespace']['#disabled'] = true; $form['namespace']['#default_value'] = 'spaces'; $form['#submit']['spaces_ui_feature_form_submit'] = array(); $form['#submit'] = array_reverse($form['#submit']); $form['#redirect'] = 'admin/build/spaces/features'; break; } } /** * Submit handler for spaces context_ui form alterations. */ function spaces_ui_feature_form_submit($form_id, $form_values) { $feature = $form_values['value']; $settings = array(); $settings['label'] = $form_values['feature']['label']; $settings['description'] = $form_values['feature']['description']; // Types if ($form_values['feature']['types'] == 0) { $settings['types'] = array(); } else { $settings['types'] = array($form_values['feature']['types']); } // Menu $settings['menu'] = array(); foreach ($form_values['feature']['menu'] as $item) { if (!empty($item['title']) && !empty($item['path'])) { $settings['menu'][$item['path']] = array( 'title' => $item['title'] ); } } ksort($settings['menu']); db_query('DELETE FROM {spaces_features_ui} WHERE feature = "%s"', $feature); db_query('INSERT INTO {spaces_features_ui} (feature, value) VALUES ("%s", "%s")', $feature, serialize($settings)); } /** * Delete confirmation submit handler that deletes the spaces feature * values. */ function spaces_ui_feature_delete($form_id, $form_values) { $feature = $form_values['spaces_feature']; db_query('DELETE FROM {spaces_features_ui} WHERE feature = "%s"', $feature); } /** * Menu page callback that shows a listing of spaces features. */ function spaces_ui_features() { drupal_set_title(t('Spaces features')); $spaces_types = spaces_types(); $spaces_features = spaces_features(); $output = ''; $rows = array(); foreach ($spaces_features as $id => $feature) { // Load the context object for this feature // @TODO: change context_ui load operation so that it wouldn't // wipe out the spaces extension if loaded. $context = context_ui_context('load', $feature); // Basic information about this feature $label = "". $feature->spaces['label'] .""; $label .= "
". $feature->spaces['description'] ."
"; // Generate action links for this item // @TODO: currently, override contexts also have a "Delete" link -- // it should probably say "Revert". However, there is no easy way // to tell that the context is an override of a code context. This // is probably something that needs to change upstream // (in context_ui). $links = array(); if ($context->system == 0) { $links[] = l(t('Edit'), 'admin/build/context/edit/'. $context->cid); $links[] = l(t('Delete'), 'admin/build/context/delete/'. $context->cid, array(), 'destination=admin/build/spaces/features'); } else { $links[] = l(t('Override'), 'admin/build/context/clone/'. $context->cid); } $links = implode(' | ', $links); // Generate human readable version of spaces types if (isset($feature->spaces['types']) && count($feature->spaces['types'])) { $types = array(); foreach ($feature->spaces['types'] as $type) { $types[] = $spaces_types[$type]['title']; } $types = implode(', ', $types); } else { $types = t('All spaces'); } $rows[] = array($label, $types, $links); } $header = array(t('Feature'), t('Usable for'), t('Actions')); $output .= theme('table', $header, $rows); return $output; } /** * Custom form theming for spaces feature menu. */ function theme_spaces_ui_feature_form_menu($form) { drupal_add_js(drupal_get_path('module', 'spaces_ui') .'/spaces_ui.js'); drupal_add_css(drupal_get_path('module', 'spaces_ui') .'/spaces.css'); // Render help markup first $output = drupal_render($form['help']); // Render menu items in a table $rows = array(); foreach (element_children($form) as $element) { if (is_numeric($element)) { $class = !$form[$element]['title']['#default_value'] ? 'hidden' : ''; $rows[] = array( 'data' => array( drupal_render($form[$element]['title']), drupal_render($form[$element]['path']), l(t('Remove'), $_GET['q'], array('class' => 'spaces-remove-menu')), ), 'class' => $class, ); } } // Add an ajax button $rows[] = array( array( 'data' => l(t('Add menu item'), $_GET['q'], array('class' => 'button spaces-add-menu')), 'colspan' => 3, 'class' => 'actions', ), ); $output .= theme('table', array(t('Title'), t('Path'), ''), $rows, array('class' => 'spaces-admin')); return $output; } ?>