'; $output .= t('You may peruse a list of your current panels layouts and edit them, or click add to create a new page.'); $output .= '
'; break; case 'admin/panels/panel-page/add': $output = ''; $output .= t('Choose a layout for your new page from the list below.'); $output .= '
'; break; } return $output; } /** * Implementation of hook_perm(). */ function panels_page_perm() { return array('create panel-pages', 'access all panel-pages'); } /** * Implementation of hook_menu(). */ function panels_page_menu($may_cache) { $items = array(); $panels = panels_page_load_all(); if ($may_cache) { $access = user_access('create panel-pages'); $items[] = array( 'path' => 'admin/panels/panel-page', 'title' => t('Panel pages'), 'access' => $access, 'callback' => 'panels_page_passthru', 'callback arguments' => array('panels_page_list_page'), 'description' => t('Create and administer panel-pages (complex layout pages with URLs).'), ); $items[] = array( 'path' => 'admin/panels/panel-page/list', 'title' => t('List'), 'access' => $access, 'callback' => 'panels_page_passthru', 'callback arguments' => array('panels_page_list_page'), 'weight' => -10, 'type' => MENU_DEFAULT_LOCAL_TASK, ); $items[] = array( 'path' => 'admin/panels/panel-page/add', 'title' => t('Add'), 'access' => $access, 'callback' => 'panels_page_passthru', 'callback arguments' => array('panels_page_add_page'), 'type' => MENU_LOCAL_TASK, ); $items[] = array( 'path' => 'admin/panels/panel-page/import', 'title' => t('Import'), 'access' => $access, 'callback' => 'panels_page_passthru', 'callback arguments' => array('panels_page_import_page'), 'type' => MENU_LOCAL_TASK, ); $items[] = array( 'path' => 'admin/panels/panel-page/settings', 'title' => t('Settings'), 'access' => $access, 'callback' => 'panels_page_settings', 'weight' => 5, 'type' => MENU_LOCAL_TASK, ); $items[] = array( 'path' => 'admin/panels/panel-page/disable', 'access' => $access, 'callback' => 'panels_page_passthru', 'callback arguments' => array('panels_page_disable_page'), 'weight' => -1, 'type' => MENU_CALLBACK, ); $items[] = array( 'path' => 'admin/panels/panel-page/enable', 'access' => $access, 'callback' => 'panels_page_passthru', 'callback arguments' => array('panels_page_enable_page'), 'weight' => -1, 'type' => MENU_CALLBACK, ); // Get all panels and, if enabled, create menu items. foreach ($panels as $panel_page) { if (empty($panel_page->disabled)) { // Only create menu items based on the path if it's not a variable path. if (strpos($panel_page->path, '%') === FALSE) { _panels_page_create_menu_item($items, $panel_page, $panel_page->path, array($panel_page->name, FALSE)); // DEBUG: Above is now creating only the basic menu item, not the admin items. } panels_page_admin_menu_items($items, 'admin/panels/panel-page/' . $panel_page->name, $panel_page); } } } else { // Look for panels with variable arguments. // Build an array of $urls because 'real' URLs will take precedence over // argument filled URLs $urls = array(); foreach ($panels as $panel_page) { $url[$panel_page->path] = TRUE; } $plugins_loaded = FALSE; foreach ($panels as $panel_page) { if (!empty($panel_page->disabled)) { continue; } if (strpos($panel_page->path, '%') !== FALSE) { $path = explode('/', $panel_page->path); // First pass: // Check if the current path sufficiently matches $panel_page->path, // which means: all fixed parts that come before the last %-wildcard // need to match, while trailing fixed parts don't matter. // We start with the last part and take up checking after reaching a %. $check = FALSE; foreach (array_reverse($path, TRUE) as $id => $chunk) { if ($chunk == '%') { $check = TRUE; continue; } if ($check && $chunk != arg($id)) { // Skip outer foreach loop to continue with the next $panel_page. continue 2; } } $args = array($panel_page, FALSE); // Second pass: $argument = reset($panel_page->arguments); // Get first argument. foreach ($path as $id => $chunk) { if ($chunk != '%') { continue; } // For arguments that are embedded in the URL, we require the // argument handler to return a context, if there is an argument handler. if ($argument) { // Try to avoid loading the plugins code unless necessary. if (!$plugins_loaded) { panels_load_include('plugins'); $plugins_loaded = TRUE; } $context = panels_argument_get_context($argument, arg($id)); if (!$context) { break; } $panel_page->context[panels_argument_context_id($argument)] = $context; } $path[$id] = arg($id); $args[] = arg($id); $argument = next($panel_page->arguments); // Get next argument. } _panels_page_create_menu_item($items, $panel_page, implode('/', $path), $args); // DEBUG: Above is now creating only the basic menu item, not the admin items. } } } return $items; } /** * Helper function to add a menu item for a panel. */ function panels_page_admin_menu_items(&$items, $base, $page) { $access = user_access('create panel-pages'); $items[] = array( 'path' => $base, 'title' => t('Preview'), 'access' => $access, 'callback' => 'panels_page_view_page', 'callback arguments' => array($page->name, TRUE), 'weight' => -10, 'type' => MENU_CALLBACK, ); $items[] = array( 'path' => $base . '/preview', 'title' => t('Preview'), 'access' => $access, 'callback' => 'panels_page_view_page', 'callback arguments' => array($page->name, TRUE), 'weight' => -10, 'type' => MENU_DEFAULT_LOCAL_TASK, ); // Set up for the 'default' display. $items[] = array( 'path' => $base . '/edit/layout', 'title' => t('Layout'), 'access' => $access, 'callback' => 'panels_page_passthru', 'callback arguments' => array('panels_page_edit_layout', $page->name), 'weight' => -9, 'type' => MENU_LOCAL_TASK, ); $items[] = array( 'path' => $base . '/edit/general', 'title' => t('Settings'), 'access' => $access, 'callback' => 'panels_page_passthru', 'callback arguments' => array('panels_page_edit', $page->name), 'weight' => -7, 'type' => MENU_LOCAL_TASK, ); $items[] = array( 'path' => $base . '/edit/settings', 'title' => t('Layout settings'), 'access' => $access, 'callback' => 'panels_page_passthru', 'callback arguments' => array('panels_page_edit_layout_settings', $page->name, NULL), 'weight' => -5, 'type' => MENU_LOCAL_TASK, ); $items[] = array( 'path' => $base . '/edit/advanced', 'title' => t('Advanced'), 'access' => $access, 'callback' => 'panels_page_passthru', 'callback arguments' => array('panels_page_edit_advanced', $page->name), 'weight' => -3, 'type' => MENU_LOCAL_TASK, ); $items[] = array( 'path' => $base . '/edit/context', 'title' => t('Context'), 'access' => $access, 'callback' => 'panels_page_passthru', 'callback arguments' => array('panels_page_edit_context', $page->name), 'weight' => -2, 'type' => MENU_LOCAL_TASK, ); $items[] = array( 'path' => $base . '/edit/content', 'title' => t('Content'), 'access' => $access, 'callback' => 'panels_page_passthru', 'callback arguments' => array('panels_page_edit_content', $page->name), 'weight' => -1, 'type' => MENU_LOCAL_TASK, ); $items[] = array( 'path' => $base . '/edit/layout/default', 'title' => t('Default'), 'access' => $access, 'callback' => 'panels_page_passthru', 'callback arguments' => array('panels_page_edit_layout', $page->name), 'weight' => -1, 'type' => MENU_DEFAULT_LOCAL_TASK, ); $items[] = array( 'path' => $base . '/edit/settings/default', 'title' => t('Default'), 'access' => $access, 'callback' => 'panels_page_passthru', 'callback arguments' => array('panels_page_edit_layout_settings', $page->name, NULL), 'weight' => -1, 'type' => MENU_DEFAULT_LOCAL_TASK, ); $items[] = array( 'path' => $base . '/edit/content/default', 'title' => t('Default'), 'access' => $access, 'callback' => 'panels_page_passthru', 'callback arguments' => array('panels_page_edit_content', $page->name), 'weight' => -1, 'type' => MENU_DEFAULT_LOCAL_TASK, ); if (!empty($page->displays)) { foreach ($page->displays as $display_id => $info) { $items[] = array( 'path' => $base . '/edit/layout/' . $display_id, 'title' => $info['title'], 'access' => $access, 'callback' => 'panels_page_passthru', 'callback arguments' => array('panels_page_edit_layout', $page->name, $display_id), 'type' => MENU_LOCAL_TASK, ); $items[] = array( 'path' => $base . '/edit/settings/' . $display_id, 'title' => $info['title'], 'access' => $access, 'callback' => 'panels_page_passthru', 'callback arguments' => array('panels_page_edit_layout_settings', $page->name, $display_id), 'type' => MENU_LOCAL_TASK, ); $items[] = array( 'path' => $base . '/edit/content/' . $display_id, 'title' => $info['title'], 'access' => $access, 'callback' => 'panels_page_passthru', 'callback arguments' => array('panels_page_edit_content', $page->name, $display_id), 'type' => MENU_LOCAL_TASK, ); } } $items[] = array( 'path' => $base . '/export', 'title' => t('Export'), 'access' => $access, 'callback' => 'panels_page_passthru', 'callback arguments' => array('drupal_get_form', 'panels_page_edit_export', $page->name), 'weight' => 0, 'type' => MENU_LOCAL_TASK, ); $items[] = array( 'path' => $base . '/delete', 'title' => t('Delete panel page'), 'access' => $access, 'callback' => 'panels_page_passthru', 'callback arguments' => array('drupal_get_form', 'panels_page_delete_confirm', $page->name), 'type' => MENU_CALLBACK, ); } /** * Create a menu item for a panel page. */ function _panels_page_create_menu_item(&$items, $panel_page, $path, $args = array()) { $access = panels_page_access($panel_page); $title = filter_xss_admin(panels_page_get_title($panel_page, 'menu')); $type = _panels_page_menu_type($panel_page); if ($type == MENU_LOCAL_TASK || $type == MENU_DEFAULT_LOCAL_TASK) { $weight = $panel_page->menu_tab_weight; } $items[] = _panels_page_menu_item($path, $title, $panel_page, $args, $access, $type, isset($weight) ? $weight : NULL); if ($type == MENU_DEFAULT_LOCAL_TASK && dirname($path) && dirname($path) != '.') { switch ($panel_page->menu_tab_default_parent_type) { case 'tab': $parent_type = MENU_LOCAL_TASK; break; case 'normal': $parent_type = MENU_NORMAL_ITEM; break; default: case 'existing': $parent_type = 0; break; } if ($parent_type) { $title = filter_xss_admin(panels_page_get_title($panel_page, 'menu-parent')); $weight = $panel_page->menu_parent_tab_weight; $items[] = _panels_page_menu_item(dirname($path), $title, $panel_page, $args, $access, $parent_type, $weight); } } } /** * Helper function to create a menu item for a panel. */ function _panels_page_menu_item($path, $title, $panel_page, $args, $access, $type, $weight = NULL) { $retval = array('path' => $path, 'title' => $title, 'callback' => 'panels_page_view_page', 'callback arguments' => $args, 'access' => user_access('access content') && $access, 'type' => $type, ); if ($weight !== NULL) { $retval['weight'] = $weight; } return $retval; } /** * Determine what menu type a panel needs to use. */ function _panels_page_menu_type($panel_page) { if ($panel_page->menu) { if ($panel_page->menu_tab_default) { $type = MENU_DEFAULT_LOCAL_TASK; } else if ($panel_page->menu_tab) { $type = MENU_LOCAL_TASK; } else { $type = MENU_NORMAL_ITEM; } } else { $type = MENU_CALLBACK; } return $type; } /** * Determine if the specified user has access to a panel. */ function panels_page_access($panel_page, $account = NULL) { if (!$account) { global $user; $account = $user; } // Administrator privileges if (user_access('access all panel-pages', $account)) { return TRUE; } // All views with an empty access setting are available to all roles. if (!$panel_page->access || !is_array($panel_page->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($panel_page->access, $roles[$account->uid]); } /** * Get the title for a panel page, given a context. * */ function panels_page_get_title($panel_page, $context = 'page', $default_title = NULL) { $title = _panels_page_get_title($panel_page, $context, $default_title); if (!empty($panel_page->keywords)) { $title = strtr($title, $panel_page->keywords); } return $title; } function _panels_page_get_title($panel_page, $op, $default_title) { if ($op == 'menu-parent' && $panel_page->menu_parent_title) { return $panel_page->menu_parent_title; } if (in_array($op, array('menu', 'menu-parent')) && $panel_page->menu_title) { return $panel_page->menu_title; } // Context has the highest priority if (!empty($panel_page->context)) { $title = NULL; foreach ($panel_page->context as $context) { if (empty($context->data)) { // Empty contexts can't provide titles continue; } if ($page_title = $context->get_page_title()) { $title = $page_title; } } if ($title) { return $title; } } // If no context returned a title use the display title configured in layout // settings if (!empty($panel_page->display->title)) { return $panel_page->display->title; } // Fall back on the panel default title if (!empty($panel_page->title)) { return $panel_page->title; } if (is_null($default_title)) { return t('No title'); } else { return $default_title; } } /** * Get the actual URL of a panel page given the passed in arguments. */ function panels_page_get_url($panel_page, $args = NULL) { if (!isset($args)) { $args = $panel_page->args; } $parts = explode('/', $panel_page->path); $url = array(); foreach ($parts as $part) { if ($part == '%') { $url[] = array_shift($args); } else { $url[] = $part; } } return implode('/', array_merge($url, $args)); } /** * Figure out if a panel is the current page; mostly useful in theming. */ function panels_page_get_current($page = NULL) { static $cache = NULL; if (isset($page)) { $cache = $page; } return $cache; } // --------------------------------------------------------------------------- // panel page administrative pages /** * Settings for panel pages. */ function panels_page_settings() { panels_load_include('common'); return drupal_get_form('panels_common_settings', 'panels_page'); } /** * Pass-through to admin.inc. */ function panels_page_passthru() { $args = func_get_args(); $callback = array_shift($args); panels_load_include('panels_page.admin', 'panels_page/'); panels_load_include('plugins'); return call_user_func_array($callback, $args); } function panels_move_menu_tabs($path, $tab) { global $_menu; // Get my menu item. $my_mid = menu_get_active_item(); // Get my parent menu item. $my_parent = $_menu['items'][$my_mid]['pid']; // Check the existing children to see if there is a default local task // already. if (!isset($_menu['items'][$my_parent]['children'])) { $_menu['items'][$my_parent]['children'] = array(); } $local_tasks = FALSE; if ($my_parent != 1) { // We do not run this loop if the parent is the top level menu item // since that way lies madness. foreach ($_menu['items'][$my_parent]['children'] as $child_mid) { if ($_menu['items'][$child_mid]['type'] & MENU_IS_LOCAL_TASK) { $local_tasks = TRUE; break; } } } if (!$local_tasks) { // Move the administrative items from the admin menu to here. $admin_item = $_menu['path index'][$path]; $_menu['items'][$my_mid]['children'] = $_menu['items'][$admin_item]['children']; } else { // But if we do have tabs, just add the admin item itself to the tabs. // Get the menu item we want to move us to. $path .= $tab; $admin_item = $_menu['path index'][$path]; $_menu['items'][$my_parent]['children'][] = $admin_item; $_menu['items'][$admin_item]['title'] = t('Edit panel'); $_menu['items'][$admin_item]['weight'] += 50; $_menu['items'][$admin_item]['type'] = MENU_LOCAL_TASK; } } // --------------------------------------------------------------------------- // view panels page /** * Page callback to view a panel page. */ function panels_page_view_page($panel_page, $admin) { if (!is_object($panel_page)) { $panel_page = panels_page_load($panel_page); } if (!$panel_page) { return drupal_not_found(); } panels_load_include('plugins'); $switchers = panels_get_switchers(); if ($switchers) { $list = array(); $candidates = array(); $result = db_query("SELECT name FROM {panels_page} WHERE switcher_name = '%s'", $panel_page->name); // get a list of all pages that might switch for this one while ($candidate = db_fetch_object($result)) { $list[] = $candidate->name; } // Add default panels that apply to the list as well foreach (panels_page_default_panels() as $page) { if ($page->switcher_name == $panel_page->name) { $candidates[$page->name] = $page; } } if ($list) { $candidates += (count($list) > 1) ? panels_page_load_all($list) : array(panels_page_load($list[0])); } if ($candidates) { // separate them based on switcher type $pages = array(); foreach ($candidates as $candidate) { $pages[$candidate->switcher_type][$candidate->name] = $candidate; } // go through switcher types and switch the first one that matches. foreach ($pages as $plugin => $candidates) { if ($page = panels_switcher_switch($plugin, 'panel_page', $panel_page->name, $candidates)) { $panel_page = $page; break; } } } } $args = func_get_args(); // remove the name. array_shift($args); // remove the admin flag. array_shift($args); $output = ''; if ($admin) { // Display an admin form to make it easy to set up arguments. panels_load_include('panels_page.admin', 'panels_page/'); $output .= drupal_get_form('panels_page_admin_view', $panel_page, $args); } else { // This piece of code goes deep into the menu system, finds the // administrative link for this panel and puts it between us and // whatever menu item is our parent. This causes the tabs to follow us // around without losing our previous menu context. panels_move_menu_tabs("admin/panels/panel-page/$panel_page->name", "/edit/general"); } if (empty($panel_page->context)) { $panel_page->context = array(); } if ($panel_page->arguments) { if (!panels_argument_load_contexts($panel_page->arguments, $panel_page->context, $args)) { if ($admin) { return $output . t('Page reports "Page not found" due to argument restrictions'); } else { return drupal_not_found(); } } } $panel_page->context = panels_context_load_contexts($panel_page, FALSE, $panel_page->context); $panel_page->keywords = panels_context_get_keywords($panel_page->context); // Figure out which display to use. $display_id = panels_argument_get_display($panel_page->arguments, $panel_page->context); panels_page_fetch_display($panel_page, $display_id); $display = $panel_page->display; // Figure out if these contexts include a form; will be NULL if there // isn't one, or the context if there is. $form = panels_context_get_form($panel_page->context); // This is the first point at which it is safe to add items to the display // as the argument handling, above, may choose which display is actually // used. $display->args = $args; $display->context = $panel_page->context; $display->keywords = $panel_page->keywords; $display->css_id = $panel_page->css_id; $display->owner = $panel_page; // unique id of this display's owner. $display->owner->id = $panel_page->name; $display->type = 'panel_page'; // Set this as 'current' so that other stuff can utilize it. panels_page_get_current($panel_page); if ($form) { $form->form['#theme'] = 'panels_page_render_form'; $form->form['#display'] = $display; $output .= drupal_render_form($form->form_id, $form->form); } else { $output .= panels_render_display($display); } // set title afterward to ensure title is retained. if ($output == NULL) { return drupal_not_found(); } if (!$display->hide_title && $title = filter_xss_admin(panels_page_get_title($panel_page, 'page', ''))) { drupal_set_title($title); } else { drupal_set_title(''); } if ($panel_page->css) { panels_load_include('panels_page.css_filter', 'panels_page/'); $css = panels_page_filter_css(panels_page_disassemble_css($panel_page->css)); // If the custom css didn't survive filtering, don't bother adding it. if (!empty($css)) { drupal_set_html_head("\n"); } } if ($panel_page->no_blocks) { print theme('page', $output, FALSE); } else { return $output; } } /** * Theme function to render our panel as a form. * * We need to do this so that the entire display is inside the form. */ function theme_panels_page_render_form($form) { $form['#children'] = panels_render_display($form['#display']); return theme('form', $form); } /** * Load a display into the 'current display' position, $panel_page->current. * * The family of panels_page_fetch*() functions are specifically dedicated to * retrieving a particular display and placing them in $panels_page->display, * which is the 'current' display upon which all other operations act. * via reference to its permanent home in the $panels_page object. The * permanent homes vary: * * -# For the primary display, that location is $panels_page->primary. * -# For alternate default displays, that location is in * $panels_page->alternates['defaults'][$did]. TODO this isn't true right now * -# For alternate non-default displays, that location is in * $panels_page->alternates['all'][$did]. * * The structure of this function family essentially means that no other * panels_page function should ever act on anything except $panel_page->display. * * * @param object $panel_page * @param string $id * A string of the format generated by panels_argument_get_display(). * @return NULL * This function has no return value, as all of its meaningful operations are * performed by reference. Look to the $panel_page object for changes. */ function panels_page_fetch_display(&$panel_page, $id = NULL) { // Redirect to the appropriate fetcher depending on whether $id is provided if (empty($id)) { panels_page_fetch_primary_display($panel_page); } else { panels_page_fetch_alternate_display($panel_page, $id); } } /** * Internal panels_page API function; directs the current display * ($panel_page->display) to the primary display ($panel_page->primary), * loading the primary display if necessary. * * @param object $panel_page */ function panels_page_fetch_primary_display(&$panel_page) { // Commented out is a more precise way of telling, but it's probably moot. // if (empty($panel_page->primary) || !is_a($panel_page->primary, 'panels_display')) { if (empty($panel_page->primary) || !is_object($panel_page->primary)) { $panel_page->primary = panels_load_display($panel_page->did); } $panel_page->display = &$panel_page->primary; $panel_page->current = 'primary'; } function panels_page_fetch_alternate_display(&$panel_page, $id) { // Get the metadata abpit the requested display. $info = $panel_page->displays[$id]; // Using the metadata, determine if the desired display exists. $requested_display_exists = panels_page_fetch_display_from_info($panel_page, $info, $id); if ($requested_display_exists) { // The requested display exists. Drop the $id into $current and bug out. $panel_page->current = $id; return; } // The requested display does not exist - determine the fallback display. We // save the $id into the object because we'll need it later for updating // the metadata if we export & save the default we fetch here. $panel_page->export = $id; // First, check for a default display for the context we're switching on, // and try to load that. if (!empty($info['default']) && !empty($panel_page->displays[$info['default']])) { // A default has been defined - figure out if it actually has a display // associated with it. if (!panels_page_fetch_display_from_info($panel_page, $panel_page->displays[$info['default']], $id)) { // No display is associated with the switched default either, so double // fall back to the primary display. Load it if it's not already. panels_page_fetch_primary_display($panel_page); } } // There's no default display defined for the context we're switching on, so // just use the primary display as the default. Load it if it's not already. else { panels_page_fetch_primary_display($panel_page); } } /** * Get a display based on whether it's already in code or needs to be loaded. */ function panels_page_fetch_display_from_info(&$panel_page, $info, $id) { // If the 'display' is set it's the result of an export/default if (isset($info['display'])) { $panel_page->display = $info['display']; return TRUE; } // If the $did is numeric, it corresponds to an existing display - load it. if (is_numeric($info['did'])) { $panel_page->display = panels_load_display($info['did']); return TRUE; } return FALSE; } // --------------------------------------------------------------------------- // Database functions /** * Fetch all panel pages in the system. * * This function does not cache. */ function panels_page_load_all($names = array(), $page_size = 0) { $pages = $dids = array(); $query = "SELECT * FROM {panels_page}"; if ($names) { $query .= " WHERE name IN (" . implode(', ', array_fill(0, sizeof($names), "'%s'")) . ")"; } if ($page_size) { $result = pager_query($query, $page_size, 0, $names); } else { $result = db_query($query, $names); } while ($page = db_fetch_object($result)) { $page->access = ($page->access ? explode(', ', $page->access) : array()); $page->arguments = (!empty($page->arguments)) ? unserialize($page->arguments) : array(); $page->displays = (!empty($page->displays)) ? unserialize($page->displays) : array(); $page->contexts = (!empty($page->contexts)) ? unserialize($page->contexts) : array(); $page->relationships = (!empty($page->relationships)) ? unserialize($page->relationships) : array(); $page->switcher_options = (!empty($page->switcher_options)) ? unserialize($page->switcher_options) : array(); $page->type = t('Local'); $pages[$page->name] = panels_page_sanitize($page); } $status = variable_get('panel_page_defaults', array()); foreach (panels_page_default_panels() as $page) { // Determine if default panel is enabled or disabled. if (isset($status[$page->name])) { $page->disabled = $status[$page->name]; } if (!empty($pages[$page->name])) { $pages[$page->name]->type = t('Overridden'); } else { $page->type = t('Default'); $page->primary = $page->display; $pages[$page->name] = $page; } } return $pages; } /** * Load a panel page. */ function panels_page_load($pid, $load_display = FALSE) { static $cache = array(); if (array_key_exists($pid, $cache)) { if ($load_display && empty($cache[$pid]->display)) { $cache[$pid]->display = panels_load_display($cache[$pid]->did); } return $cache[$pid]; } if (!is_numeric($pid)) { $where = "name = '%s'"; } else { $where = 'pid = %d'; } $page = db_fetch_object(db_query("SELECT * FROM {panels_page} WHERE $where", $pid)); if (!$page) { $defaults = panels_page_default_panels(); if (isset($defaults[$pid])) { $page = $cache[$pid] = $defaults[$pid]; $page->primary = $page->display; return $page; } return; } $page->access = ($page->access ? explode(', ', $page->access) : array()); $page->arguments = (!empty($page->arguments)) ? unserialize($page->arguments) : array(); $page->displays = (!empty($page->displays)) ? unserialize($page->displays) : array(); $page->contexts = (!empty($page->contexts)) ? unserialize($page->contexts) : array(); $page->relationships = (!empty($page->relationships)) ? unserialize($page->relationships) : array(); $page->switcher_options = (!empty($page->switcher_options)) ? unserialize($page->switcher_options) : array(); if ($load_display) { $page->display = panels_load_display($page->did); } $cache[$pid] = panels_page_sanitize($page); // Make sure that we've statically cached the loaded page for both possible // unique identifiers - $page->pid AND $page->name. $other_id = is_numeric($pid) || $pid == 'new' ? $page->name : $page->pid; $cache[$other_id] =& $cache[$pid]; return $cache[$pid]; } /** * A list of the fields used in the panel_page table. */ function panels_page_fields() { return array( "name" => "'%s'", "title" => "'%s'", "arguments" => "'%s'", "displays" => "'%s'", "contexts" => "'%s'", "relationships" => "'%s'", "access" => "'%s'", "path" => "'%s'", "css_id" => "'%s'", "css" => "'%s'", "no_blocks" => "%d", "switcher_type" => "'%s'", "switcher_name" => "'%s'", "switcher_options" => "'%s'", "menu" => "%d", "menu_tab" => "%d", "menu_tab_weight" => "%d", "menu_title" => "'%s'", "menu_tab_default" => "%d", "menu_tab_default_parent_type" => "'%s'", "menu_parent_title" => "'%s'", "menu_parent_tab_weight" => "%d", ); } /** * Sanitize a panel prior to saving it. */ function panels_page_sanitize(&$page) { foreach (array('arguments', 'displays', 'contexts', 'relationships', 'switcher_options') as $id) { if (!is_array($page->$id)) { $page->$id = array(); } } return $page; } /** * Delete a panel page and its associated displays. */ function panels_page_delete($panel_page) { // Delete the panel page. db_query("DELETE FROM {panels_page} WHERE pid = %d", $panel_page->pid); menu_rebuild(); // Delete the primary display. panels_delete_display($panel_page->did); // Delete all secondary displays. if (!empty($panel_page->displays)) { foreach ($panel_page->displays as $info) { if ($info['did'] !== 'new') { panels_delete_display($info['did']); } } } } /** * Export a panel page into PHP code for use in import. * * The code returned from can be used directly in panels_page_save(). */ function panels_page_export($panel_page, $prefix = '') { $output = ''; $fields = panels_page_fields(); $output .= $prefix . '$page = new stdClass()' . ";\n"; $output .= $prefix . '$page->pid = \'new\'' . ";\n"; foreach (array_keys($fields) as $field) { if (!isset($panel_page->$field) || in_array($field, array('displays', 'contexts', 'display'))) { continue; } $output .= $prefix . ' $page->' . $field . ' = ' . panels_var_export($panel_page->$field, ' ') . ";\n"; } // Export the contexts. $output .= $prefix . '$page->contexts = array()' . ";\n"; foreach ($panel_page->contexts as $id => $info) { $output .= $prefix . ' $page->contexts[\'' . $id . "'] = array(\n"; foreach ($info as $key => $value) { $output .= $prefix . " '$key' => " . panels_var_export($value, ' ') . ",\n"; } $output .= $prefix . " );\n"; } // Export the primary display $display = !empty($panel_page->display) ? $panel_page->display : panels_load_display($panel_page->did); $output .= panels_export_display($display, $prefix); $output .= $prefix . '$page->display = $display' . ";\n"; // Export all secondary displays $output .= $prefix . '$page->displays = array()' . ";\n"; foreach ($panel_page->displays as $did => $info) { $output .= $prefix . ' $page->displays[\'' . $did . "']['title'] = '" . check_plain($info['title']) . "';\n"; $output .= $prefix . ' $page->displays[\'' . $did . "']['argument_id'] = '" . check_plain($info['argument_id']) . "';\n"; $display = !empty($info['display']) ? $info['display'] : panels_load_display($info['did']); $output .= panels_export_display($display, $prefix . ' '); $output .= $prefix . ' $page->displays[\'' . $did . "']['display'] = \$display;\n"; } return $output; } /** * Get all 'default' panels. * * @ingroup HookInvokers */ function panels_page_default_panels() { $panels = module_invoke_all('default_panel_pages'); if (!is_array($panels)) { $panels = array(); } return $panels; } /** * Implementation of hook_panels_exportables(). */ function panels_page_panels_exportables($op = 'list', $panels = NULL, $name = 'foo') { static $all_panels = NULL; if ($op == 'list') { if (empty($all_panels)) { $all_panels = panels_page_load_all(); } foreach ($all_panels as $name => $panel) { $return[$name] = check_plain($name) . ' (' . check_plain(panels_page_get_title($panel)) . ')'; } return $return; } if ($op == 'export') { $code = "/**\n"; $code .= " * Implementation of hook_default_panel_pages()\n"; $code .= " */\n"; $code .= "function " . $name . "_default_panel_pages() {\n"; foreach ($panels as $panel => $truth) { $code .= panels_page_export($all_panels[$panel], ' '); $code .= ' $pages[\'' . check_plain($panel) . '\'] = $page;' . "\n\n\n"; } $code .= " return \$pages;\n"; $code .= "}\n"; return $code; } }