FALSE, 'process' => 'ctools_content_process', ); } /** * Provide defaults for a content type. * * Currently we check for automatically named callbacks to make life a little * easier on the developer. */ function ctools_content_process(&$plugin, $info) { $function_base = $plugin['module'] . '_' . $plugin['name'] . '_content_type_'; if (empty($plugin['render callback']) && function_exists($function_base . 'render')) { $plugin['render callback'] = $function_base . 'render'; } if (empty($plugin['admin title'])) { if (function_exists($function_base . 'admin_title')) { $plugin['admin title'] = $function_base . 'admin_title'; } else { $plugin['admin title'] = $plugin['title']; } } if (empty($plugin['admin info']) && function_exists($function_base . 'admin_info')) { $plugin['admin info'] = $function_base . 'admin_info'; } if (!isset($plugin['edit form']) && function_exists($function_base . 'edit_form')) { $plugin['edit form'] = $function_base . 'edit_form'; } if (!isset($plugin['add form']) && function_exists($function_base . 'add_form')) { $plugin['add form'] = $function_base . 'add_form'; } if (!isset($plugin['add form']) && function_exists($function_base . 'edit_form')) { $plugin['add form'] = $function_base . 'edit_form'; } // Another ease of use check: if (!isset($plugin['content types'])) { // If a subtype plugin exists, try to use it. Otherwise assume single. if (function_exists($function_base . 'content_types')) { $plugin['content types'] = $function_base . 'content_types'; } else { $type = array( 'title' => $plugin['title'], 'description' => $plugin['description'], 'icon' => ctools_content_admin_icon($plugin), 'category' => $plugin['category'], ); if (isset($plugin['required context'])) { $type['required context'] = $plugin['required context']; } if (isset($plugin['top level'])) { $type['top level'] = $plugin['top level']; } $plugin['content types'] = array($plugin['name'] => $type); if (!isset($plugin['single'])) { $plugin['single'] = TRUE; } } } } /** * Fetch metadata on a specific content_type plugin. * * @param $content type * Name of a panel content type. * * @return * An array with information about the requested panel content type. */ function ctools_get_content_type($content_type) { ctools_include('context'); ctools_include('plugins'); return ctools_get_plugins('ctools', 'content_types', $content_type); } /** * Fetch metadata for all content_type plugins. * * @return * An array of arrays with information about all available panel content types. */ function ctools_get_content_types() { ctools_include('context'); ctools_include('plugins'); return ctools_get_plugins('ctools', 'content_types'); } /** * Get all of the individual subtypes provided by a given content type. This * would be all of the blocks for the block type, or all of the views for * the view type. * * @param $type * The content type to load. * * @return * An array of all subtypes available. */ function ctools_content_get_subtypes($type) { static $cache = array(); $subtypes = array(); if (is_array($type)) { $plugin = $type; } else { $plugin = ctools_get_content_type($type); } if (empty($plugin) || empty($plugin['name'])) { return; } if (isset($cache[$plugin['name']])) { return $cache[$plugin['name']]; } if (isset($plugin['content types'])) { $function = $plugin['content types']; if (is_array($function)) { $subtypes = $function; } else if (function_exists($function)) { // Cast to array to prevent errors from non-array returns. $subtypes = (array) $function($plugin); } } // Walk through the subtypes and ensure minimal settings are // retained. foreach ($subtypes as $id => $subtype) { // Use exact name since this is a modify by reference. ctools_content_prepare_subtype($subtypes[$id], $plugin); } $cache[$plugin['name']] = $subtypes; return $subtypes; } /** * Given a content type and a subtype id, return the information about that * content subtype. * * @param $type * The content type being fetched. * @param $subtype_id * The id of the subtype being fetched. * * @return * An array of information describing the content subtype. */ function ctools_content_get_subtype($type, $subtype_id) { $subtype = array(); if (is_array($type)) { $plugin = $type; } else { $plugin = ctools_get_content_type($type); } $function = ctools_plugin_get_function($plugin, 'content type'); if ($function) { $subtype = $function($subtype_id, $plugin); } else { $subtypes = ctools_content_get_subtypes($type); if (isset($subtypes[$subtype_id])) { $subtype = $subtypes[$subtype_id]; } // If there's only 1 and we somehow have the wrong subtype ID, do not // care. Return the proper subtype anyway. if (empty($subtype) && !empty($plugin['single'])) { $subtype = current($subtypes); } } if ($subtype) { ctools_content_prepare_subtype($subtype, $plugin); } return $subtype; } /** * Ensure minimal required settings on a content subtype exist. */ function ctools_content_prepare_subtype(&$subtype, $plugin) { foreach (array('path', 'js', 'css') as $key) { if (!isset($subtype[$key]) && isset($plugin[$key])) { $subtype[$key] = $plugin[$key]; } } } /** * Get the content from a given content type. * * @param $type * The content type. May be the name or an already loaded content type plugin. * @param $subtype * The name of the subtype being rendered. * @param $conf * The configuration for the content type. * @param $keywords * An array of replacement keywords that come from outside contexts. * @param $args * The arguments provided to the owner of the content type. Some content may * wish to configure itself based on the arguments the panel or dashboard * received. * @param $context * An array of context objects available for use. * @param $incoming_content * Any incoming content, if this display is a wrapper. * * @return * The content as rendered by the plugin. This content should be an array * with the following possible keys: * - title: The safe to render title of the content. * - content: The safe to render HTML content. * - links: An array of links associated with the content suitable for * theme('links'). * - more: An optional 'more' link (destination only) * - admin_links: Administrative links associated with the content, suitable * for theme('links'). * - feeds: An array of feed icons or links associated with the content. * Each member of the array is rendered HTML. * - type: The content type. * - subtype: The content subtype. These two may be used together as * module-delta for block style rendering. */ function ctools_content_render($type, $subtype, $conf, $keywords = array(), $args = array(), $context = array(), $incoming_content = '') { if (is_array($type)) { $plugin = $type; } else { $plugin = ctools_get_content_type($type); } $subtype_info = ctools_content_get_subtype($plugin, $subtype); $function = ctools_plugin_get_function($subtype_info, 'render callback'); if (!$function) { $function = ctools_plugin_get_function($plugin, 'render callback'); } if ($function) { $pane_context = ctools_content_select_context($plugin, $subtype, $conf, $context); if ($pane_context === FALSE) { return; } $content = $function($subtype, $conf, $args, $pane_context, $incoming_content); // Set up some defaults and other massaging on the content before we hand // it back to the caller. if (!isset($content->type)) { $content->type = $plugin['name']; } if (!isset($content->subtype)) { $content->subtype = $subtype; } // Override the title if configured to if (!empty($conf['override_title'])) { // Give previous title as an available substitution here. $keywords['%title'] = empty($content->title) ? '' : $content->title; $content->original_title = $keywords['%title']; $content->title = $conf['override_title_text']; } if (!empty($content->title)) { // Perform substitutions if (!empty($keywords) || !empty($context)) { $content->title = ctools_context_keyword_substitute($content->title, $keywords, $context); } // Sterilize the title $content->title = filter_xss_admin($content->title); // If a link is specified, populate. if (!empty($content->title_link)) { if (!is_array($content->title_link)) { $url = array('href' => $content->title_link); } else { $url = $content->title_link; } // set defaults so we don't bring up notices $url += array('href' => '', 'attributes' => NULL, 'query' => NULL, 'fragment' => NULL, 'absolute' => NULL, 'html' => TRUE); $content->title = l($content->title, $url['href'], $url); } } return $content; } } /** * Determine if a content type can be edited or not. * * Some content types simply have their content and no options. This function * lets a UI determine if it should display an edit link or not. */ function ctools_content_editable($type, $subtype, $conf) { if (empty($type['edit form']) && empty($subtype['edit form'])) { return FALSE; } if ($function = ctools_plugin_get_function($subtype, 'check editable')) { return $function($type, $subtype, $conf); } return TRUE; } /** * Get the administrative title from a given content type. * * @param $type * The content type. May be the name or an already loaded content type object. * @param $subtype * The subtype being rendered. * @param $conf * The configuration for the content type. * @param $context * An array of context objects available for use. These may be placeholders. */ function ctools_content_admin_title($type, $subtype, $conf, $context = NULL) { if (is_array($type)) { $plugin = $type; } else if (is_string($type)) { $plugin = ctools_get_content_type($type); } else { return; } if ($function = ctools_plugin_get_function($plugin, 'admin title')) { $pane_context = ctools_content_select_context($plugin, $subtype, $conf, $context); if ($pane_context === FALSE) { if ($plugin['name'] == $subtype) { return t('@type will not display due to missing context', array('@type' => $plugin['name'])); } return t('@type:@subtype will not display due to missing context', array('@type' => $plugin['name'], '@subtype' => $subtype)); } return $function($subtype, $conf, $pane_context); } else if (isset($plugin['admin title'])) { return $plugin['admin title']; } else if (isset($plugin['title'])) { return $plugin['title']; } } /** * Get the proper icon path to use, falling back to default icons if no icon exists. * * $subtype * The loaded subtype info. */ function ctools_content_admin_icon($subtype) { $icon = ''; if (isset($subtype['icon'])) { $icon = $subtype['icon']; if (!file_exists($icon)) { $icon = $subtype['path'] . '/' . $icon; } } if (empty($icon) || !file_exists($icon)) { $icon = ctools_image_path('no-icon.png'); } return $icon; } /** * Set up the default $conf for a new instance of a content type. */ function ctools_content_get_defaults($plugin, $subtype) { if (isset($plugin['defaults'])) { $defaults = $plugin['defaults']; } else if (isset($subtype['defaults'])) { $defaults = $subtype['defaults']; } if (isset($defaults)) { if (is_string($defaults) && function_exists($defaults)) { if ($return = $defaults($pane)) { return $return; } } else if (is_array($defaults)) { return $defaults; } } return array(); } /** * Get the administrative title from a given content type. * * @param $type * The content type. May be the name or an already loaded content type object. * @param $subtype * The subtype being rendered. * @param $conf * The configuration for the content type. * @param $context * An array of context objects available for use. These may be placeholders. */ function ctools_content_admin_info($type, $subtype, $conf, $context = NULL) { if (is_array($type)) { $plugin = $type; } else { $plugin = ctools_get_content_type($type); } if ($function = ctools_plugin_get_function($plugin, 'admin info')) { $output = $function($subtype, $conf, $context); } if (empty($output) || !is_object($output)) { $output = new stdClass(); $output->title = t('No info'); $output->content =t ('No info available.'); } return $output; } /** * Add the default FAPI elements to the content type configuration form */ function ctools_content_configure_form_defaults(&$form, &$form_state) { $plugin = $form_state['plugin']; $subtype = $form_state['subtype']; $contexts = isset($form_state['contexts']) ? $form_state['contexts'] : NULL; $conf = $form_state['conf']; $add_submit = FALSE; if (!empty($subtype['required context']) && is_array($contexts)) { $form['context'] = ctools_context_selector($contexts, $subtype['required context'], isset($conf['context']) ? $conf['context'] : array()); $add_submit = TRUE; } ctools_include('dependent'); // Unless we're not allowed to override the title on this content type, add this // gadget to all panes. if (empty($plugin['no title override']) && empty($subtype['no title override'])) { $form['aligner_start'] = array( '#value' => '