";
}
return $block;
}
break;
}
}
/**
* Implementation of hook_context_items().
*
* Allows modules to integrate with context_ui and provide their native
* objects as options for setting/getting a context definition. The
* hook should return an array of items keyed on the object "type"
* (e.g. "node", "user", etc.) with key-value pairs corresponding to
* a FormAPI element array with some restrictions and additional info.
*
* '#title': Required. The title of the object / form option.
* '#type': Required. The FormAPI element type to use. Currently only
* 'select', 'checkboxes', 'radio', and 'textfield' are allowed.
* '#description': Optional. Help text to be displayed on the form.
* '#options': Required. A key-value array of options. They key will be
* stored and passed to context_ui_set(), so the integrating module
* should use a unique (within its namespace) / usable identifier.
* '#context_ui': Either 'setter' or 'getter'. Determines where this
* item will appear on the context_ui form.
*/
function context_ui_context_items() {
$items = array();
// Content Types
$nodetypes = array();
foreach (node_get_types() as $type) {
$nodetypes[$type->type] = t($type->name);
}
$items['node'] = array(
'#title' => t('Content Types'),
'#description' => t('Set this context when viewing a node page or using the add/edit form of one of these content types.'),
'#options' => $nodetypes,
'#type' => 'checkboxes',
'#context_ui' => 'setter',
);
// Menu
if (module_exists('menu')) {
// grab menu cache
global $_menu;
$menus = array();
$errors = array();
// build options using root menus
foreach (array_reverse(menu_get_root_menus(), true) as $root_mid => $root_menu) {
// build menu options from children of each root menu
$menu = array();
$options = menu_parent_options(0, $root_mid, 0);
unset($options[key($options)]);
foreach ($options as $mid => $title) {
$item = menu_get_item($mid);
$path = $item['path'];
// If path is unique, enter into options
if (!isset($menu[$path])) {
$menu[$path] = $title;
}
// If duplicate, add to error erray
else {
$errors[] = t('!item at !path', array('!item' => str_replace('-', '', $menu[$path]), '!path' => $path));
$errors[] = t('!item at !path', array('!item' => str_replace('-', '', $title), '!path' => $path));
}
}
$path = $_menu['items'][$root_mid]['path'];
$menus[$root_mid] = "". $root_menu ."";
$menus = $menus + $menu;
}
$items['menu'] = array(
'#title' => t('Menus'),
'#description' => t('Display the selected menu item as active when this context is set.'),
'#options' => $menus,
'#type' => 'radios',
'#context_ui' => 'getter',
);
if (count($errors)) {
$items['menu']['#description'] .= '
'. t('Note: context_ui will not work properly with menu items that share the same path. You can work around this issue by pointing custom menu items at !alias. The following duplicates were found:', array('!alias' => l(t('path aliases'), 'admin/build/path'))) .'
';
$items['menu']['#description'] .= theme('item_list', $errors);
}
}
// User
$items['user'] = array(
'#title' => t('User Pages'),
'#description' => t('Set this context when a user with selected role(s) is viewed'),
'#options' => user_roles(true),
'#type' => 'checkboxes',
'#context_ui' => 'setter',
);
// Book
if (module_exists('book')) {
$result = db_query("SELECT b.nid, nr.title FROM {book} b JOIN {node} n ON n.nid = b.nid AND n.vid = b.vid JOIN {node_revisions} nr ON nr.vid = n.vid WHERE n.status = 1 AND b.parent = 0");
$options = array();
while ($book = db_fetch_object($result)) {
$options[$book->nid] = $book->title;
}
$items['book'] = array(
'#title' => t('Book'),
'#description' => t('Set this context when a node in the selected book is viewed.'),
'#options' => $options,
'#type' => 'checkboxes',
'#context_ui' => 'setter',
);
}
return $items;
}
/**
* Implementation of hook_menu().
*/
function context_ui_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array(
'path' => 'admin/build/context',
'callback' => 'context_ui_admin',
'access' => user_access('administer site configuration'),
'type' => MENU_NORMAL_ITEM,
'title' => t('Context'),
'description' => t('Associate menus, views, blocks, etc. with different contexts to structure your site.')
);
$items[] = array(
'path' => 'admin/build/context/list',
'title' => t('List'),
'callback' => 'context_ui_admin',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => 0,
);
$items[] = array(
'path' => 'admin/build/context/add',
'callback' => 'drupal_get_form',
'callback arguments' => array('context_ui_form', 'add'),
'access' => user_access('administer site configuration'),
'type' => MENU_LOCAL_TASK,
'title' => t('Add Context'),
'description' => t('Add a context to your site.'),
'weight' => 1,
);
$items[] = array(
'title' => t('Import'),
'path' => 'admin/build/context/import',
'callback' => 'context_ui_import_page',
'access' => user_access('administer site configuration'),
'type' => MENU_LOCAL_TASK,
'description' => t('Import a context definition into your site.'),
'weight' => 2,
);
$items[] = array(
'path' => 'admin/build/context/edit',
'callback' => 'drupal_get_form',
'callback arguments' => array('context_ui_form', 'edit'),
'access' => user_access('administer site configuration'),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'admin/build/context/clone',
'callback' => 'drupal_get_form',
'callback arguments' => array('context_ui_form', 'clone'),
'access' => user_access('administer site configuration'),
'type' => MENU_CALLBACK,
'title' => t('Clone Context'),
'description' => t('Duplicate an existing context.'),
'weight' => 1,
);
$items[] = array(
'path' => 'admin/build/context/view',
'callback' => 'drupal_get_form',
'callback arguments' => array('context_ui_form', 'view'),
'access' => user_access('administer site configuration'),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'admin/build/context/export',
'callback' => 'drupal_get_form',
'callback arguments' => array('context_ui_export'),
'access' => user_access('administer site configuration'),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'admin/build/context/delete',
'callback' => 'drupal_get_form',
'callback arguments' => array('context_ui_delete_confirm'),
'access' => user_access('administer site configuration'),
'type' => MENU_CALLBACK,
);
return $items;
}
else {
// Include admin functions
if (arg(0) .'/'. arg(1) .'/'. arg(2) == 'admin/build/context') {
include_once(drupal_get_path("module", "context_ui") ."/context_ui_admin.inc");
}
// Rebuild context_ui "cache" when hitting the modules page
else if ($_GET['q'] == 'admin/build/modules') {
include_once(drupal_get_path("module", "context_ui") ."/context_ui_admin.inc");
context_ui_rebuild();
}
}
}
/**
* Implementation of hook_help().
*/
function context_ui_help($section) {
switch ($section) {
case 'admin/build/context':
return "
".
t('Contexts provide you with a way to organize your site using terms familiar to real human beings. You can create a set of sections like "News", "Projects", "Staff", and associate different technical aspects of Drupal to each section. For example, the "News" section may be a collection of Nodes, Views, Menus and Blocks.')
."
";
break;
}
}
/**
* Implementation of hook_nodeapi().
*/
function context_ui_nodeapi(&$node, $op, $teaser, $page) {
if ($op == 'view' && $page && arg(0) == 'node') {
// Implementation of context_ui_set for node.
context_ui_set('node', $node->type);
// Implementation of context_ui_set for book.
if (module_exists('book') && isset($node->parent)) {
// @TODO this non-strict check makes me very nervous...
if ($node->parent == 0) {
context_ui_set('book', $node->nid);
}
else {
$location = book_location($node);
if ($location[0]->parent == 0) {
context_ui_set('book', $location[0]->nid);
}
}
}
}
}
/**
* Implementation of hook_form_alter().
*/
function context_ui_form_alter($form_id, &$form) {
if ($form['#node'] && arg(0) != 'admin') { // Prevent this from firing on admin pages... damn form driven apis...
context_ui_set('node', $form['#node']->type);
}
else if ($form_id == 'comment_form' && $nid = $form['nid']['#value']) {
$node = node_load($nid);
context_ui_set('node', $node->type);
}
else if ($form_id == 'block_admin_configure') {
// Display context_ui visibility information on block configuration pages
$module = $form['module']['#value'];
$delta = $form['delta']['#value'];
$result = db_query("SELECT cb.cid, cb.region, c.namespace, c.attribute, c.value FROM {context_ui_block} cb JOIN {context_ui} c ON cb.cid = c.cid WHERE cb.module = '%s' AND cb.delta = '%s' AND c.status = %d", $module, $delta, 1);
$rows = array();
while ($row = db_fetch_object($result)) {
$rows[] = array($row->namespace, $row->attribute, $row->value, $row->region, l(t('Edit visibility'), 'admin/build/context/edit/'. $row->cid, array(), null, 'context-ui-blocks'));
}
if ($rows) {
$content = theme('table', array(t('Namespace'), t('Attribute'), t('Value'), t('Region'), ''), $rows);
}
else {
$content = "
". t('No visibility rules have been set for this block using context_ui.') ."
";
}
$form['context_ui'] = array(
'#type' => 'fieldset',
'#title' => t('Context UI visibility'),
'#weight' => -1,
'#collapsible' => true,
);
$form['context_ui']['contexts'] = array(
'#type' => 'item',
'#value' => $content,
'#description' => t('To add or remove block visibility rules based on context, use the !context_admin.', array('!context_admin' => l(t('context administration page'), 'admin/build/context'))),
);
$form['block_settings']['#weight'] = -5;
}
}
/**
* Implementation of hook_user().
*/
function context_ui_user($op, &$edit, &$account, $category = NULL) {
if ($op == 'view') {
context_ui_set('user', array_keys($account->roles));
}
}
/**
* Invokes hook_context_define() to collect all contexts provided in code by modules.
*
* @param $space
* An optional string namespace identifier. If provided, only context definitions with the
* specified namespace will be returned.
*
* @return
* An array of context objects.
*/
function context_ui_defaults($namespace = null) {
static $contexts, $namespaces;
if (!$contexts) {
$contexts = array();
foreach (module_implements('context_define') as $module) {
$function = $module .'_context_define';
$contexts = array_merge($contexts, $function());
}
foreach ($contexts as $key => $context) {
$context = (object) $context;
$contexts[$key] = $context;
$namespaces[$context->namespace][] = $context;
}
}
if ($namespace) {
if (isset($namespaces[$namespace])) {
return $namespaces[$namespace];
}
else {
return array();
}
}
return $contexts;
}
/**
* Invokes hook_context_items() to provides an array of item types that a context may be associated with.
*/
function context_ui_types($op = 'list') {
static $types;
if (!$types) {
$types = array();
foreach (module_implements('context_items') as $module) {
$function = $module .'_context_items';
$types = array_merge($types, $function());
}
}
switch ($op) {
case 'list':
return array_keys($types);
break;
case 'full':
return $types;
break;
}
}
/**
* Sets a namespace-attribute-value context that has been associated with the provided item.
*
* @param $type
* The item type to be matched. Any of the currently supported context items types ("view",
* "node", etc.) can be specified.
* @param $id
* An array of string or integer ids of the context item to match. Individual ids are also accepted.
*
* @return
* True if one or more contexts were set. False if no items/contexts matched.
*/
function context_ui_set($type, $id) {
if (!is_array($id)) {
$id = array($id);
}
$set = false;
$result = db_query("
SELECT c.namespace, c.attribute, c.value, c.cid FROM {context_ui_item} ci
JOIN {context_ui} c ON ci.cid = c.cid
WHERE ci.type = '%s' AND ci.id IN (". substr(str_repeat("'%s',", count($id)), 0, -1) .") AND c.status = 1",
array_merge(array($type), $id));
while ($context = db_fetch_object($result)) {
// If this context already has a value, don't alter it.
if (!context_isset($context->namespace, $context->attribute)) {
context_set($context->namespace, $context->attribute, $context->value);
// Allow getters to respond to the set context
$context = context_ui_context('load', $context);
module_invoke_all('context_getter', $context);
// Store the cid of set contexts. Other parts of the stack may be interested.
$cid = context_get('context_ui', 'cid');
$cid = $cid ? $cid : array();
$cid[] = $context->cid;
context_set('context_ui', 'cid', $cid);
$set = true;
}
}
return $set;
}
/**
* Implementation of hook_context_getter().
*/
function context_ui_context_getter($context) {
// Set active menu context
context_ui_menu_set_location($context);
}
/**
* Takes a retrieved context array and returns a themed out tree representation of that context.
*/
function theme_context_devel($context) {
drupal_add_css(drupal_get_path("module", "context_ui") ."/context_ui.css");
$output = '';
foreach ($context as $space => $a) {
$output .= "
$space
";
$output .= "
". theme_context_devel_recurse($a) ."
";
}
return $output;
}
/**
* Helper function to theme_context_devel that recurses down context arrays and themes accordingly.
*/
function theme_context_devel_recurse($value) {
$output = '';
if (is_array($value) || is_object($value)) {
if (is_array($value)) {
$type = 'array';
}
else if (is_object($value)) {
$type = 'object';
}
foreach ((array)$value as $key => $a) {
$output .= "
". theme('context_devel_recurse', $a) ."
";
}
}
else {
if (is_string($value)) {
$type = 'string';
}
else if (is_int($value)) {
$type = 'int';
}
else if (is_bool($value)) {
$type = 'bool';
}
$output .= "";
}
return $output;
}
/**
* Alters the menu to reflect any active contexts. Called from context_ui_set().
*/
function context_ui_menu_set_location($context) {
if ($context->cid) {
$result = db_query("
SELECT ci.id
FROM {context_ui_item} ci
WHERE ci.type = '%s' AND ci.cid = %d",
'menu', $context->cid);
if ($path = db_result($result)) {
// Load global menu -- unfortunately we may have to modify it manually
global $_menu;
// Get menu item for active context
$context_menu = menu_get_item(null, $path);
$items[] = $context_menu;
// Grab the menu tree from active context item to the root
$mid = $context_menu['pid'];
while ($mid && ($item = menu_get_item($mid))) {
$items[] = $item;
$mid = $item['pid'];
}
$items = array_reverse($items);
// Graft the current active page on if it is different
$active_mid = menu_get_active_item();
if ($active_mid != $_menu['path index'][$path] && !$items[$active_mid]) {
$active_menu = menu_get_item($active_mid);
// Due to a bug/feature? of menu_set_location() menu leaves that
// are part of the 'visible' portion of the menu tree short-circuit
// any further menu grafting. We check here, and make sure the leaf
// item is not a visible one.
if (isset($_menu['visible'][$active_mid])) {
unset($_menu['visible'][$active_mid]);
}
// If the active menu item is a local task we need to make sure
// to include it's parent.
if ($active_menu['type'] & MENU_IS_LOCAL_TASK) {
$parent_menu = menu_get_item($active_menu['pid']);
$items[] = $parent_menu;
// Allow for two levels of local tasks.
if ($parent_menu['type'] & MENU_IS_LOCAL_TASK) {
$items[] = menu_get_item($parent_menu['pid']);
}
}
if (($active_menu['type'] & MENU_IS_LOCAL_TASK & MENU_LINKS_TO_PARENT)) {
$real_q = end($items);
$real_q = $real_q['path'];
}
$items[] = $active_menu;
}
// Push the new location path through
menu_set_location($items);
// Repair query string
if ($real_q) {
$_GET['q'] = $real_q;
}
}
}
}
/**
* In order to add blocks we need to intercept theme_blocks and build the block
* content using an diffrent process. The current implementation assumes that
* the theme layer isn't going to define either 'phptemplate_blocks' or
* 'themename_blocks'.
*/
function phptemplate_blocks($region) {
$output = "";
if ($list = context_ui_block_list($region)) {
foreach ($list as $key => $block) {
$output .= theme("block", $block);
}
}
// Add any content assigned to this region through drupal_set_content() calls.
$output .= drupal_get_content($region);
return $output;
}
/**
* An alternative version of block_list() that provides any context_ui enabled blocks.
*/
function context_ui_block_list($region) {
global $user, $theme_key;
static $cids = array();
static $blocks = array();
$defaults = array();
if (!count($blocks)) {
// generate list of active DB contexts
// formerly an API function -- TODO: evaluate whether this may be useful otherwise
$result = db_query("SELECT * FROM {context_ui} WHERE status = 1", 'context_ui');
while ($context = db_fetch_object($result)) {
if (context_get($context->namespace, $context->attribute) == $context->value) {
$cids[$context->cid] = $context->cid;
}
}
$rids = array_keys($user->roles);
$placeholders = implode(',', array_fill(0, count($rids), '%d'));
$result = db_query("
SELECT DISTINCT b.*, c.weight AS context_weight, c.region AS context_region, c.cid
FROM {blocks} b
LEFT JOIN {blocks_roles} r ON b.module = r.module AND b.delta = r.delta
LEFT JOIN {context_ui_block} c ON b.module = c.module AND b.delta = c.delta
WHERE b.theme = '%s' AND (r.rid IN ($placeholders) OR r.rid IS NULL)
ORDER BY b.region, b.weight, b.module",
array_merge(array($theme_key), $rids)
);
while ($block = db_fetch_object($result)) {
// we determine status as a combination of DB setting + context definition
$status = FALSE;
// prepare context blocks
// if cid is in active contexts, use context weight + region
if (isset($block->cid) && in_array($block->cid, $cids)) {
$block->context_ui = TRUE;
$block->region = $block->context_region ? $block->context_region : $block->region;
$block->weight = $block->context_weight ? $block->context_weight : $block->weight;
$status = TRUE;
}
// use db setting
else {
$status = $block->status;
}
if ($status) {
if (!isset($blocks[$block->region])) {
$blocks[$block->region] = array();
}
$enabled = _context_ui_block_visibility('user', $block);
$page_match = _context_ui_block_visibility('page', $block);
$throttle = _context_ui_block_visibility('throttle', $block);
if ($enabled && $page_match && $throttle) {
// Invoke hook_block('view');
$array = module_invoke($block->module, 'block', 'view', $block->delta);
if (isset($array) && is_array($array) && $array['content'] && !empty($array['content'])) {
foreach ($array as $k => $v) {
$block->$k = $v;
}
// Override default block title if a custom display title is present.
if ($block->title) {
// Check plain here to allow module generated titles to keep any markup.
$block->subject = $block->title == '' ? '' : check_plain($block->title);
}
$blocks[$block->region]["{$block->module}_{$block->delta}"] = $block;
}
}
}
}
// Custom sort since SQL order by won't give it to us for free
foreach ($blocks as $key => $region_blocks) {
uasort($region_blocks, '_context_ui_block_compare');
$blocks[$key] = $region_blocks;
}
}
// Create an empty array if there were no entries
if (!isset($blocks[$region])) {
$blocks[$region] = array();
}
return $blocks[$region];
}
function _context_ui_block_visibility($op, $block) {
switch ($op) {
case 'user':
global $user;
// Use the user's block visibility setting, if necessary
if ($block->custom != 0) {
if ($user->uid && isset($user->block[$block->module][$block->delta])) {
return $user->block[$block->module][$block->delta];
}
else {
return ($block->custom == 1);
}
}
return true;
case 'page':
// Match path if necessary
if ($block->pages) {
if ($block->visibility < 2) {
$path = drupal_get_path_alias($_GET['q']);
$regexp = '/^('. preg_replace(array('/(\r\n?|\n)/', '/\\\\\*/', '/(^|\|)\\\\($|\|)/'), array('|', '.*', '\1'. preg_quote(variable_get('site_frontpage', 'node'), '/') .'\2'), preg_quote($block->pages, '/')) .')$/';
// Compare with the internal and path alias (if any).
$page_match = preg_match($regexp, $path);
if ($path != $_GET['q']) {
$page_match = $page_match || preg_match($regexp, $_GET['q']);
}
// When $block->visibility has a value of 0, the block is displayed on
// all pages except those listed in $block->pages. When set to 1, it
// is displayed only on those pages listed in $block->pages.
return !($block->visibility xor $page_match);
}
else {
return drupal_eval($block->pages);
}
}
return true;
case 'throttle':
if (!($block->throttle && (module_invoke('throttle', 'status') > 0))) {
return true;
}
return false;
}
}
/**
* Helper function to sort block objects by weight
*/
function _context_ui_block_compare($a, $b) {
// Enabled blocks
return ($a->weight - $b->weight);
}
/**
* Provides simple operations (load/insert/update/etc.) on a core context space/key/value definition.
*
* @param $op
* Operation to perform on a context. May be one of load/insert/update/delete.
* @param $context
* A context object. Optionally, can be an integer cid for the "load" operation.
*
* @return
* If loading, returns a full context item. All other operations return true on success and false on failure.
*/
function context_ui_context($op, $context) {
switch ($op) {
case 'load':
static $cache = array();
// Argument is a cid
if (is_numeric($context)) {
if (!isset($cache[$context])) {
$context = db_fetch_object(db_query("SELECT * FROM {context_ui} WHERE cid = %d", $context));
}
else {
return $cache[$context];
}
}
// Context object has an associated cid
else if (is_object($context) && isset($context->cid)) {
if (!$cache[$context->cid]) {
$context = db_fetch_object(db_query("SELECT * FROM {context_ui} WHERE cid = %d", $context->cid));
}
else {
return $cache[$context->cid];
}
}
// Context object has no cid -- we'll try to load by ns/attr/val
else if (is_object($context) && $context->namespace && $context->attribute && $context->value) {
$args = array(
$context->namespace,
$context->attribute,
$context->value,
);
$system = '';
$status = '';
if (isset($context->system)) {
$args[] = $context->system;
$system = "AND system = '%s'";
}
if (isset($context->status)) {
$args[] = $context->status;
$status = "AND status = %d";
}
$context = db_fetch_object(db_query("SELECT * FROM {context_ui} WHERE namespace = '%s' AND attribute = '%s' AND value = '%s' $system $status", $args));
}
if ($context) {
$context = context_ui_item('load', $context);
$context = context_ui_item_block('load', $context);
// After all that hard work, cache the context
$cache[$context->cid] = $context;
return $context;
}
return false;
case 'insert':
// check for type & existence of context definition
$existing = context_ui_context('load', $context);
if (!$existing || $existing->system != $context->system) {
$context->cid = db_next_id('{context_ui}_cid');
$values = array(
'cid' => $context->cid,
'system' => $context->system,
'status' => $context->status,
'namespace' => $context->namespace,
'attribute' => $context->attribute,
'value' => $context->value,
);
$keys = implode(', ', array_keys($values));
$args = array_merge(array($keys), $values);
$result = db_query("INSERT INTO {context_ui} (%s) VALUES(%d, %d, %d, '%s', '%s', '%s')", $args);
$result = $result && context_ui_item('save', $context);
$result = $result && context_ui_item_block('save', $context);
return $result ? true : false;
}
return false;
break;
case 'update':
if ($context->cid) {
// update core context information
$values = array(
'system' => $context->system,
'status' => $context->status,
'namespace' => $context->namespace,
'attribute' => $context->attribute,
'value' => $context->value,
'cid' => $context->cid,
);
$result = db_query("UPDATE {context_ui} SET system = %d, status = %d, namespace = '%s', attribute = '%s', value = '%s'WHERE cid = %d", $values);
$result = $result && context_ui_item('save', $context);
$result = $result && context_ui_item_block('save', $context);
return $result ? true : false;
}
break;
case 'delete':
if ($context = context_ui_context('load', $context)) {
db_query("DELETE FROM {context_ui} WHERE cid = %d", $context->cid);
db_query("DELETE FROM {context_ui_item} WHERE cid = %d", $context->cid);
db_query("DELETE FROM {context_ui_block} WHERE cid = %d", $context->cid);
return true;
}
return false;
}
}
/**
* Provides simple operations (load/save) on any context-item associations. context_ui_item() will
* automatically sync the database with the context object provided when saving. Any associations
* that exist on the object that are absent from the database will be inserted, and any associations
* that are missing will be removed from the database.
*
* @param $op
* Operation to perform on a context. May be either load or save.
* @param $context
* A context object with item associations.
*
* @return
* Load returns a context object with item associations. Save returns true on success and false on failure.
*/
function context_ui_item($op = 'load', $context) {
if ($context->cid) {
switch ($op) {
case 'load':
$result = db_query("SELECT * FROM {context_ui_item} WHERE cid = %d", $context->cid);
while ($row = db_fetch_object($result)) {
$context->{$row->type}[$row->id] = $row->id;
}
return $context;
case 'save':
$current = new stdClass();
$current->cid = $context->cid;
$current = context_ui_item('load', $current);
foreach (context_ui_types() as $type) {
// Delete any stale associations
if (isset($current->{$type}) && is_array($current->{$type})) {
foreach ($current->{$type} as $id) {
$delete = false;
if (!is_array($context->{$type})) {
$delete = true;
}
else if (array_search($id, $context->{$type}) === false) {
$delete = true;
}
if ($delete) {
$result = db_query("DELETE FROM {context_ui_item} WHERE cid = %d AND type = '%s' AND id = '%s'", $context->cid, $type, $id);
}
}
}
// Add/update any missing associations
if (isset($context->{$type}) && is_array($context->{$type})) {
foreach ($context->{$type} as $id) {
$update = false;
if (!(isset($current->{$type}) && is_array($current->{$type}))) {
$update = true;
}
else if (array_search($id, $current->{$type}) === false) {
$update = true;
}
if ($update) {
$result = db_query("REPLACE INTO {context_ui_item} (cid, type, id) VALUES(%d, '%s', '%s')", $context->cid, $type, $id);
}
}
}
}
return true;
break;
}
}
return false;
}
/**
* Provides simple operations (load/save) on any context-block associations. Parallel usage as
* context_ui_item().
*
* @param $op
* Operation to perform on a context. May be either load or save.
* @param $context
* A context object with an array of blocks at $context->block.
*
* @return
* Load returns a context object with block information. Save returns true on success and false on failure.
*/
function context_ui_item_block($op = 'load', $context) {
if ($context->cid) {
switch ($op) {
case 'load':
$result = db_query("SELECT module, delta, region, weight FROM {context_ui_block} WHERE cid = %d", $context->cid);
$context->block = array();
while ($block = db_fetch_object($result)) {
$bid = $block->module ."_". $block->delta;
$block->bid = $bid;
$context->block[$bid] = $block;
}
return $context;
break;
case 'save':
// grab the current context-> block associations
$current = (object) array('cid' => $context->cid);
$current = context_ui_item_block('load', $current);
// compare current definition with new definition. remove missing associations from the DB
if (is_array($current->block)) {
foreach ($current->block as $block) {
if (!isset($context->block[$block->bid]) || $current->block[$block->bid] != $context->block[$block->bid]) {
$result = db_query("DELETE FROM {context_ui_block WHERE cid = %d AND module = '%s' AND delta = '%s'", $context->cid, $block->module, $block->delta);
}
}
}
// compare new definition with current definition. add missing associations to the DB
if (is_array($context->block)) {
foreach ($context->block as $block) {
$block = (object) $block;
if (!isset($current->block[$block->bid]) || $current->block[$block->bid] != $context->block[$block->bid]) {
$args = array(
'module' => $block->module,
'delta' => $block->delta,
'region' => $block->region,
'weight' => $block->weight,
'cid' => $context->cid,
);
$result = db_query("REPLACE INTO {context_ui_block} (module, delta, region, weight, cid) VALUES ('%s', '%s', '%s', %d, %d)", $args);
}
}
}
return true;
break;
}
}
return false;
}
/**
* Generates a themed set of links for node types associated with
* the current active contexts.
*/
function theme_context_ui_node_links() {
$output = '';
$links = _context_ui_node_links();
foreach ($links as $link) {
$output .= l('+ '. t('Add !type', array('!type' => $link['title'])), $link['href'], array('class' => 'button'));
}
return $output;
}
/**
* Generates an array of links (suitable for use with theme_links)
* to the node forms of types associated with current active contexts.
*/
function _context_ui_node_links($resest = false) {
static $links;
if (!$links || $reset) {
$links = array();
if ($cids = context_get('context_ui', 'cid')) {
// Collect types
$types = node_get_types();
// Iterate over active contexts
foreach ($cids as $cid) {
$context = context_ui_context('load', $cid);
if (is_array($context->node)) {
foreach ($context->node as $type) {
if (isset($types[$type]) && node_access('create', $type)) {
$links[$type] = array(
'title' => $types[$type]->name,
'href' => 'node/add/'. $type,
);
}
}
}
}
}
}
return $links;
}