'admin/panels', 'title' => t('Panels'), 'access' => user_access('access administration pages'), 'callback' => 'system_admin_menu_block_page', 'description' => t('Administer items related to the Panels module.'), ); $items[] = array( 'path' => 'panels/node/autocomplete', 'title' => t('Autocomplete node'), 'callback' => 'panels_node_autocomplete', 'access' => user_access('access content'), 'type' => MENU_CALLBACK ); $items[] = array( 'path' => 'panels/ajax', 'title' => t('ajax'), 'callback' => 'panels_ajax_passthru', 'callback arguments' => array('panels_ajax'), 'access' => user_access('access content'), 'type' => MENU_CALLBACK ); $items[] = array( 'path' => 'panels/common/ajax', 'title' => t('ajax'), 'callback' => 'panels_ajax_passthru', 'callback arguments' => array('panels_common_ajax'), 'access' => user_access('access content'), 'type' => MENU_CALLBACK ); $items[] = array( 'path' => 'panels/ajax/add-content', 'title' => t('ajax'), 'callback' => 'panels_ajax_passthru', 'callback arguments' => array('panels_ajax_add_content'), 'access' => user_access('access content'), 'type' => MENU_CALLBACK ); $items[] = array( 'path' => 'panels/ajax/add-config', 'title' => t('ajax'), 'callback' => 'panels_ajax_passthru', 'callback arguments' => array('panels_ajax_add_config'), 'access' => user_access('access content'), 'type' => MENU_CALLBACK ); $items[] = array( 'path' => 'panels/ajax/configure', 'title' => t('ajax'), 'callback' => 'panels_ajax_passthru', 'callback arguments' => array('panels_ajax_configure'), 'access' => user_access('access content'), 'type' => MENU_CALLBACK ); } return $items; } /** * Helper function for our AJAX stuff to call through to the right location */ function panels_ajax_passthru() { $args = func_get_args(); $callback = array_shift($args); if (arg(1) == 'common') { include_once './' . panels_get_path('includes/common.inc'); } else { include_once './' . panels_get_path('includes/display_edit.inc'); } return call_user_func_array($callback, $args); } /** * Simple render function to make sure output is what we want. * @ingroup panels_ajax */ function panels_ajax_render($output = NULL, $title = NULL, $url = NULL) { if (!is_object($output)) { $temp = new stdClass(); $temp->output = $output; $temp->type = 'display'; $temp->title = $title; $temp->url = $url; $output = $temp; } if (!$output->output || !$output->type) { $output->output = t('The input was invalid'); $output->type = 'display'; $output->title = t('Error'); } drupal_set_header('Content-Type: text/javascript; charset=utf-8'); print drupal_to_js($output); exit; } /** * panels path helper function */ function panels_get_path($file, $base_path = false, $module = 'panels') { if ($base_path) { $output = base_path(); } return $output . drupal_get_path('module', $module) . '/' . $file; } /** * Implementation of hook_perm */ function panels_perm() { return array('view all panes', 'administer pane visibility', 'administer advanced pane settings'); } // --------------------------------------------------------------------------- // panels custom image button /** * Custom form element to do our nice images. */ function panels_elements() { $type['panels_imagebutton'] = array('#input' => TRUE, '#button_type' => 'submit',); return $type; } /** * Theme our image button. */ function theme_panels_imagebutton($element) { return '\n"; } function panels_imagebutton_value() { // null function guarantees default_value doesn't get moved to #value. } /** * Add a single button to a form. */ function panels_add_button($image, $name, $text, $class, $id = NULL) { return array( '#type' => 'panels_imagebutton', '#image' => panels_get_path('images/' . $image), '#title' => $text, '#default_value' => $name, '#class' => $class, '#id' => $id, ); } // --------------------------------------------------------------------------- // cache handling stuff for display editing /** * Get a display from the cache; this is used if the display is currently * being edited, which can be a seriously multi-step process. */ function panels_cache_get($did) { static $cache = array(); if (!array_key_exists($did, $cache)) { $data = cache_get(session_id() . ':' . $did, 'cache'); $cache[$did] = unserialize($data->data); } return $cache[$did]; } /** * Save the edited display into the cache. */ function panels_cache_set($did, $cache) { cache_set(session_id() . ':' . $did, 'cache', serialize($cache), time() + 86400); } /** * Clear a display from the cache; used if the editing is aborted. */ function panels_cache_clear($did) { cache_clear_all(session_id() . ':' . $did, 'cache'); } /** * Global storage function, used mostly so that _submit hooks can pass data * back to their originator more easily. */ function panels_set($var, $value = NULL) { static $vars = array(); if ($value !== NULL) { $vars[$var] = $value; } return $vars[$var]; } /** * Retrieve from global storage */ function panels_get($var) { return panels_set($var); } // --------------------------------------------------------------------------- // panels display editing /** * Main API entry point to edit a panel display. * * TODO: Doc this. Important. */ function panels_edit($display, $destination, $content_types = NULL) { include_once './' . panels_get_path('includes/display_edit.inc'); return _panels_edit($display, $destination, $content_types); } /** * Shortcut to the panels layout editor * * TODO: Doc this. Important. */ function panels_edit_layout($display, $finish, $destination) { include_once './' . panels_get_path('includes/display_edit.inc'); return drupal_get_form('panels_choose_layout', $display, $finish, $destination); } /** * Shortcut to the panels layout settings editor * * TODO: Doc this. Important. */ function panels_edit_layout_settings($display, $finish, $destination) { include_once './' . panels_get_path('includes/display_edit.inc'); return drupal_get_form('panels_edit_layout_settings_form', $display, $finish, $destination); } // --------------------------------------------------------------------------- // panels database functions /** * Forms the basis of a panel display */ class panels_display { var $args = array(); var $incoming_content = NULL; var $css_id = NULL; var $context = array(); } /** * Forms the basis for describing and storing a context that a display * might be running in. */ class panels_context { var $type = NULL; var $data = NULL; function panels_context($type = 'none', $data = NULL) { $this->type = $type; $this->data = $data; $this->title = t('Unknown context'); } function is_type($type) { $a = is_array($type) ? $type : array($type); $b = is_array($this->type) ? $type : array($this->type); return (bool) array_intersect($a, $b); } } /** * Clean up a display and make sure it has some required information if * it doesn't already exist. Currently we wrequire a context, an incoming * content and a css_id. */ function panels_sanitize_display(&$display) { if (!isset($display->args)) { $display->args = array(); } if (!isset($display->incoming_content)) { $display->incoming_content = NULL; } if (!isset($display->context)) { $display->context = array(); } if (!isset($display->css_id)) { $display->css_id = NULL; } } /** * Creates a new display, setting the ID to our magic new id. */ function panels_new_display() { $display = new panels_display(); $display->did = 'new'; return $display; } /** * Load a display from the database */ function panels_load_displays($dids) { $displays = array(); if (empty($dids) || !is_array($dids)) { return $displays; } $subs = implode(', ', array_fill(0, count($dids), '%d')); $result = db_query("SELECT * FROM {panels_display} WHERE did IN ($subs)", $dids); while ($obj = db_fetch_array($result)) { $display = new panels_display(); foreach ($obj as $key => $value) { $display->$key = $value; } // unserialize important bits: if (!empty($display->layout_settings)) { $display->layout_settings = unserialize($display->layout_settings); } else { $display->layout_settings = array(); } if (!empty($display->panel_settings)) { $display->panel_settings = unserialize($display->panel_settings); } else { $display->panel_settings = array(); } $display->panels = $display->content = array(); $displays[$display->did] = $display; } $result = db_query("SELECT * FROM {panels_pane} WHERE did IN ($subs) ORDER BY did, panel, position", $dids); while ($pane = db_fetch_object($result)) { $pane->configuration = unserialize($pane->configuration); $pane->access = ($pane->access ? explode(', ', $pane->access) : array()); $displays[$pane->did]->panels[$pane->panel][] = $pane->pid; $displays[$pane->did]->content[$pane->pid] = $pane; } return $displays; } /** * Load a single display. */ function panels_load_display($did) { $displays = panels_load_displays(array($did)); if (!empty($displays)) { return array_shift($displays); } } /** * Save a display. */ function panels_save_display(&$display) { if ($display->did && $display->did != 'new') { db_query("UPDATE {panels_display} SET layout = '%s', layout_settings = '%s', panel_settings = '%s' WHERE did = %d", $display->layout, serialize($display->layout_settings), serialize($display->panel_settings), $display->did); db_query("DELETE FROM {panels_pane} WHERE did = %d", $display->did); } else { $display->did = db_next_id("{panels_display}_id"); db_query("INSERT INTO {panels_display} (did, layout, layout_settings, panel_settings) VALUES (%d, '%s', '%s', '%s')", $display->did, $display->layout, serialize($display->layout_settings), serialize($display->panel_settings)); } // update all the panes foreach ((array) $display->panels as $id => $panes) { $position = 0; $new_panes = array(); foreach ((array) $panes as $pid) { $pane = $display->content[$pid]; $pane->position = $position++; if (!is_numeric($pid)) { unset($display->content[$pid]); $pane->pid = db_next_id("{panels_pane}_pid"); } db_query("INSERT INTO {panels_pane} (pid, did, panel, type, subtype, configuration, access, position) VALUES (%d, %d, '%s', '%s', '%s', '%s', '%s', %d)", $pane->pid, $display->did, $pane->panel, $pane->type, $pane->subtype, serialize($pane->configuration), !empty($pane->access) ? implode(', ', $pane->access) : '', $pane->position); // and put it back so our pids and positions can be used $display->content[$pid] = $pane; $new_panes[] = $pid; } $display->panels[$id] = $panes; } return $display; // to be nice, even tho we have a reference. } /** * Delete a display */ function panels_delete_display($display) { if (is_object($display)) { $did = $display->did; } else { $did = $display; } db_query("DELETE FROM {panels_display} WHERE did = %d", $did); db_query("DELETE FROM {panels_pane} WHERE did = %d", $did); } /** * Export a display into code */ function panels_export_display($display) { $output = ''; $output .= '$display = new stdClass()' . ";\n"; $output .= '$display->did = \'new\'' . ";\n"; $fields = array('name', 'layout', 'layout_settings', 'panel_settings'); foreach ($fields as $field) { $output .= '$display->' . $field . ' = ' . var_export($display->$field, TRUE) . ";\n"; } $output .= '$display->content = array()' . ";\n"; $output .= '$display->panels = array()' . ";\n"; $panels = array(); $counter = 0; $counters = array(); foreach ($display->content as $pane) { $id = 'new-' . ++$counter; $output .= '$pane = new stdClass()' . ";\n"; $fields = array('panel', 'type', 'subtype', 'access', 'configuration'); foreach ($fields as $field) { $output .= ' $pane->' . $field . ' = ' . var_export($pane->$field, TRUE) . ";\n"; } $output .= '$display->content[\'' . $id . '\'] = $pane' . ";\n"; if (!isset($counters[$pane->panel])) { $counters[$pane->panel] = 0; } $output .= '$display->panels[\'' . $pane->panel . '\'][' . $counters[$pane->panel]++ .'] = \'' . $id . "';\n"; } return $output; } /** * For external use: Given a layout ID and a $content array, return the * panel display. The content array is filled in based upon the content * available in the layout. If it's a two column with a content * array defined like array('left' => t('Left side'), 'right' => * t('Right side')), then the $content array should be array('left' => * $output_left, 'right' => $output_right) * @render */ function panels_print_layout($id, $content) { $layout = panels_get_layout($id); if (!$layout) { return; } return panels_render_layout($layout, $content); } /** * Given a full layout structure and a content array, render a panel display. * @render */ function panels_render_layout($layout, $content, $css_id = NULL, $settings = array()) { if (file_exists(path_to_theme() . '/' . $layout['css'])) { drupal_add_css(path_to_theme() . '/' . $layout['css']); } else { drupal_add_css(panels_get_path($layout['css'], false, $layout['module'])); } // This now comes after the CSS is added, because panels-within-panels must // have their CSS added in the right order; inner content before outer content. if (is_object($content)) { $display = $content; $content = array(); // Loop through all panels, put all panes that belong to the current panel // in an array, then render the panel. foreach ($display->panels as $panel_name => $pids) { $panels = array(); foreach ($pids as $pid) { $panels[$pid] = $display->content[$pid]; } $content[$panel_name] = panels_render_panel($panels, $display); } } $output = theme($layout['theme'], check_plain($css_id), $content, $settings); return $output; } /** * Render a display by loading the content into an appropriate * array and then passing through to panels_render_layout. * * if $incoming_content is NULL, default content will be applied. Use * an empty string to indicate no content. * @render */ function panels_render_display(&$display) { $layout = panels_get_layout($display->layout); if (!$layout) { return NULL; } // TODO: This may not be necessary now. Check this. panels_sanitize_display($display); return panels_render_layout($layout, $display, $display->css_id, $display->layout_settings); } /** * Render a panel, by storing the content of each pane in an appropriate array * and then passing through to the theme function that will render the panel * in the configured panel style. * * @param $panes * An array of panes that are assigned to the panel that's being rendered. * @param $display * A display object. * @return * The rendered HTML for a panel. * @render */ function panels_render_panel($panes_in_panel, $display) { if (!empty($display->panel_settings)) { $style = panels_get_style($display->panel_settings['style']); } else { $style = panels_get_style('default'); }; // Store all panes in an array, sorted by their position in the panel. $panes = array(); foreach ($panes_in_panel as $pane_id => $pane) { if (panels_pane_access($pane)) { // Identify which of our possible contexts apply. $context = NULL; if ($pane->subtype) { $content_type = panels_ct_get_types($pane->type); if (!empty($content_type[$pane->subtype]['required context'])) { if (isset($pane->configuration['context']) && isset($display->context[$pane->configuration['context']])) { $context = $display->context[$pane->configuration['context']]; } // Don't display this pane if a context is required and not found. else { continue; } } } $panes[$pane->position] = panels_get_pane_content($pane, $display->args, $context, $display->incoming_content); } } // Retrieve the pid (can be a panel page id, a mini panel id, etc.), this // might be used (or even necessary) for some panel display styles. // TODO: Got to fix this to use panel page name instead of pid, since pid is // no longer guaranteed. This needs an API to be able to set the final id. $pid = 0; if (isset($display->owner) && is_object($display->owner) && isset($display->owner->pid)) { $panel_id = $display->owner->pid; } if ($function = $style['render panel']) { return $function($display, $panel_id, $panes); } else { // TODO: DEPRECATED. Leaving in to make the transition easier. This will disappear by // alpha 11. return module_invoke($style['module'], 'panels_panel_style_render', $display, $style['name'], $panel_id, $panes); } } /** * @defgroup panels_content Panels content and pane helper/info functions * @{ */ /** * Determine visibility of a panel pane * * @param $pane * The pane object to test. * @param $account * The account to test access against. */ function panels_pane_access($pane, $account = NULL) { if (!$account) { global $user; $account = $user; } // Administrator privileges if (user_access('view all pane', $account)) { return TRUE; } // All views with an empty access setting are available to all roles. if (!$pane->access || !is_array($pane->access)) { return TRUE; } // Otherwise, check roles static $roles = array(); if (!isset($roles[$account->uid])) { $roles[$account->uid] = array_keys($account->roles); $roles[$account->uid][] = $account->uid ? DRUPAL_AUTHENTICATED_RID : DRUPAL_ANONYMOUS_RID; } return array_intersect($pane->access, $roles[$account->uid]); } /** * Get the function to call for a given operation on a content type. * * @param $type * The content type to check. May be the name (which loads the content type) or * an already loaded content type object. * @param $name * The name of the function to retrieve; this will be set in the content type * definition. May be: * - render callback * - title callback * - add callback * - add validate callback * - add submit callback * - edit callback * - edit validate callback * - edit submit callback */ function panels_ct_function($type, $name) { if (is_object($type)) { $content_type = $type; } else { $content_type = panels_get_content_type($type); } $function = $content_type[$name]; if (function_exists($function)) { return $function; } } /** * Get the content from a given content type. * * @param $type * The content type. May be the name or an already loaded content type object. * @param $conf * The configuration for the content type. * @param $args * The arguments to the content type. * @param $context * The panels_context object. * @Param $incoming_content * Any incoming content, if this display is a wrapper. */ function panels_ct_get_content($type, $conf, $args, $context, $incoming_content) { if ($function = panels_ct_function($type, 'render callback')) { return $function($conf, $args, $context, $incoming_content); } } /** * Get the title from a given content type. * * @param $type * The content type. May be the name or an already loaded content type object. * @param $conf * The configuration for the content type. * @param $context * The panels_context object. * @Param $incoming_content * Any incoming content, if this display is a wrapper. */ function panels_ct_get_title($type, $conf, $context = NULL, $incoming_content = NULL) { if ($function = panels_ct_function($type, 'title callback')) { return $function($conf, $context, $incoming_content); } } /** * Create the basic config form */ function panels_ct_conf_form($type, $id, $contexts, $conf) { $content_type = panels_ct_get_types($type); if (!empty($content_type[$id]['required context']) && is_array($contexts)) { // See which of these contexts are valid foreach ($contexts as $cid => $context) { if ($context->is_type($content_type[$id]['required context'])) { $options[$cid] = $context->title; } } } $form = array(); if (!empty($options)) { $form['context'] = array( '#type' => 'select', '#options' => $options, '#title' => t('Context'), '#description' => t('Multiple contexts are valid for this pane; one must be chosen.'), '#default_value' => $conf['context'], ); } return $form; } /** * Get the form to add a new instance of a content type. * * @param $type * The content type. May be the name or an already loaded content type object. * @param $id * The identifier for the content to add; this is specific to the type of * content. * @param $contexts * A list of possible contexts. * @param $parents * The #parents to be used on the form, because some form gadgets need to * know where they live. */ function panels_ct_get_add_form($type, $id, $contexts, $parents) { $form = panels_ct_conf_form($type, $id, $contexts, array()); if ($function = panels_ct_function($type, 'add callback')) { $result = $function($id, $parents); if (is_array($result)) { $form += $result; } } return $form; } /** * Call the validate handler for the add form for a content type. * @param $type * The content type. May be the name or an already loaded content type object. * @param $form * The actual Forms API form that is being validated. * @param $form_values * The actual Forms API values being validated. */ function panels_ct_validate_add_form($type, $form, $form_values) { if ($function = panels_ct_function($type, 'add validate callback')) { return $function($form, $form_values); } } /** * Call the submit handler for the add form for a content type. * @param $type * The content type. May be the name or an already loaded content type object. * @param $form_values * The actual Forms API values being validated. */ function panels_ct_submit_add_form($type, $form_values) { if ($function = panels_ct_function($type, 'add submit callback')) { return $function($form_values); } } /** * Get the form to edit an instance of a content type. * * @param $type * The content type. May be the name or an already loaded content type object. * @param $id * The identifier for the content to add; this is specific to the type of * content. * @param $parents * The #parents to be used on the form, because some form gadgets need to * know where they live. */ function panels_ct_get_edit_form($type, $subtype, $contexts, $conf, $parents) { $form = panels_ct_conf_form($type, $subtype, $contexts, $conf); if ($function = panels_ct_function($type, 'edit callback')) { $result = $function($subtype, $parents, $conf); if (is_array($result)) { $form += $result; } } return $form; } /** * Call the validate handler for the edit form for a content type. * @param $type * The content type. May be the name or an already loaded content type object. * @param $form * The actual Forms API form that is being validated. * @param $form_values * The actual Forms API values being validated. */ function panels_ct_validate_edit_form($type, $form, $form_values) { if ($function = panels_ct_function($type, 'edit validate callback')) { return $function($form, $form_values); } } /** * Call the submit handler for the edit form for a content type. * @param $type * The content type. May be the name or an already loaded content type object. * @param $form_values * The actual Forms API values being validated. */ function panels_ct_submit_edit_form($type, $form_values) { if ($function = panels_ct_function($type, 'edit submit callback')) { return $function($form_values); } } /** * Get all of the individual types provided by a given content types. 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. */ function panels_ct_get_types($type) { if (is_array($type)) { $content_type = $type; } else { $content_type = panels_get_content_type($type); } $function = $content_type['content_types']; if (is_array($function)) { return $function; } if (function_exists($function)) { return $function($conf); } } /** * Get a list of panels available in the layout. @layout */ function panels_get_panels($layout, $display) { if (!empty($layout['panels function']) && function_exists($layout['panels function'])) { return $layout['panels function']($display, $display->layout_settings); } if (!empty($layout['panels'])) { return $layout['panels']; } return array(); } /** * Get an array of all available content types that can be fed into the * display editor for the add content list. * * @param $context * If a context is provided, content that requires that context can apepar. * @param $has_content * Whether or not the display will have incoming content * @param $allowed_types * An array of content allowed keyed boy content_type . '-' . sub_type * @param $default_types * A default allowed/denied status for content that isn't known about */ function panels_get_available_content_types($contexts = NULL, $has_content = FALSE, $allowed_types = NULL, $default_types = NULL) { $content_types = panels_get_content_types(); $available = array(); foreach ($content_types as $id => $type) { foreach (panels_ct_get_types($type) as $cid => $cinfo) { // exclude items that require content if we're saying we don't // provide it. if (!empty($cinfo['requires content']) && !$has_content) { continue; } // Check to see if the content type can be used in this context. if (isset($cinfo['required context'])) { if (empty($contexts)) { continue; } foreach ($contexts as $context) { if (!$context->is_type($cinfo['required_context'])) { continue; } } } // Check to see if the passed-in allowed types allows this content. if ($allowed_types) { $key = $id . '-' . $cid; if (!isset($allowed_types[$key])) { $allowed_types[$key] = isset($default_types[$id]) ? $default_types[$id] : $default_types['other']; } if (!$allowed_types[$key]) { continue; } } // If we made it through all the tests, then we can use this content. $available[$id][$cid] = $cinfo; } } return $available; } // ------------------------------------------------------------------ // Functions to provide information about a panel or part of a panel. /** * Get the content from a given pane. * * @param $pane * The pane to retrieve content from. * @param $args * The arguments sent to the display. * @param $context * The panels context. * @param $incoming_content * Any incoming content if this display is a wrapper. */ function panels_get_pane_content($pane, $args = array(), $context = NULL, $incoming_content = '') { if (!$context) { $context = new panels_context; } if (!$incoming_content === '') { $incoming_content = t('Incoming content will be displayed here.'); } return panels_ct_get_content($pane->type, $pane->configuration, $args, $context, $incoming_content); } /** * Get the title of a pane. * * @param $pane * The $pane object. */ function panels_get_pane_title($pane, $context = NULL, $incoming_content = NULL) { return panels_ct_get_title($pane->type, $pane->configuration, $context, $incoming_content); } /** * @} End of "defgroup panels_content". */ // --------------------------------------------------------------------------- // panels data loading /** * Load plugins from a directory. * * @param $directory * The directory to choose; also the plugin type. * @param $hook * The name of the hook to be invoked. * @param $file * The file to load if we're looking for just one particular plugin. * * @return * An array of information created for this plugin. */ function panels_load_includes($directory, $hook, $file = NULL) { // Load all our plugins. $path = panels_get_path($directory); $files = drupal_system_listing("$file" . '.inc$', $path, 'name', 0); $info = array(); foreach($files as $file) { require_once('./' . $file->filename); $result = _panels_process_plugin('panels', 'panels_' . $file->name, dirname($file->filename), $hook); if (is_array($result)) { $info = array_merge($info, $result); } } return $info; } /** * Load plugin info for all hooks; this is handled separately from plugins * from files. This is cached so we don't find ourselves building htis * repeatedly. * * @param $hook * The hook being invoked. * * @return * An array of info supplied by any hook implementations. */ function panels_load_hooks($hook) { $info = array(); foreach (module_implements($hook) as $module) { $result = _panels_process_plugin($module, $module, drupal_get_path('module', $module), $hook); if (is_array($result)) { $info = array_merge($info, $result); } } return $info; } /** * Process a single hook implementation of a panels plugin. * * @param $module * The module that owns the hook. * @param $identifier * Either the module or 'panels_' . $file->name * @param $hook * The name of the hook being invoked. */ function _panels_process_plugin($module, $identifier, $path, $hook) { $function = $identifier . '_' . $hook; if (!function_exists($function)) { return NULL; } $result = $function(); if (!isset($result) || !is_array($result)) { return NULL; } // Fill in defaults. foreach ($result as $name => $plugin) { $result[$name]['module'] = $module; $result[$name]['name'] = $name; $result[$name]['path'] = $path; } return $result; } /** * Fetch a group of plugins by name. * * @param $plugin * This is the name of the plugin, and also the name of the directory. * @param $hook * This is the hook to call to get the info for the plugin. * * @return * An array of information arrays about the plugins received. */ function panels_get_plugins($plugin, $hook, $id = NULL) { static $plugins = array(); static $all_hooks = array(); static $all_files = array(); // Always load all hooks if we need them. if (!isset($all_hooks[$plugin])) { $all_hooks[$plugin] = TRUE; $plugins[$plugin] = panels_load_hooks($hook); // TODO: DEPRECATED. Put in to make the transition easier! This WILL // disappear by alpha 11. if ($plugin == 'styles') { $plugins[$plugin] = array_merge($plugins[$plugin], panels_load_hooks('panels_panel_style_info')); } } // First, see if it's in our hooks before we even bother. if ($id && array_key_exists($id, $plugins[$plugin])) { return $plugins[$plugin][$id]; } // Then see if we should load all files. We only do this if we're // want a list of all plugins. if (!$id && empty($all_files[$plugin])) { $all_files[$plugin] = TRUE; $plugins[$plugin] = array_merge($plugins[$plugin], panels_load_includes($plugin, $hook)); } // If no id was requested, we are finished here: if (!$id) { return $plugins[$plugin]; } // Check to see if we need to look for the file if (!array_key_exists($id, $plugins[$plugin])) { $result = panels_load_includes($plugin, $hook, $id); // Set to either what was returned or NULL. $plugins[$plugin][$id] = isset($result[$id]) ? $result[$id] : NULL; } // At this point we should either have the plugin, or a NULL. return $plugins[$plugin][$id]; } /** * Fetch a layout plugin * * @param $layout * Name of a panel layout. * @return * An array with information about the requested panel layout. */ function panels_get_layout($layout) { return panels_get_plugins('layouts', 'panels_layouts', $layout); } /** * Fetch all layout plugins * * @return * An array of arrays with information about all available panel layouts. */ function panels_get_layouts() { return panels_get_plugins('layouts', 'panels_layouts'); } /** * Collate information about a specific panel style. * * @param $style * Name of a panel style. * @return * An array with information about the requested panel style. */ function panels_get_style($style) { return panels_get_plugins('styles', 'panels_styles', $style); } /** * Collate information about all available panel styles. * * @return * An array of arrays with information about all available panel styles. */ function panels_get_styles() { return panels_get_plugins('styles', 'panels_styles'); } /** * Collate information about a specific panel argument. * * @param $argument * Name of a panel argument. * @return * An array with information about the requested panel argument. */ function panels_get_argument($argument) { return panels_get_plugins('arguments', 'panels_arguments', $argument); } /** * Collate information about all available panel arguments. * * @return * An array of arrays with information about all available panel arguments. */ function panels_get_arguments() { return panels_get_plugins('arguments', 'panels_arguments'); } /** * Fetch a content_type plugin * * @param $content type * Name of a panel content type. * @return * An array with information about the requested panel content type. */ function panels_get_content_type($content_type) { return panels_get_plugins('content_types', 'panels_content_types', $content_type); } /** * Fetch all content type plugins * * @return * An array of arrays with information about all available panel content types. */ function panels_get_content_types() { return panels_get_plugins('content_types', 'panels_content_types'); } // @render function theme_panels_pane($block, $display) { if (!empty($block->content)) { $output = '
'; $output .= theme('block', $block); $output .= '
'; } return $output; } /** * Print the layout link. Sends out to a theme function. * @layout */ function panels_print_layout_link($id, $layout, $link) { drupal_add_css(panels_get_path('css/panels_admin.css')); $file = panels_get_path($layout['icon'], false, $layout['module']); $image = l(theme('image', $file), $link, NULL, NULL, NULL, NULL, TRUE); $title = l($layout['title'], $link); return theme('panels_layout_link', $title, $id, $image, $link); } // @layout function panels_print_layout_icon($id, $layout, $title = NULL) { drupal_add_css(panels_get_path('css/panels_admin.css')); $file = panels_get_path($layout['icon'], false, $layout['module']); return theme('panels_layout_icon', $id, theme('image', $file), $title); } /** * Theme the layout link image * @layout */ function theme_panels_layout_link($title, $id, $image, $link) { $output .= ''; return $output; } /** * Theme the layout icon image * @layout */ function theme_panels_layout_icon($id, $image, $title = NULL) { $output .= '
'; $output .= $image; if ($title) { $output .= '
' . $title . '
'; } $output .= '
'; return $output; } /** * Helper function for autocompletion of node titles. * This is mostly stolen from clipper. */ function panels_node_autocomplete($string) { // TODO: Compare this to the nodequeue version, see which is better. if ($string != '') { // if there are node_types passed, we'll use those in a MySQL IN query. $result = db_query_range(db_rewrite_sql('SELECT n.title, u.name FROM {node} n INNER JOIN {users} u ON u.uid = n.uid WHERE LOWER(title) LIKE LOWER(\'%%%s%%\')'), $string, 0, 10); $prefix = count($array) ? implode(', ', $array) .', ' : ''; $matches = array(); while ($node = db_fetch_object($result)) { $n = $node->title; // Commas and quotes in terms are special cases, so encode 'em. if (preg_match('/,/', $node->title) || preg_match('/"/', $node->title)) { $n = '"'. preg_replace('/"/', '""', $node->title) .'"'; } $matches[$prefix . $n] = ''. check_plain($node->title) .' ('. t('by %user', array('%user' => check_plain($node->name))) .')'; } drupal_set_header('Content-Type: text/javascript; charset=utf-8'); print drupal_to_js($matches); exit(); } }