'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',
'access' => user_access('access content'),
'type' => MENU_CALLBACK
);
$items[] = array(
'path' => 'panels/ajax/add-content',
'title' => t('ajax'),
'callback' => '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_add_config',
'access' => user_access('access content'),
'type' => MENU_CALLBACK
);
$items[] = array(
'path' => 'panels/ajax/configure',
'title' => t('ajax'),
'callback' => 'panels_ajax_configure',
'access' => user_access('access content'),
'type' => MENU_CALLBACK
);
}
return $items;
}
/**
* 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;
}
// ---------------------------------------------------------------------------
// 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, true),
'#title' => $text,
'#default_value' => $name,
'#class' => $class,
'#id' => $id,
);
}
// ---------------------------------------------------------------------------
// session handling stuff for display editing
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];
}
function panels_cache_set($did, $cache) {
cache_set(session_id() . ':' . $did, 'cache', serialize($cache), time() + 86400);
}
function panels_cache_clear($did) {
cache_clear_all(session_id() . ':' . $did, 'cache');
}
// non-session globals
function panels_set($var, $value = NULL) {
static $vars = array();
if ($value !== NULL) {
$vars[$var] = $value;
}
return $vars[$var];
}
function panels_get($var) {
return panels_set($var);
}
// ---------------------------------------------------------------------------
// panels display editing
/**
* Main API entry point to edit a panel display.
*/
function panels_edit($display, $destination, $content_types = NULL) {
$did = $display->did;
if (!$did) {
$display->did = $did = 'new';
}
if (!empty($_POST) && is_object($cache = panels_cache_get($did))) {
$display = $cache->display;
}
else {
panels_cache_clear($did);
$cache = new stdClass();
$cache->display = $display;
$cache->highest = 0;
$cache->content_types = $content_types;
panels_cache_set($did, $cache);
}
$output = drupal_get_form('panels_edit_display', $display, $destination);
$hidden = theme('panels_hidden');
return $output . $hidden;
}
function panels_edit_display($display, $destination) {
$form['did'] = array(
'#type' => 'hidden',
'#value' => $display->did,
'#id' => 'panel-did',
);
$form['op'] = array(
'#type' => 'hidden',
'#id' => 'panel-op',
);
$form['panels_display'] = array(
'#type' => 'value',
'#value' => $display
);
$form['destination'] = array(
'#type' => 'value',
'#value' => $destination
);
$form['button']['#tree'] = TRUE;
foreach ($display->content as $pid => $panel) {
$form['button'][$pid]['#tree'] = TRUE;
$form['button'][$pid]['configure'] = panels_add_button('wrench.gif', t('Configure'), t('Configure this pane'), 'pane-configure');
$form['button'][$pid]['delete'] = panels_add_button('close.gif', t('Delete'), t('Remove this pane'), 'pane-delete');
}
$layout = panels_get_layout($display->layout);
foreach ($layout['panels'] as $id => $name) {
$form['panels'][$id]['add'] = panels_add_button('add.gif', t('Add content'), t('Add content to this panel'), 'pane-add', "pane-add-$id");
}
$form['panel'] = array('#tree' => TRUE);
$form['panel']['pane'] = array('#tree' => TRUE);
foreach ($layout['panels'] as $panel_id => $title) {
$form['panel']['pane'][$panel_id] = array(
'#type' => 'hidden',
'#default_value' => implode(',', (array) $display->panels[$panel_id]),
);
}
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
'#id' => 'panels-dnd-save',
);
$form['cancel'] = array(
'#type' => 'submit',
'#value' => t('Cancel'),
);
$form['hide'] = array(
'#prefix' => '',
'#suffix' => '',
);
$form['hide']['hide-all'] = array(
'#type' => 'submit',
'#value' => t('Hide all'),
'#id' => 'panels-hide-all',
);
$form['hide']['show-all'] = array(
'#type' => 'submit',
'#value' => t('Show all'),
'#id' => 'panels-show-all',
);
if ($submit) {
// The caller wants their own submit.
$form['#submit'] = array($submit => array());
}
return $form;
}
function theme_panels_edit_display($form) {
_panels_js_files();
$display = $form['panels_display']['#value'];
$layout = panels_get_layout($display->layout);
foreach ($layout['panels'] as $panel_id => $title) {
foreach ((array) $display->panels[$panel_id] as $pid) {
$pane = $display->content[$pid];
$left_buttons = NULL;
$buttons = drupal_render($form['button'][$pid]['configure']);
$buttons .= drupal_render($form['button'][$pid]['delete']);
$content[$pane->panel] .= panels_show_pane($pane, $left_buttons, $buttons);
}
$content[$panel_id] = theme('panels_panel_dnd', $content[$panel_id], $panel_id, $title, drupal_render($form['panels'][$panel_id]['add']));
}
$output .= drupal_render($form);
$output .= theme('panels_dnd', panels_render_layout($layout, $content));
return $output;
}
function panels_edit_display_submit($form_id, $form_values) {
$display = $form_values['panels_display'];
if ($form_values['op'] == t('Save')) {
$old_content = $display->content;
$display->content = array();
foreach ($form_values['panel']['pane'] as $panel_id => $panes) {
$display->panels[$panel_id] = array();
if ($panes) {
$pids = explode(',', $panes);
foreach ($pids as $pid) {
if ($old_content[$pid]) {
$display->panels[$panel_id][] = $pid;
$old_content[$pid]->panel = $panel_id;
$display->content[$pid] = $old_content[$pid];
}
}
}
}
drupal_set_message(t('Panel content has been updated.'));
panels_save_display($display);
}
panels_cache_clear($display->did);
return $form_values['destination'];
}
/**
* Shortcut to the panels layout editor
*/
function panels_edit_layout($display, $finish, $destination) {
return drupal_get_form('panels_choose_layout', $display, $finish, $destination);
}
/**
* Form to change the layout of a display.
*/
function panels_choose_layout($display, $finish, $destination) {
$layouts = panels_get_layouts();
foreach ($layouts as $id => $layout) {
$options[$id] = panels_print_layout_icon($id, $layout, check_plain($layout['title']));
}
$form['layout'] = array(
'#type' => 'radios',
'#title' => t('Choose layout'),
'#options' => $options,
'#default_value' => $display->layout,
);
$form['clearer'] = array(
'#value' => '
',
);
$form['variables'] = array(
'#type' => 'value',
'#value' => array($display, $finish, $destination),
);
if ($_POST['op'] && $_POST['op'] != t('Back') && $display->content) {
$form['#post'] = $_POST;
$form = form_builder('panels_choose_layout', $form);
unset($form['#post']);
$form['layout']['#type'] = 'hidden';
panels_change_layout($form, $display, $form['layout']['#value']);
}
if (($_POST['op'] && $_POST['op'] != t('Back')) || !$display->content) {
$form['submit'] = array(
'#type' => 'submit',
'#value' => $finish,
);
}
else {
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Next'),
);
}
$form['#token'] = FALSE; // no token please
return $form;
}
function panels_choose_layout_submit($form_id, $form_values) {
list($display, $finish, $destination) = $form_values['variables'];
$new_layout_id = $form_values['layout'];
if ($form_values['op'] == $finish) {
foreach ($form_values['old'] as $id => $new_id) {
$content[$new_id] = (array) $content[$new_id] + $display->panels[$id];
foreach($content[$new_id] as $pid) {
$display->content[$pid]->panel = $new_id;
}
}
$display->panels = $content;
$display->layout = $new_layout_id;
// save it back to our session.
panels_save_display($display);
return $destination;
}
return FALSE;
}
function panels_change_layout(&$form, $display, $new_layout_id) {
$new_layout = panels_get_layout($new_layout_id);
$options = $new_layout['panels'];
$keys = array_keys($options);
$default = $options[0];
$old_layout = panels_get_layout($display->layout);
$form['container'] = array(
'#prefix' => '',
'#suffix' => '
',
);
$form['container']['old_layout'] = array(
'#value' => panels_print_layout_icon($display->layout, $old_layout, check_plain($old_layout['title'])),
);
$form['container']['right_arrow'] = array(
'#value' => theme('image', drupal_get_path('module', 'panels') . '/images/go-right.png'),
);
$form['container']['new_layout'] = array(
'#value' => panels_print_layout_icon($new_layout_id, $new_layout, check_plain($new_layout['title'])),
);
$form['container-clearer'] = array(
'#value' => '',
);
$form['old'] = array(
'#tree' => true,
);
foreach ($display->panels as $id => $content) {
$form['old'][$id] = array(
'#type' => 'select',
'#title' => t('Move content in @layout to', array('@layout' => $old_layout['panels'][$id])),
'#options' => $options,
'#default_value' => array_key_exists($id, $options) ? $id : $default,
);
}
$form['back'] = array(
'#type' => 'submit',
'#value' => t('Back'),
);
return $form;
}
// ------------------------------------------------------------------
// Functions to provide information about a content type
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;
}
}
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);
}
}
function panels_ct_get_title($type, $conf) {
if ($function = panels_ct_function($type, 'title callback')) {
return $function($conf);
}
}
function panels_ct_get_add_form($type, $id, $parents) {
if ($function = panels_ct_function($type, 'add callback')) {
return $function($id, $parents);
}
}
function panels_ct_get_edit_form($type, $conf, $parents) {
if ($function = panels_ct_function($type, 'edit callback')) {
return $function($conf, $parents);
}
}
function panels_ct_validate_form($type, $form, $form_values) {
if ($function = panels_ct_function($type, 'validate callback')) {
return $function($form, $form_values);
}
}
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 an array of all available content types that can be fed into the
* display editor for the add content list.
*/
function panels_get_available_content_types($context = NULL, $has_content = FALSE) {
$content_types = panels_get_content_types();
uasort($content_types, 'panels_title_sort');
$available = array();
foreach ($content_types as $id => $type) {
// exclude items that require content if we're saying we don't
// provide it.
if (!empty($type['requires content']) && !$has_content) {
continue;
}
// Check to see if the content type can be used in this context.
if (!isset($type['required context']) ||
(is_array($type['required_context']) &&
in_array($context, $type['required_context'])) ||
($type['required_context'] == $context)) {
$available[$id] = panels_ct_get_types($type);
}
}
return $available;
}
// ------------------------------------------------------------------
// Functions to provide information about a panel or part of a panel.
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);
}
function panels_get_pane_title($pane) {
return panels_ct_get_title($pane->type, $pane->configuration);
}
function panels_get_pane_edit_form($pane, $parents) {
return panels_ct_get_edit_form($pane->type, $pane->configuration, $parents);
}
function panels_show_pane($pane, $left_buttons, $buttons, $skin = TRUE) {
$block = panels_get_pane_content($pane);
$title = panels_get_pane_title($pane);
$output = theme('panels_pane_dnd', $block, $pane->pid, $title, $left_buttons, $buttons);
if ($skin) {
$output = '' . $output . '
';
}
return $output;
}
// ---------------------------------------------------------------------------
// panels ajax stuff (part of editing)
/**
* Simple render function to make sure output is what we want.
*/
function panels_ajax_render($output = NULL, $title = NULL) {
if (!is_object($output)) {
$temp = new stdClass();
$temp->output = $output;
$temp->type = 'display';
$temp->title = $title;
$output = $temp;
}
if (!$output->output || !$output->type) {
$output->output = t('The input was invalid');
$output->type = 'display';
$output->title = t('Error');
}
print drupal_to_js($output);
exit;
}
/**
* entry point into all the ajax stuff
*/
function panels_ajax($op = NULL, $did = NULL, $pid = NULL) {
switch ($op) {
case 'submit-form':
if ((is_numeric($did) || $did == 'new') && $cache = panels_cache_get($did)) {
$output = panels_edit_submit_subform($cache->display);
}
break;
}
panels_ajax_render($output);
}
function panels_ajax_add_content($did = NULL, $panel_id = NULL) {
if ((is_numeric($did) || $did == 'new') && $cache = panels_cache_get($did)) {
$display = $cache->display;
$layout = panels_get_layout($display->layout);
if ($layout && array_key_exists($panel_id, $layout['panels'])) {
$output->output = panels_add_content($cache, $panel_id);
$output->type = 'display';
$output->title = t('Add content to !s', array('!s' => $layout['panels'][$panel_id]));
}
}
panels_ajax_render($output);
}
function panels_add_content($cache, $panel_id) {
$return->type = 'display';
$return->title = t('Choose type');
panels_set('return', $return);
if (!isset($cache->content_types)) {
$cache->content_types = panels_get_available_content_types();
}
foreach ($cache->content_types as $id => $types) {
if (is_array($types)) {
foreach ($types as $content_id => $info) {
if (isset($info['icon'])) {
$icon = $info['icon'];
if (isset($info['path'])) {
$path = $info['path'];
}
else {
$path = panels_get_path("content_types/$id");
}
}
else {
$icon = 'no-icon.png';
$path = panels_get_path('images');
}
$title = filter_xss_admin($info['title']);
if (isset($info['description'])) {
$description = $info['description'];
}
else {
$description = $title;
}
$output .= '';
$link_text = theme('image', $path . '/' . $icon, $description, $description);
$output .= l($link_text, 'javascript: void()', array('class' => 'panels-modal-add-config', 'id' => $id . '-' . $panel_id . '-' . $content_id), NULL, NULL, NULL, TRUE);
$output .= "
$title
";
$output .= '
';
}
}
}
if (!$output) {
$output = t('There are no content types you may add to this display.');
}
return $output;
}
function panels_ajax_add_config($did = NULL, $pid = NULL) {
if ((is_numeric($did) || $did == 'new') && $cache = panels_cache_get($did)) {
$display = $cache->display;
list($content_type_id, $panel_id, $type) = explode('-', $pid, 3);
$conf = panels_ct_get_add_form($content_type_id, $type, array('configuration'));
$types = panels_ct_get_types($content_type_id);
$title = $types[$type]['title'];
$cache->add_config = array($content_type_id, $conf, $panel_id, $title);
panels_cache_set($display->did, $cache);
$text = drupal_get_form('panels_add_content_config_form', $cache, $content_type_id, $conf, $panel_id, $title);
$output = panels_get('return');
$output->output = $text;
}
panels_ajax_render($output);
}
function panels_add_content_config_form($display, $content_type_id = NULL, $conf = NULL, $panel_id = NULL, $title = NULL) {
if (empty($content_type_id)) {
$cache = panels_cache_get($display->did);
if (isset($cache->add_config)) {
list($content_type_id, $conf, $panel_id, $title) = $cache->add_config;
}
}
$form['start_form'] = array('#value' => '');
$form['did'] = array(
'#type' => 'value',
'#value' => $display->did,
);
$form['type'] = array(
'#type' => 'value',
'#value' => $content_type_id,
);
$form['panel'] = array(
'#type' => 'value',
'#value' => $panel_id,
);
$form['configuration'] = $conf;
$form['configuration']['#tree'] = TRUE;
$form['end_form'] = array('#value' => '
');
$form['next'] = array(
'#type' => 'submit',
'#value' => t('Add pane'),
);
$return->type = 'display';
$return->title = t('Configure !s', array('!s' => $title));
panels_set('return', $return);
return $form;
}
function panels_add_content_config_form_validate($form_id, $form_values, $form) {
panels_ct_validate_form($form_values['type'], $form['configuration'], $form_values['configuration']);
}
function panels_add_content_config_form_submit($form_id, $form) {
$cache = panels_cache_get($form['did']);
// keep an incrementing counter, add the data to the display.
$pid = ++$cache->highest;
$form['pid'] = "new-$pid";
$cache->display->content[$form['pid']] = (object) $form;
$cache->display->panels[$form['panel']][] = $form['pid'];
panels_cache_set($form['did'], $cache);
$return->type = 'add';
$return->area = $form['panel'];
$return->id = $form['pid'];
// we need to fake the buttons a little.
$buttons['configure'] = panels_add_button('wrench.gif', t('Configure'), t('Configure this pane'), 'pane-configure');
$buttons['configure']['#parents'] = array('button', $form['pid'], 'configure');
$buttons['delete'] = panels_add_button('close.gif', t('Delete'), t('Remove this pane'), 'pane-delete');
$buttons['delete']['#parents'] = array('button', $form['pid'], 'delete');
$buttons = form_builder('dummy', $buttons);
$return->output = panels_show_pane($cache->display->content[$form['pid']], NULL, drupal_render($buttons));
panels_set('return', $return);
return FALSE;
}
function panels_ajax_configure($did = NULL, $pid = NULL) {
if ((is_numeric($did) || $did == 'new') && $cache = panels_cache_get($did)) {
$text = drupal_get_form('panels_edit_pane_config_form', $cache->display, $pid);
$output = panels_get('return');
$output->output = $text;
}
panels_ajax_render($output);
}
function panels_edit_pane_config_form($display, $pid = NULL) {
$cache = panels_cache_get($display->did);
if ($pid === NULL) {
if (isset($cache->pid)) {
$pid = $cache->pid;
}
else {
return array();
}
}
else {
$cache->pid = $pid;
panels_cache_set($display->did, $cache);
}
$pane = $display->content[$pid];
$form['start_form'] = array('#value' => '');
$form['did'] = array(
'#type' => 'value',
'#value' => $display->did,
);
$form['pid'] = array(
'#type' => 'value',
'#value' => $pid,
);
$form['type'] = array(
'#type' => 'value',
'#value' => $content_type_id,
);
$return->title = t('Configure !s', array('!s' => panels_get_pane_title($pane)));
$form['configuration'] = panels_get_pane_edit_form($pane, array('configuration'));
$form['configuration']['#tree'] = true;
$return->type = 'display';
panels_set('return', $return);
$form['end_form'] = array('#value' => '
');
$form['next'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
return $form;
}
function panels_edit_pane_config_form_submit($form_id, $form) {
// save the new configuration.
$cache = panels_cache_get($form['did']);
$cache->display->content[$form['pid']]->configuration = $form['configuration'];
panels_cache_set($form['did'], $cache);
$return->type = 'replace';
$return->id = $form['pid'];
$block = panels_get_pane_content($cache->display->content[$form['pid']]);
if (!$block->subject) {
$block->subject = t('No title');
}
$return->output = theme('panels_pane', $block, $cache->display);
panels_set('return', $return);
return FALSE;
}
function panels_edit_submit_subform($display) {
$valid_forms = array('panels_add_content_config_form', 'panels_edit_pane_config_form');
$form_id = $_POST['form_id'];
if (!in_array($form_id, $valid_forms)) {
return panels_ajax_render();
}
// TODO: protect form_id to make sure it can only get panels forms.
$output = drupal_get_form($form_id, $display);
$next = panels_get('next');
if ($next) {
$output = drupal_get_form($next['form'], $display, $next['data']);
$return = panels_get('return');
if (!$return->output) {
$return->output = $output;
}
}
else {
if (!($return = panels_get('return'))) {
$return->type = 'display';
$return->output = $output;
}
else if ($return->type == 'display' && !$return->output) {
$return->output = $output;
}
}
if ($return->type == 'display') {
$return->output = theme('status_messages') . $return->output;
}
return $return;
}
// End of ajax functions
// ---------------------
/* TODO: Integrate this back in */
/*
function panels_edit_display_validate($form_id, $form_values, $form) {
foreach ($form_values['content'] as $area => $content) {
foreach ($content as $id => $item) {
if (is_numeric($id)) {
panels_ct_validate($item['type'], $item['configuration'], $form['content'][$area][$id]['configuration']);
}
}
}
}
*/
/**
* move an item in an array to the top
*/
function panels_move_top(&$array, &$position) {
$value = $array[$position];
unset($array[$position]);
array_unshift($array, $value);
// reindex the array now
$array = array_values($array);
}
/**
* move an item in an array to the bottom
*/
function panels_move_bottom(&$array, &$position) {
$value = $array[$position];
unset($array[$position]);
$array[] = $value;
// reindex the array now
$array = array_values($array);
}
/**
* move an item in an array up one position
*/
function panels_move_up(&$array, &$position) {
$value = $array[$position];
$array[$position] = $array[$position - 1];
$array[$position - 1] = $value;
}
/**
* move an item in an array up one position
*/
function panels_move_down(&$array, &$position) {
$value = $array[$position];
$array[$position] = $array[$position + 1];
$array[$position + 1] = $value;
}
/**
* Remove an item from an array
*/
function panels_move_delete(&$array, &$position) {
unset($array[$position]);
// reindex the array now
$array = array_values($array);
}
// ---------------------------------------------------------------------------
// panels database functions
class panels_display {
var $args = array();
var $incoming_content = NULL;
var $context = NULL;
var $css_id = NULL;
function panels_display($context = NULL) {
if (!isset($context)) {
$this->context = new panels_context();
}
}
}
function panels_new_display($context = NULL) {
$display = new panels_display($context);
$display->did = 'new';
return $display;
}
function panels_load_display($did, $context = NULL) {
$display = new panels_display($context);
$obj = db_fetch_array(db_query("SELECT * FROM {panels_display} WHERE did = %d", $did));
foreach ($obj as $key => $value) {
$display->$key = $value;
}
if (!$display) {
return NULL;
}
$result = db_query("SELECT * FROM {panels_pane} WHERE did = %d ORDER BY panel, position", $did);
$display->panels = $display->content = array();
while ($pane = db_fetch_object($result)) {
$pane->configuration = unserialize($pane->configuration);
$display->panels[$pane->panel][] = $pane->pid;
$display->content[$pane->pid] = $pane;
}
return $display;
}
function panels_save_display(&$display) {
if ($display->did && $display->did != 'new') {
db_query("UPDATE {panels_display} SET layout = '%s' WHERE did = %d", $display->layout, $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) VALUES (%d, '%s')", $display->did, $display->layout);
}
// update all the panes
foreach ($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, configuration, position) VALUES (%d, %d, '%s', '%s', '%s', %d)", $pane->pid, $display->did, $pane->panel, $pane->type, serialize($pane->configuration), $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.
}
function panels_delete_display($display) {
db_query("DELETE FROM {panels_display} WHERE did = %d", $display->did);
db_query("DELETE FROM {panels_pane} WHERE did = %d", $display->did);
}
/**
* For external use: Given a layout ID and a $content array, return the
* panel display.
*/
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.
*/
function panels_render_layout($layout, $content, $css_id = NULL) {
$output = theme($layout['theme'], check_plain($css_id), $content);
if ($output) {
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']));
}
}
return $output;
}
class panels_context {
var $type = NULL;
var $data = NULL;
function panels_context($type = 'none', $data = NULL) {
$this->type = $type;
$this->data = $data;
}
}
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 = new panels_context();
}
if (!isset($display->css_id)) {
$display->css_id = NULL;
}
}
/**
* 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.
*/
function panels_render_display(&$display) {
$layout = panels_get_layout($display->layout);
if (!$layout) {
return NULL;
}
panels_sanitize_display($display);
foreach ($display->content as $pid => $pane) {
if ($result = panels_get_pane_content($pane, $display->args, $display->context, $display->incoming_content)) {
if (!empty($content[$pane->panel])) {
$content[$pane->panel] .= theme('panels_separator', $display);
}
$content[$pane->panel] .= theme('panels_pane', $result, $display);
}
}
$output = panels_render_layout($layout, $content, $display->css_id);
return $output;
}
// ---------------------------------------------------------------------------
// panels data loading
function panels_load_includes($directory, $callback, $file = NULL) {
// Load all our module 'on behalfs'.
$path = panels_get_path($directory);
$files = drupal_system_listing("$file" . '.inc$', $path, 'name', 0);
foreach($files as $file) {
require_once('./' . $file->filename);
}
$output = module_invoke_all($callback);
foreach ($files as $file) {
$function = 'panels_' . $file->name . '_' . $callback;
if (function_exists($function)) {
$result = $function();
if (isset($result) && is_array($result)) {
$output = array_merge($output, $result);
}
}
}
return $output;
}
function panels_get_layout($layout) {
return panels_get_layouts($layout);
}
function panels_get_layouts($layout = NULL) {
static $layouts = array();
static $all_layouts = FALSE;
if (!$all_layouts) {
if (!$layout) {
$layouts = panels_load_includes('layouts', 'panels_layouts');
$all_layouts = TRUE;
}
else if (!array_key_exists($layout, $layouts)) {
$temp_layouts = panels_load_includes('layouts', 'panels_layouts', $layout);
if (isset($temp_layouts[$layout])) {
$layouts[$layout] = $temp_layouts[$layout];
}
}
}
if ($layout) {
return isset($layouts[$layout]) ? $layouts[$layout] : NULL;
}
return $layouts;
}
function panels_get_content_type($content_type) {
return panels_get_content_types($content_type);
}
function panels_get_content_types($content_type = NULL) {
static $content_types = array();
static $all_content_types = FALSE;
if (!$all_content_types) {
if (!$content_type) {
$content_types = panels_load_includes('content_types', 'panels_content_types');
$all_content_types = TRUE;
}
else if (!array_key_exists($content_type, $content_types)) {
$temp_content_types = panels_load_includes('content_types', 'panels_content_types', $content_type);
if (isset($temp_content_types[$content_type])) {
$content_types[$content_type] = $temp_content_types[$content_type];
}
}
}
if ($content_type) {
return isset($content_types[$content_type]) ? $content_types[$content_type] : NULL;
}
return $content_types;
}
/**
* Includes required JavaScript libraries:
* jQuery, iutil, idrag, idrop, isortables
* In addition to panels.js.
*/
function _panels_js_files() {
// while we don't use this directly some of our forms do.
drupal_add_js('misc/collapse.js');
drupal_add_js('misc/autocomplete.js');
drupal_add_js(panels_get_path('js/lib/dimensions.js'));
drupal_add_js(panels_get_path('js/lib/mc.js'));
drupal_add_js(panels_get_path('js/lib/form.js'));
drupal_add_js(panels_get_path('js/display_editor.js'));
drupal_add_css(panels_get_path('css/panels_dnd.css'));
drupal_add_css(panels_get_path('css/panels_admin.css'));
}
// ---------------------------------------------------------------------------
// Panels theming functions
function theme_panels_dnd($content) {
$output = "$content
";
return $output;
}
function theme_panels_panel_dnd($content, $area, $label, $footer) {
return "$footer
$label
$content";
}
function theme_panels_pane_dnd($block, $id, $label, $left_buttons = NULL, $buttons = NULL) {
if (!$block->subject) {
$block->subject = t('No title');
}
static $count = 0;
$output .= "";
if ($buttons) {
$output .= "$buttons";
}
if ($left_buttons) {
$output .= "$left_buttons";
}
$output .= "$label
";
$output .= '';
$output .= theme('panels_pane_collapsible', $block);
$output .= '
';
return $output;
}
function theme_panels_pane($block, $display) {
$output = '';
$output .= theme('block', $block);
$output .= '
';
return $output;
}
function theme_panels_pane_collapsible($block) {
$output .= '' . $block->subject . '
';
$output .= '' . filter_xss_admin($block->content) . '
';
return $output;
}
function theme_panels_separator($display) {
return '';
}
/**
* Print the layout link. Sends out to a theme function.
*/
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);
}
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
*/
function theme_panels_layout_link($title, $id, $image, $link) {
$output .= '';
$output .= $image;
$output .= '
' . $title . '
';
$output .= '
';
return $output;
}
/**
* Theme the layout icon image
*/
function theme_panels_layout_icon($id, $image, $title = NULL) {
$output .= '';
$output .= $image;
if ($title) {
$output .= '
' . $title . '
';
}
$output .= '
';
return $output;
}
/**
* This is separate because it must be outside the