panels_page.module

Go to the documentation of this file.
00001 <?php
00002 // $Id: panels_page.module,v 1.1.2.78 2008/12/28 10:18:44 sdboyer Exp $
00003 
00004 
00005 /**
00006  * @file panels_page.module
00007  *
00008  * This module is the primary implementation pf the Panels API.
00009  * It provides Panel pages that are used to create full page layouts.
00010  *
00011  * Code exclusively used on admin pages can be found in panels_page.admin.inc.
00012  */
00013 
00014 /**
00015  * Implementation of hook_help().
00016  */
00017 function panels_page_help($section = '') {
00018   switch ($section) {
00019     case 'admin/panels/panel-page':
00020     case 'admin/panels/panel-page/list':
00021       $output = '<p>';
00022       $output .= t('You may peruse a list of your current panels layouts and edit them, or click add to create a new page.');
00023       $output .= '</p>';
00024       break;
00025 
00026     case 'admin/panels/panel-page/add':
00027       $output = '<p>';
00028       $output .= t('Choose a layout for your new page from the list below.');
00029       $output .= '</p>';
00030       break;
00031   }
00032   return $output;
00033 }
00034 
00035 /**
00036  * Implementation of hook_perm().
00037  */
00038 function panels_page_perm() {
00039   return array('create panel-pages', 'access all panel-pages');
00040 }
00041 
00042 /**
00043  * Implementation of hook_menu().
00044  */
00045 function panels_page_menu($may_cache) {
00046   $items = array();
00047   $panels = panels_page_load_all();
00048   if ($may_cache) {
00049     $access = user_access('create panel-pages');
00050     $items[] = array(
00051       'path' => 'admin/panels/panel-page',
00052       'title' => t('Panel pages'),
00053       'access' => $access,
00054       'callback' => 'panels_page_passthru',
00055       'callback arguments' => array('panels_page_list_page'),
00056       'description' => t('Create and administer panel-pages (complex layout pages with URLs).'),
00057     );
00058     $items[] = array(
00059       'path' => 'admin/panels/panel-page/list',
00060       'title' => t('List'),
00061       'access' => $access,
00062       'callback' => 'panels_page_passthru',
00063       'callback arguments' => array('panels_page_list_page'),
00064       'weight' => -10,
00065       'type' => MENU_DEFAULT_LOCAL_TASK,
00066     );
00067     $items[] = array(
00068       'path' => 'admin/panels/panel-page/add',
00069       'title' => t('Add'),
00070       'access' => $access,
00071       'callback' => 'panels_page_passthru',
00072       'callback arguments' => array('panels_page_add_page'),
00073       'type' => MENU_LOCAL_TASK,
00074     );
00075     $items[] = array(
00076       'path' => 'admin/panels/panel-page/import',
00077       'title' => t('Import'),
00078       'access' => $access,
00079       'callback' => 'panels_page_passthru',
00080       'callback arguments' => array('panels_page_import_page'),
00081       'type' => MENU_LOCAL_TASK,
00082     );
00083     $items[] = array(
00084       'path' => 'admin/panels/panel-page/settings',
00085       'title' => t('Settings'),
00086       'access' => $access,
00087       'callback' => 'panels_page_settings',
00088       'weight' => 5,
00089       'type' => MENU_LOCAL_TASK,
00090     );
00091     $items[] = array(
00092       'path' => 'admin/panels/panel-page/disable',
00093       'access' => $access,
00094       'callback' => 'panels_page_passthru',
00095       'callback arguments' => array('panels_page_disable_page'),
00096       'weight' => -1,
00097       'type' => MENU_CALLBACK,
00098     );
00099     $items[] = array(
00100       'path' => 'admin/panels/panel-page/enable',
00101       'access' => $access,
00102       'callback' => 'panels_page_passthru',
00103       'callback arguments' => array('panels_page_enable_page'),
00104       'weight' => -1,
00105       'type' => MENU_CALLBACK,
00106     );
00107 
00108     // Get all panels and, if enabled, create menu items.
00109     foreach ($panels as $panel_page) {
00110       if (empty($panel_page->disabled)) {
00111         // Only create menu items based on the path if it's not a variable path.
00112         if (strpos($panel_page->path, '%') === FALSE) {
00113           _panels_page_create_menu_item($items, $panel_page, $panel_page->path, array($panel_page->name, FALSE));
00114           // DEBUG: Above is now creating only the basic menu item, not the admin items.
00115         }
00116         panels_page_admin_menu_items($items, 'admin/panels/panel-page/' . $panel_page->name, $panel_page);
00117       }
00118     }
00119   }
00120   else {
00121     // Look for panels with variable arguments.
00122     // Build an array of $urls because 'real' URLs will take precedence over
00123     // argument filled URLs
00124     $urls = array();
00125     foreach ($panels as $panel_page) {
00126       $url[$panel_page->path] = TRUE;
00127     }
00128 
00129     $plugins_loaded = FALSE;
00130     foreach ($panels as $panel_page) {
00131       if (!empty($panel_page->disabled)) {
00132         continue;
00133       }
00134       if (strpos($panel_page->path, '%') !== FALSE) {
00135         $path = explode('/', $panel_page->path);
00136 
00137         // First pass:
00138         // Check if the current path sufficiently matches $panel_page->path,
00139         // which means: all fixed parts that come before the last %-wildcard
00140         // need to match, while trailing fixed parts don't matter.
00141         // We start with the last part and take up checking after reaching a %.
00142         $check = FALSE;
00143         foreach (array_reverse($path, TRUE) as $id => $chunk) {
00144           if ($chunk == '%') {
00145             $check = TRUE;
00146             continue;
00147           }
00148           if ($check && $chunk != arg($id)) {
00149             // Skip outer foreach loop to continue with the next $panel_page.
00150             continue 2;
00151           }
00152         }
00153 
00154         $args = array($panel_page, FALSE);
00155 
00156         // Second pass:
00157         $argument = reset($panel_page->arguments); // Get first argument.
00158         foreach ($path as $id => $chunk) {
00159           if ($chunk != '%') {
00160             continue;
00161           }
00162           // For arguments that are embedded in the URL, we require the
00163           // argument handler to return a context, if there is an argument handler.
00164           if ($argument) {
00165             // Try to avoid loading the plugins code unless necessary.
00166             if (!$plugins_loaded) {
00167               panels_load_include('plugins');
00168               $plugins_loaded = TRUE;
00169             }
00170             $context = panels_argument_get_context($argument, arg($id));
00171             if (!$context) {
00172               break;
00173             }
00174             $panel_page->context[panels_argument_context_id($argument)] = $context;
00175           }
00176           $path[$id] = arg($id);
00177           $args[] = arg($id);
00178           $argument = next($panel_page->arguments); // Get next argument.
00179         }
00180         _panels_page_create_menu_item($items, $panel_page, implode('/', $path), $args);
00181         // DEBUG: Above is now creating only the basic menu item, not the admin items.
00182       }
00183     }
00184   }
00185   return $items;
00186 }
00187 
00188 /**
00189  * Helper function to add a menu item for a panel.
00190  */
00191 function panels_page_admin_menu_items(&$items, $base, $page) {
00192   $access = user_access('create panel-pages');
00193 
00194   $items[] = array(
00195     'path' => $base,
00196     'title' => t('Preview'),
00197     'access' => $access,
00198     'callback' => 'panels_page_view_page',
00199     'callback arguments' => array($page->name, TRUE),
00200     'weight' => -10,
00201     'type' => MENU_CALLBACK,
00202   );
00203 
00204   $items[] = array(
00205     'path' => $base . '/preview',
00206     'title' => t('Preview'),
00207     'access' => $access,
00208     'callback' => 'panels_page_view_page',
00209     'callback arguments' => array($page->name, TRUE),
00210     'weight' => -10,
00211     'type' => MENU_DEFAULT_LOCAL_TASK,
00212   );
00213 
00214   // Set up for the 'default' display.
00215   $items[] = array(
00216     'path' => $base . '/edit/layout',
00217     'title' => t('Layout'),
00218     'access' => $access,
00219     'callback' => 'panels_page_passthru',
00220     'callback arguments' => array('panels_page_edit_layout', $page->name),
00221     'weight' => -9,
00222     'type' => MENU_LOCAL_TASK,
00223   );
00224 
00225   $items[] = array(
00226     'path' => $base . '/edit/general',
00227     'title' => t('Settings'),
00228     'access' => $access,
00229     'callback' => 'panels_page_passthru',
00230     'callback arguments' => array('panels_page_edit', $page->name),
00231     'weight' => -7,
00232     'type' => MENU_LOCAL_TASK,
00233   );
00234 
00235   $items[] = array(
00236     'path' => $base . '/edit/settings',
00237     'title' => t('Layout settings'),
00238     'access' => $access,
00239     'callback' => 'panels_page_passthru',
00240     'callback arguments' => array('panels_page_edit_layout_settings', $page->name, NULL),
00241     'weight' => -5,
00242     'type' => MENU_LOCAL_TASK,
00243   );
00244 
00245   $items[] = array(
00246     'path' => $base . '/edit/advanced',
00247     'title' => t('Advanced'),
00248     'access' => $access,
00249     'callback' => 'panels_page_passthru',
00250     'callback arguments' => array('panels_page_edit_advanced', $page->name),
00251     'weight' => -3,
00252     'type' => MENU_LOCAL_TASK,
00253   );
00254 
00255   $items[] = array(
00256     'path' => $base . '/edit/context',
00257     'title' => t('Context'),
00258     'access' => $access,
00259     'callback' => 'panels_page_passthru',
00260     'callback arguments' => array('panels_page_edit_context', $page->name),
00261     'weight' => -2,
00262     'type' => MENU_LOCAL_TASK,
00263   );
00264 
00265   $items[] = array(
00266     'path' => $base . '/edit/content',
00267     'title' => t('Content'),
00268     'access' => $access,
00269     'callback' => 'panels_page_passthru',
00270     'callback arguments' => array('panels_page_edit_content', $page->name),
00271     'weight' => -1,
00272     'type' => MENU_LOCAL_TASK,
00273   );
00274 
00275   $items[] = array(
00276     'path' => $base . '/edit/layout/default',
00277     'title' => t('Default'),
00278     'access' => $access,
00279     'callback' => 'panels_page_passthru',
00280     'callback arguments' => array('panels_page_edit_layout', $page->name),
00281     'weight' => -1,
00282     'type' => MENU_DEFAULT_LOCAL_TASK,
00283   );
00284 
00285   $items[] = array(
00286     'path' => $base . '/edit/settings/default',
00287     'title' => t('Default'),
00288     'access' => $access,
00289     'callback' => 'panels_page_passthru',
00290     'callback arguments' => array('panels_page_edit_layout_settings', $page->name, NULL),
00291     'weight' => -1,
00292     'type' => MENU_DEFAULT_LOCAL_TASK,
00293   );
00294 
00295   $items[] = array(
00296     'path' => $base . '/edit/content/default',
00297     'title' => t('Default'),
00298     'access' => $access,
00299     'callback' => 'panels_page_passthru',
00300     'callback arguments' => array('panels_page_edit_content', $page->name),
00301     'weight' => -1,
00302     'type' => MENU_DEFAULT_LOCAL_TASK,
00303   );
00304 
00305   if (!empty($page->displays)) {
00306     foreach ($page->displays as $display_id => $info) {
00307       $items[] = array(
00308         'path' => $base . '/edit/layout/' . $display_id,
00309         'title' => $info['title'],
00310         'access' => $access,
00311         'callback' => 'panels_page_passthru',
00312         'callback arguments' => array('panels_page_edit_layout', $page->name, $display_id),
00313         'type' => MENU_LOCAL_TASK,
00314       );
00315 
00316       $items[] = array(
00317         'path' => $base . '/edit/settings/' . $display_id,
00318         'title' => $info['title'],
00319         'access' => $access,
00320         'callback' => 'panels_page_passthru',
00321         'callback arguments' => array('panels_page_edit_layout_settings', $page->name, $display_id),
00322         'type' => MENU_LOCAL_TASK,
00323       );
00324 
00325       $items[] = array(
00326         'path' => $base . '/edit/content/' . $display_id,
00327         'title' => $info['title'],
00328         'access' => $access,
00329         'callback' => 'panels_page_passthru',
00330         'callback arguments' => array('panels_page_edit_content', $page->name, $display_id),
00331         'type' => MENU_LOCAL_TASK,
00332       );
00333     }
00334   }
00335 
00336   $items[] = array(
00337     'path' => $base . '/export',
00338     'title' => t('Export'),
00339     'access' => $access,
00340     'callback' => 'panels_page_passthru',
00341     'callback arguments' => array('drupal_get_form', 'panels_page_edit_export', $page->name),
00342     'weight' => 0,
00343     'type' => MENU_LOCAL_TASK,
00344   );
00345   $items[] = array(
00346     'path' => $base . '/delete',
00347     'title' => t('Delete panel page'),
00348     'access' => $access,
00349     'callback' => 'panels_page_passthru',
00350     'callback arguments' => array('drupal_get_form', 'panels_page_delete_confirm', $page->name),
00351     'type' => MENU_CALLBACK,
00352   );
00353 }
00354 
00355 /**
00356  * Create a menu item for a panel page.
00357  */
00358 function _panels_page_create_menu_item(&$items, $panel_page, $path, $args = array()) {
00359   $access = panels_page_access($panel_page);
00360   $title  = filter_xss_admin(panels_page_get_title($panel_page, 'menu'));
00361   $type   = _panels_page_menu_type($panel_page);
00362 
00363   if ($type == MENU_LOCAL_TASK || $type == MENU_DEFAULT_LOCAL_TASK) {
00364     $weight = $panel_page->menu_tab_weight;
00365   }
00366   $items[] = _panels_page_menu_item($path, $title, $panel_page, $args, $access, $type, isset($weight) ? $weight : NULL);
00367 
00368   if ($type == MENU_DEFAULT_LOCAL_TASK && dirname($path) && dirname($path) != '.') {
00369     switch ($panel_page->menu_tab_default_parent_type) {
00370       case 'tab':
00371         $parent_type = MENU_LOCAL_TASK;
00372         break;
00373 
00374       case 'normal':
00375         $parent_type = MENU_NORMAL_ITEM;
00376         break;
00377 
00378       default:
00379       case 'existing':
00380         $parent_type = 0;
00381         break;
00382     }
00383     if ($parent_type) {
00384       $title   = filter_xss_admin(panels_page_get_title($panel_page, 'menu-parent'));
00385       $weight  = $panel_page->menu_parent_tab_weight;
00386       $items[] = _panels_page_menu_item(dirname($path), $title, $panel_page, $args, $access, $parent_type, $weight);
00387     }
00388   }
00389 }
00390 
00391 /**
00392  * Helper function to create a menu item for a panel.
00393  */
00394 function _panels_page_menu_item($path, $title, $panel_page, $args, $access, $type, $weight = NULL) {
00395   $retval = array('path' => $path,
00396     'title' => $title,
00397     'callback' => 'panels_page_view_page',
00398     'callback arguments' => $args,
00399     'access' => user_access('access content') && $access,
00400     'type' => $type,
00401   );
00402   if ($weight !== NULL) {
00403     $retval['weight'] = $weight;
00404   }
00405   return $retval;
00406 }
00407 
00408 /**
00409  * Determine what menu type a panel needs to use.
00410  */
00411 function _panels_page_menu_type($panel_page) {
00412   if ($panel_page->menu) {
00413     if ($panel_page->menu_tab_default) {
00414       $type = MENU_DEFAULT_LOCAL_TASK;
00415     }
00416     else if ($panel_page->menu_tab) {
00417       $type = MENU_LOCAL_TASK;
00418     }
00419     else {
00420       $type = MENU_NORMAL_ITEM;
00421     }
00422   }
00423   else {
00424     $type = MENU_CALLBACK;
00425   }
00426   return $type;
00427 }
00428 
00429 /**
00430  * Determine if the specified user has access to a panel.
00431  */
00432 function panels_page_access($panel_page, $account = NULL) {
00433   if (!$account) {
00434     global $user;
00435     $account = $user;
00436   }
00437 
00438   // Administrator privileges
00439   if (user_access('access all panel-pages', $account)) {
00440     return TRUE;
00441   }
00442 
00443   // All views with an empty access setting are available to all roles.
00444   if (!$panel_page->access || !is_array($panel_page->access)) {
00445     return TRUE;
00446   }
00447 
00448   // Otherwise, check roles
00449   static $roles = array();
00450   if (!isset($roles[$account->uid])) {
00451     $roles[$account->uid] = array_keys($account->roles);
00452     $roles[$account->uid][] = $account->uid ? DRUPAL_AUTHENTICATED_RID : DRUPAL_ANONYMOUS_RID;
00453   }
00454 
00455   return array_intersect($panel_page->access, $roles[$account->uid]);
00456 }
00457 
00458 /**
00459  * Get the title for a panel page, given a context.
00460  *
00461  */
00462 function panels_page_get_title($panel_page, $context = 'page', $default_title = NULL) {
00463   $title = _panels_page_get_title($panel_page, $context, $default_title);
00464   if (!empty($panel_page->keywords)) {
00465     $title = strtr($title, $panel_page->keywords);
00466   }
00467   return $title;
00468 }
00469 
00470 function _panels_page_get_title($panel_page, $op, $default_title) {
00471   if ($op == 'menu-parent' && $panel_page->menu_parent_title) {
00472     return $panel_page->menu_parent_title;
00473   }
00474 
00475   if (in_array($op, array('menu', 'menu-parent')) && $panel_page->menu_title) {
00476     return $panel_page->menu_title;
00477   }
00478 
00479   // Context has the highest priority
00480   if (!empty($panel_page->context)) {
00481     $title = NULL;
00482     foreach ($panel_page->context as $context) {
00483       if (empty($context->data)) {
00484         // Empty contexts can't provide titles
00485         continue;
00486       }
00487       if ($page_title = $context->get_page_title()) {
00488         $title = $page_title;
00489       }
00490     }
00491     if ($title) {
00492       return $title;
00493     }
00494   }
00495 
00496   // If no context returned a title use the display title configured in layout
00497   // settings
00498   if (!empty($panel_page->display->title)) {
00499     return $panel_page->display->title;
00500   }
00501 
00502   // Fall back on the panel default title
00503   if (!empty($panel_page->title)) {
00504     return $panel_page->title;
00505   }
00506 
00507   if (is_null($default_title)) {
00508     return t('No title');
00509   }
00510   else {
00511     return $default_title;
00512   }
00513 }
00514 
00515 /**
00516  * Get the actual URL of a panel page given the passed in arguments.
00517  */
00518 function panels_page_get_url($panel_page, $args = NULL) {
00519   if (!isset($args)) {
00520     $args = $panel_page->args;
00521   }
00522 
00523   $parts = explode('/', $panel_page->path);
00524   $url = array();
00525   foreach ($parts as $part) {
00526     if ($part == '%') {
00527       $url[] = array_shift($args);
00528     }
00529     else {
00530       $url[] = $part;
00531     }
00532   }
00533   return implode('/', array_merge($url, $args));
00534 }
00535 
00536 /**
00537  * Figure out if a panel is the current page; mostly useful in theming.
00538  */
00539 function panels_page_get_current($page = NULL) {
00540   static $cache = NULL;
00541   if (isset($page)) {
00542     $cache = $page;
00543   }
00544 
00545   return $cache;
00546 }
00547 
00548 // ---------------------------------------------------------------------------
00549 // panel page administrative pages
00550 
00551 /**
00552  * Settings for panel pages.
00553  */
00554 function panels_page_settings() {
00555   panels_load_include('common');
00556   return drupal_get_form('panels_common_settings', 'panels_page');
00557 }
00558 
00559 /**
00560  * Pass-through to admin.inc.
00561  */
00562 function panels_page_passthru() {
00563   $args = func_get_args();
00564   $callback = array_shift($args);
00565 
00566   panels_load_include('panels_page.admin', 'panels_page/');
00567   panels_load_include('plugins');
00568   return call_user_func_array($callback, $args);
00569 }
00570 
00571 function panels_move_menu_tabs($path, $tab) {
00572   global $_menu;
00573 
00574   // Get my menu item.
00575   $my_mid = menu_get_active_item();
00576 
00577   // Get my parent menu item.
00578   $my_parent = $_menu['items'][$my_mid]['pid'];
00579 
00580   // Check the existing children to see if there is a default local task
00581   // already.
00582   if (!isset($_menu['items'][$my_parent]['children'])) {
00583     $_menu['items'][$my_parent]['children'] = array();
00584   }
00585   $local_tasks = FALSE;
00586 
00587   if ($my_parent != 1) {
00588     // We do not run this loop if the parent is the top level menu item
00589     // since that way lies madness.
00590     foreach ($_menu['items'][$my_parent]['children'] as $child_mid) {
00591       if ($_menu['items'][$child_mid]['type'] & MENU_IS_LOCAL_TASK) {
00592         $local_tasks = TRUE;
00593         break;
00594       }
00595     }
00596   }
00597 
00598   if (!$local_tasks) {
00599     // Move the administrative items from the admin menu to here.
00600     $admin_item = $_menu['path index'][$path];
00601     $_menu['items'][$my_mid]['children'] = $_menu['items'][$admin_item]['children'];
00602   }
00603   else {
00604     // But if we do have tabs, just add the admin item itself to the tabs.
00605     // Get the menu item we want to move us to.
00606     $path .= $tab;
00607     $admin_item = $_menu['path index'][$path];
00608 
00609     $_menu['items'][$my_parent]['children'][] = $admin_item;
00610     $_menu['items'][$admin_item]['title'] = t('Edit panel');
00611     $_menu['items'][$admin_item]['weight'] += 50;
00612     $_menu['items'][$admin_item]['type'] = MENU_LOCAL_TASK;
00613   }
00614 }
00615 
00616 // ---------------------------------------------------------------------------
00617 // view panels page
00618 
00619 /**
00620  * Page callback to view a panel page.
00621  */
00622 function panels_page_view_page($panel_page, $admin) {
00623   if (!is_object($panel_page)) {
00624     $panel_page = panels_page_load($panel_page);
00625   }
00626   if (!$panel_page) {
00627     return drupal_not_found();
00628   }
00629 
00630   panels_load_include('plugins');
00631 
00632   $switchers = panels_get_switchers();
00633   if ($switchers) {
00634     $list = array();
00635     $candidates = array();
00636     $result = db_query("SELECT name FROM {panels_page} WHERE switcher_name = '%s'", $panel_page->name);
00637     // get a list of all pages that might switch for this one
00638     while ($candidate = db_fetch_object($result)) {
00639       $list[] = $candidate->name;
00640     }
00641     // Add default panels that apply to the list as well
00642     foreach (panels_page_default_panels() as $page) {
00643       if ($page->switcher_name == $panel_page->name) {
00644         $candidates[$page->name] = $page;
00645       }
00646     }
00647 
00648     if ($list) {
00649       $candidates += (count($list) > 1) ? panels_page_load_all($list) : array(panels_page_load($list[0]));
00650     }
00651 
00652     if ($candidates) {
00653       // separate them based on switcher type
00654       $pages = array();
00655       foreach ($candidates as $candidate) {
00656         $pages[$candidate->switcher_type][$candidate->name] = $candidate;
00657       }
00658 
00659       // go through switcher types and switch the first one that matches.
00660       foreach ($pages as $plugin => $candidates) {
00661         if ($page = panels_switcher_switch($plugin, 'panel_page', $panel_page->name, $candidates)) {
00662           $panel_page = $page;
00663           break;
00664         }
00665       }
00666     }
00667   }
00668 
00669   $args = func_get_args();
00670   // remove the name.
00671   array_shift($args);
00672   // remove the admin flag.
00673   array_shift($args);
00674 
00675   $output = '';
00676   if ($admin) {
00677     // Display an admin form to make it easy to set up arguments.
00678     panels_load_include('panels_page.admin', 'panels_page/');
00679     $output .= drupal_get_form('panels_page_admin_view', $panel_page, $args);
00680   }
00681   else {
00682     // This piece of code goes deep into the menu system, finds the
00683     // administrative link for this panel and puts it between us and
00684     // whatever menu item is our parent. This causes the tabs to follow us
00685     // around without losing our previous menu context.
00686     panels_move_menu_tabs("admin/panels/panel-page/$panel_page->name", "/edit/general");
00687   }
00688 
00689   if (empty($panel_page->context)) {
00690     $panel_page->context = array();
00691   }
00692 
00693   if ($panel_page->arguments) {
00694     if (!panels_argument_load_contexts($panel_page->arguments, $panel_page->context, $args)) {
00695       if ($admin) {
00696         return $output . t('Page reports "Page not found" due to argument restrictions');
00697       }
00698       else {
00699         return drupal_not_found();
00700       }
00701     }
00702   }
00703 
00704   $panel_page->context = panels_context_load_contexts($panel_page, FALSE, $panel_page->context);
00705   $panel_page->keywords = panels_context_get_keywords($panel_page->context);
00706 
00707   // Figure out which display to use.
00708   $display_id = panels_argument_get_display($panel_page->arguments, $panel_page->context);
00709 
00710   panels_page_fetch_display($panel_page, $display_id);
00711   $display = $panel_page->display;
00712 
00713   // Figure out if these contexts include a form; will be NULL if there
00714   // isn't one, or the context if there is.
00715   $form = panels_context_get_form($panel_page->context);
00716 
00717   // This is the first point at which it is safe to add items to the display
00718   // as the argument handling, above, may choose which display is actually
00719   // used.
00720   $display->args     = $args;
00721   $display->context  = $panel_page->context;
00722   $display->keywords = $panel_page->keywords;
00723   $display->css_id   = $panel_page->css_id;
00724   $display->owner    = $panel_page;
00725   // unique id of this display's owner.
00726   $display->owner->id = $panel_page->name;
00727   $display->type = 'panel_page';
00728 
00729   // Set this as 'current' so that other stuff can utilize it.
00730   panels_page_get_current($panel_page);
00731 
00732   if ($form) {
00733     $form->form['#theme'] = 'panels_page_render_form';
00734     $form->form['#display'] = $display;
00735     $output .= drupal_render_form($form->form_id, $form->form);
00736   }
00737   else {
00738     $output .= panels_render_display($display);
00739   }
00740 
00741   // set title afterward to ensure title is retained.
00742   if ($output == NULL) {
00743     return drupal_not_found();
00744   }
00745 
00746   if (!$display->hide_title && $title = filter_xss_admin(panels_page_get_title($panel_page, 'page', ''))) {
00747     drupal_set_title($title);
00748   }
00749   else {
00750     drupal_set_title('');
00751   }
00752 
00753   if ($panel_page->css) {
00754     panels_load_include('panels_page.css_filter', 'panels_page/');
00755     $css = panels_page_filter_css(panels_page_disassemble_css($panel_page->css));
00756     // If the custom css didn't survive filtering, don't bother adding it.
00757     if (!empty($css)) {
00758       drupal_set_html_head("<style type=\"text/css\" media=\"all\">" . panels_page_compress_css($css) . "</style>\n");
00759     }
00760   }
00761   if ($panel_page->no_blocks) {
00762     print theme('page', $output, FALSE);
00763   }
00764   else {
00765     return $output;
00766   }
00767 }
00768 
00769 /**
00770  * Theme function to render our panel as a form.
00771  *
00772  * We need to do this so that the entire display is inside the form.
00773  */
00774 function theme_panels_page_render_form($form) {
00775   $form['#children'] = panels_render_display($form['#display']);
00776   return theme('form', $form);
00777 }
00778 
00779 /**
00780  * Load a display into the 'current display' position, $panel_page->current.
00781  *
00782  * The family of panels_page_fetch*() functions are specifically dedicated to
00783  * retrieving a particular display and placing them in $panels_page->display,
00784  * which is the 'current' display upon which all other operations act.
00785  * via reference to its permanent home in the $panels_page object. The
00786  * permanent homes vary:
00787  *
00788  *   -# For the primary display, that location is $panels_page->primary.
00789  *   -# For alternate default displays, that location is in
00790  *      $panels_page->alternates['defaults'][$did]. TODO this isn't true right now
00791  *   -# For alternate non-default displays, that location is in
00792  *      $panels_page->alternates['all'][$did].
00793  *
00794  * The structure of this function family essentially means that no other
00795  * panels_page function should ever act on anything except $panel_page->display.
00796  *
00797  *
00798  * @param object $panel_page
00799  * @param string $id
00800  *   A string of the format generated by panels_argument_get_display().
00801  * @return NULL
00802  *   This function has no return value, as all of its meaningful operations are
00803  *   performed by reference. Look to the $panel_page object for changes.
00804  */
00805 function panels_page_fetch_display(&$panel_page, $id = NULL) {
00806   // Redirect to the appropriate fetcher depending on whether $id is provided
00807   if (empty($id)) {
00808     panels_page_fetch_primary_display($panel_page);
00809   }
00810   else {
00811     panels_page_fetch_alternate_display($panel_page, $id);
00812   }
00813 }
00814 
00815 /**
00816  * Internal panels_page API function; directs the current display
00817  * ($panel_page->display) to the primary display ($panel_page->primary),
00818  * loading the primary display if necessary.
00819  *
00820  * @param object $panel_page
00821  */
00822 function panels_page_fetch_primary_display(&$panel_page) {
00823   // Commented out is a more precise way of telling, but it's probably moot.
00824   // if (empty($panel_page->primary) || !is_a($panel_page->primary, 'panels_display')) {
00825   if (empty($panel_page->primary) || !is_object($panel_page->primary)) {
00826     $panel_page->primary = panels_load_display($panel_page->did);
00827   }
00828   $panel_page->display = &$panel_page->primary;
00829   $panel_page->current = 'primary';
00830 }
00831 
00832 function panels_page_fetch_alternate_display(&$panel_page, $id) {
00833   // Get the metadata abpit the requested display.
00834   $info = $panel_page->displays[$id];
00835   // Using the metadata, determine if the desired display exists.
00836   $requested_display_exists = panels_page_fetch_display_from_info($panel_page, $info, $id);
00837   if ($requested_display_exists) {
00838     // The requested display exists. Drop the $id into $current and bug out.
00839     $panel_page->current = $id;
00840     return;
00841   }
00842 
00843   // The requested display does not exist - determine the fallback display. We
00844   // save the $id into the object because we'll need it later for updating
00845   // the metadata if we export & save the default we fetch here.
00846   $panel_page->export = $id;
00847   // First, check for a default display for the context we're switching on,
00848   // and try to load that.
00849   if (!empty($info['default']) && !empty($panel_page->displays[$info['default']])) {
00850     // A default has been defined - figure out if it actually has a display
00851     // associated with it.
00852     if (!panels_page_fetch_display_from_info($panel_page, $panel_page->displays[$info['default']], $id)) {
00853       // No display is associated with the switched default either, so double
00854       // fall back to the primary display. Load it if it's not already.
00855       panels_page_fetch_primary_display($panel_page);
00856     }
00857   }
00858   // There's no default display defined for the context we're switching on, so
00859   // just use the primary display as the default. Load it if it's not already.
00860   else {
00861     panels_page_fetch_primary_display($panel_page);
00862   }
00863 }
00864 
00865 /**
00866  * Get a display based on whether it's already in code or needs to be loaded.
00867  */
00868 function panels_page_fetch_display_from_info(&$panel_page, $info, $id) {
00869   // If the 'display' is set it's the result of an export/default
00870   if (isset($info['display'])) {
00871     $panel_page->display = $info['display'];
00872     return TRUE;
00873   }
00874 
00875   // If the $did is numeric, it corresponds to an existing display - load it.
00876   if (is_numeric($info['did'])) {
00877     $panel_page->display = panels_load_display($info['did']);
00878     return TRUE;
00879   }
00880 
00881   return FALSE;
00882 }
00883 
00884 // ---------------------------------------------------------------------------
00885 // Database functions
00886 
00887 /**
00888  * Fetch all panel pages in the system.
00889  *
00890  * This function does not cache.
00891  */
00892 function panels_page_load_all($names = array(), $page_size = 0) {
00893   $pages = $dids = array();
00894   $query = "SELECT * FROM {panels_page}";
00895 
00896   if ($names) {
00897     $query .= " WHERE name IN (" . implode(', ', array_fill(0, sizeof($names), "'%s'")) . ")";
00898   }
00899 
00900   if ($page_size) {
00901     $result = pager_query($query, $page_size, 0, $names);
00902   }
00903   else {
00904     $result = db_query($query, $names);
00905   }
00906 
00907   while ($page = db_fetch_object($result)) {
00908     $page->access = ($page->access ? explode(', ', $page->access) : array());
00909     $page->arguments = (!empty($page->arguments)) ? unserialize($page->arguments) : array();
00910     $page->displays = (!empty($page->displays)) ? unserialize($page->displays) : array();
00911     $page->contexts = (!empty($page->contexts)) ? unserialize($page->contexts) : array();
00912     $page->relationships = (!empty($page->relationships)) ? unserialize($page->relationships) : array();
00913     $page->switcher_options = (!empty($page->switcher_options)) ? unserialize($page->switcher_options) : array();
00914 
00915     $page->type = t('Local');
00916     $pages[$page->name] = panels_page_sanitize($page);
00917   }
00918 
00919   $status = variable_get('panel_page_defaults', array());
00920   foreach (panels_page_default_panels() as $page) {
00921     // Determine if default panel is enabled or disabled.
00922     if (isset($status[$page->name])) {
00923       $page->disabled = $status[$page->name];
00924     }
00925 
00926     if (!empty($pages[$page->name])) {
00927       $pages[$page->name]->type = t('Overridden');
00928     }
00929     else {
00930       $page->type = t('Default');
00931       $page->primary = $page->display;
00932       $pages[$page->name] = $page;
00933     }
00934   }
00935   return $pages;
00936 }
00937 
00938 /**
00939  * Load a panel page.
00940  */
00941 function panels_page_load($pid, $load_display = FALSE) {
00942   static $cache = array();
00943 
00944   if (array_key_exists($pid, $cache)) {
00945     if ($load_display && empty($cache[$pid]->display)) {
00946       $cache[$pid]->display = panels_load_display($cache[$pid]->did);
00947     }
00948     return $cache[$pid];
00949   }
00950 
00951   if (!is_numeric($pid)) {
00952     $where = "name = '%s'";
00953   }
00954   else {
00955     $where = 'pid = %d';
00956   }
00957   $page = db_fetch_object(db_query("SELECT * FROM {panels_page} WHERE $where", $pid));
00958   if (!$page) {
00959     $defaults = panels_page_default_panels();
00960     if (isset($defaults[$pid])) {
00961       $page = $cache[$pid] = $defaults[$pid];
00962       $page->primary = $page->display;
00963       return $page;
00964     }
00965     return;
00966   }
00967 
00968   $page->access           = ($page->access ? explode(', ', $page->access) : array());
00969   $page->arguments        = (!empty($page->arguments)) ? unserialize($page->arguments) : array();
00970   $page->displays         = (!empty($page->displays)) ? unserialize($page->displays) : array();
00971   $page->contexts         = (!empty($page->contexts)) ? unserialize($page->contexts) : array();
00972   $page->relationships    = (!empty($page->relationships)) ? unserialize($page->relationships) : array();
00973   $page->switcher_options = (!empty($page->switcher_options)) ? unserialize($page->switcher_options) : array();
00974 
00975   if ($load_display) {
00976     $page->display = panels_load_display($page->did);
00977   }
00978 
00979   $cache[$pid] = panels_page_sanitize($page);
00980   // Make sure that we've statically cached the loaded page for both possible
00981   // unique identifiers - $page->pid AND $page->name.
00982   $other_id = is_numeric($pid) || $pid == 'new' ? $page->name : $page->pid;
00983   $cache[$other_id] =& $cache[$pid];
00984 
00985 
00986   return $cache[$pid];
00987 }
00988 
00989 /**
00990  * A list of the fields used in the panel_page table.
00991  */
00992 function panels_page_fields() {
00993   return array(
00994     "name" => "'%s'",
00995     "title" => "'%s'",
00996     "arguments" => "'%s'",
00997     "displays" => "'%s'",
00998     "contexts" => "'%s'",
00999     "relationships" => "'%s'",
01000     "access" => "'%s'",
01001     "path" => "'%s'",
01002     "css_id" => "'%s'",
01003     "css" => "'%s'",
01004     "no_blocks" => "%d",
01005     "switcher_type" => "'%s'",
01006     "switcher_name" => "'%s'",
01007     "switcher_options" => "'%s'",
01008     "menu" => "%d",
01009     "menu_tab" => "%d",
01010     "menu_tab_weight" => "%d",
01011     "menu_title" => "'%s'",
01012     "menu_tab_default" => "%d",
01013     "menu_tab_default_parent_type" => "'%s'",
01014     "menu_parent_title" => "'%s'",
01015     "menu_parent_tab_weight" => "%d",
01016   );
01017 }
01018 
01019 /**
01020  * Sanitize a panel prior to saving it.
01021  */
01022 function panels_page_sanitize(&$page) {
01023   foreach (array('arguments', 'displays', 'contexts', 'relationships', 'switcher_options') as $id) {
01024     if (!is_array($page->$id)) {
01025       $page->$id = array();
01026     }
01027   }
01028 
01029   return $page;
01030 }
01031 
01032 /**
01033  * Delete a panel page and its associated displays.
01034  */
01035 function panels_page_delete($panel_page) {
01036   // Delete the panel page.
01037   db_query("DELETE FROM {panels_page} WHERE pid = %d", $panel_page->pid);
01038   menu_rebuild();
01039 
01040   // Delete the primary display.
01041   panels_delete_display($panel_page->did);
01042 
01043   // Delete all secondary displays.
01044   if (!empty($panel_page->displays)) {
01045     foreach ($panel_page->displays as $info) {
01046       if ($info['did'] !== 'new') {
01047         panels_delete_display($info['did']);
01048       }
01049     }
01050   }
01051 }
01052 
01053 /**
01054  * Export a panel page into PHP code for use in import.
01055  *
01056  * The code returned from can be used directly in panels_page_save().
01057  */
01058 function panels_page_export($panel_page, $prefix = '') {
01059   $output = '';
01060   $fields = panels_page_fields();
01061   $output .= $prefix . '$page = new stdClass()' . ";\n";
01062   $output .= $prefix . '$page->pid = \'new\'' . ";\n";
01063   foreach (array_keys($fields) as $field) {
01064     if (!isset($panel_page->$field) || in_array($field, array('displays', 'contexts', 'display'))) {
01065       continue;
01066     }
01067     $output .= $prefix . '  $page->' . $field . ' = ' . panels_var_export($panel_page->$field, '  ') . ";\n";
01068   }
01069   // Export the contexts.
01070   $output .= $prefix . '$page->contexts = array()' . ";\n";
01071   foreach ($panel_page->contexts as $id => $info) {
01072     $output .= $prefix . '  $page->contexts[\'' . $id . "'] = array(\n";
01073     foreach ($info as $key => $value) {
01074       $output .= $prefix . "    '$key' => " . panels_var_export($value, '    ') . ",\n";
01075     }
01076     $output .= $prefix . "  );\n";
01077   }
01078 
01079   // Export the primary display
01080   $display = !empty($panel_page->display) ? $panel_page->display : panels_load_display($panel_page->did);
01081   $output .= panels_export_display($display, $prefix);
01082   $output .= $prefix . '$page->display = $display' . ";\n";
01083 
01084   // Export all secondary displays
01085   $output .= $prefix . '$page->displays = array()' . ";\n";
01086   foreach ($panel_page->displays as $did => $info) {
01087     $output .= $prefix . '  $page->displays[\'' . $did . "']['title'] = '" . check_plain($info['title']) . "';\n";
01088     $output .= $prefix . '  $page->displays[\'' . $did . "']['argument_id'] = '" . check_plain($info['argument_id']) . "';\n";
01089     $display = !empty($info['display']) ? $info['display'] : panels_load_display($info['did']);
01090     $output .= panels_export_display($display, $prefix . '    ');
01091     $output .= $prefix . '  $page->displays[\'' . $did . "']['display'] =  \$display;\n";
01092   }
01093   return $output;
01094 }
01095 
01096 /**
01097  * Get all 'default' panels.
01098  *
01099  * @ingroup HookInvokers
01100  */
01101 function panels_page_default_panels() {
01102   $panels = module_invoke_all('default_panel_pages');
01103   if (!is_array($panels)) {
01104     $panels = array();
01105   }
01106 
01107   return $panels;
01108 }
01109 
01110 /**
01111  * Implementation of hook_panels_exportables().
01112  */
01113 function panels_page_panels_exportables($op = 'list', $panels = NULL, $name = 'foo') {
01114   static $all_panels = NULL;
01115   if ($op == 'list') {
01116     if (empty($all_panels)) {
01117       $all_panels = panels_page_load_all();
01118     }
01119 
01120     foreach ($all_panels as $name => $panel) {
01121       $return[$name] = check_plain($name) . ' (' . check_plain(panels_page_get_title($panel)) . ')';
01122     }
01123     return $return;
01124   }
01125 
01126   if ($op == 'export') {
01127     $code = "/**\n";
01128     $code .= " * Implementation of hook_default_panel_pages()\n";
01129     $code .= " */\n";
01130     $code .= "function " . $name . "_default_panel_pages() {\n";
01131     foreach ($panels as $panel => $truth) {
01132       $code .= panels_page_export($all_panels[$panel], '  ');
01133       $code .= '  $pages[\'' . check_plain($panel) . '\'] = $page;' . "\n\n\n";
01134     }
01135     $code .= "  return \$pages;\n";
01136     $code .= "}\n";
01137     return $code;
01138   }
01139 }
01140 

Generated on Thu Jul 29 05:00:15 2010 for Panels 2 by  doxygen 1.5.6