t('Block'), 'content type' => 'ctools_block_content_type_content_type', ); /** * Return the block content types with the specified $subtype_id. */ function ctools_block_content_type_content_type($subtype_id) { list($module, $delta) = explode('-', $subtype_id, 2); $module_blocks = module_invoke($module, 'block_info'); if (isset($module_blocks[$delta])) { return _ctools_block_content_type_content_type($module, $delta, $module_blocks[$delta]); } } /** * Return all block content types available. * * Modules wanting to make special adjustments the way that CTools handles their blocks * can implement an extension to the hook_block() family, where the function name is * of the form "$module . '_ctools_block_info'". */ function ctools_block_content_type_content_types() { $types = &drupal_static(__FUNCTION__); if (isset($types)) { return $types; } $types = array(); foreach (module_implements('block_info') as $module) { $module_blocks = module_invoke($module, 'block_info'); if ($module_blocks) { foreach ($module_blocks as $delta => $block) { $info = _ctools_block_content_type_content_type($module, $delta, $block); // This check means modules can remove their blocks; particularly useful // if they offer the block some other way (like we do for views) if ($info) { $types["$module-$delta"] = $info; } } } } return $types; } /** * Return an info array for a specific block. */ function _ctools_block_content_type_content_type($module, $delta, $block) { // strip_tags used because it goes through check_plain and that // just looks bad. $info = array( 'title' => strip_tags($block['info']), ); // Ask around for further information by invoking the hook_block() extension. $function = $module . '_ctools_block_info'; if (!function_exists($function)) { $function = 'ctools_default_block_info'; } $function($module, $delta, $info); return $info; } /** * Load block info from the database. * * This is copied from _block_load_blocks(). It doesn't use that * function because _block_load_blocks sorts by region, and it * doesn't cache its results anyway. */ function _ctools_block_load_blocks() { if (!module_exists('block')) { return array(); } $blocks = &drupal_static(__FUNCTION__, NULL); if (!isset($blocks)) { global $theme_key; $query = db_select('block', 'b'); $result = $query ->fields('b') ->condition('b.theme', $theme_key) ->orderBy('b.region') ->orderBy('b.weight') ->orderBy('b.module') ->addTag('block_load') ->addTag('translatable') ->execute(); $block_info = $result->fetchAllAssoc('bid'); // Allow modules to modify the block list. drupal_alter('block_list', $block_info); $blocks = array(); foreach ($block_info as $block) { $blocks["{$block->module}_{$block->delta}"] = $block; } } return $blocks; } /** * Fetch the stored info for a block. * * The primary reason to use this is so that modules which perform alters * can have their alters make it to the block. */ function _ctools_get_block_info($module, $delta) { $blocks = _ctools_block_load_blocks(); $key = $module . '_' . $delta; if (isset($blocks[$key])) { return $blocks[$key]; } } /** * Output function for the 'block' content type. Outputs a block * based on the module and delta supplied in the configuration. */ function ctools_block_content_type_render($subtype, $conf) { list($module, $delta) = _ctools_block_get_module_delta($subtype, $conf); $info = _ctools_get_block_info($module, $delta); $block = module_invoke($module, 'block_view', $delta); if (!empty($info)) { // Valid PHP function names cannot contain hyphens. $block_delta = str_replace('-', '_', $delta); // Allow modules to modify the block before it is viewed, via either // hook_block_view_alter() or hook_block_view_MODULE_DELTA_alter(). drupal_alter(array('block_view', "block_view_{$module}_{$block_delta}"), $block, $info); } if (empty($block)) { return; } $block = (object) $block; $block->module = $module; $block->delta = $delta; if (!isset($block->title)) { if ($module == 'block' && !empty($info) && isset($info->title)) { $block->title = $info->title; } elseif (isset($block->subject)) { $block->title = $block->subject; } else { $block->title = NULL; } } if (module_exists('block') && user_access('administer blocks')) { $block->admin_links = array( array( 'title' => t('Configure block'), 'href' => "admin/structure/block/manage/$module/$delta/configure", 'query' => drupal_get_destination(), ), ); } return $block; } /** * Empty form so we can have the default override title. */ function ctools_block_content_type_edit_form($form, &$form_state) { // Does nothing! return $form; } /** * Submit function to fix the subtype for really old panel panes. */ function ctools_block_content_type_edit_form_submit($form, &$form_state) { if (empty($form_state['subtype']) && isset($form_state['pane'])) { $form_state['pane']->subtype = $form_state['conf']['module'] . '-' . $form_state['conf']['delta']; unset($form_state['conf']['module']); unset($form_state['conf']['delta']); } } /** * Returns the administrative title for a type. */ function ctools_block_content_type_admin_title($subtype, $conf) { list($module, $delta) = _ctools_block_get_module_delta($subtype, $conf); $block = module_invoke($module, 'block_info'); if (empty($block) || empty($block[$delta])) { return t('Deleted/missing block @module-@delta', array('@module' => $module, '@delta' => $delta)); } // The block description reported by hook_block() is plain text, but the title // reported by this hook should be HTML. $title = check_plain($block[$delta]['info']); return $title; } /** * Output function for the 'block' content type. Outputs a block * based on the module and delta supplied in the configuration. */ function ctools_block_content_type_admin_info($subtype, $conf) { list($module, $delta) = _ctools_block_get_module_delta($subtype, $conf); $block = (object) module_invoke($module, 'block_view', $delta); if (!empty($block)) { // Sanitize the block because