b2evolution PHP Cross Reference Blogging Systems

Source: /skins_adm/_adminUI_general.class.php - 1445 lines - 41415 bytes - Summary - Text - Print

Description: This file implements the Admin UI class. Admin skins should derive from this class and override {@link get_template()} for example. This file is part of the b2evolution/evocms project - {@link http://b2evolution.net/}. See also {@link http://sourceforge.net/projects/evocms/}.

   1  <?php
   2  /**
   3   * This file implements the Admin UI class.
   4   * Admin skins should derive from this class and override {@link get_template()}
   5   * for example.
   6   *
   7   * This file is part of the b2evolution/evocms project - {@link http://b2evolution.net/}.
   8   * See also {@link http://sourceforge.net/projects/evocms/}.
   9   *
  10   * @copyright (c)2003-2014 by Francois Planque - {@link http://fplanque.com/}.
  11   * Parts of this file are copyright (c)2005 by Daniel HAHLER - {@link http://thequod.de/contact}.
  12   *
  13   * @license http://b2evolution.net/about/license.html GNU General Public License (GPL)
  14   *
  15   * {@internal Open Source relicensing agreement:
  16   * Daniel HAHLER grants Francois PLANQUE the right to license
  17   * Daniel HAHLER's contributions to this file and the b2evolution project
  18   * under any OSI approved OSS license (http://www.opensource.org/licenses/).
  19   * }}
  20   *
  21   * @package admin
  22   *
  23   * {@internal Below is a list of authors who have contributed to design/coding of this file: }}
  24   * @author blueyed: Daniel HAHLER
  25   * @author fplanque: Francois PLANQUE.
  26   *
  27   * @todo dh> Refactor to allow easier contributions!
  28   *
  29   * @version $Id: _adminUI_general.class.php 6136 2014-03-08 07:59:48Z manuel $
  30   */
  31  if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
  32  
  33  
  34  load_class( '_core/ui/_menu.class.php', 'Menu' );
  35  
  36  
  37  /**
  38   * The general Admin UI class. It provides functions to handle the UI part of the
  39   * Backoffice.
  40   *
  41   * Admin skins should derive from this class and override {@link get_template()}
  42   * for example.
  43   *
  44   * @package admin
  45   * @todo CODE DOCUMENTATION!!!
  46   */
  47  class AdminUI_general extends Menu
  48  {
  49      /**
  50       * Visual path seperator (used in html title, ..)
  51       *
  52       * @var string
  53       */
  54      var $pathSeparator = ' &rsaquo; ';
  55  
  56      /*-------------------------------------------------------------------*/
  57      /*- The members below should not get overridden in a derived class. -*/
  58  
  59      /**
  60       * The path of the current selected menu entry.
  61       * Array of strings.
  62       * The top level entry is at position 0. Selected submenu entries follow.
  63       *
  64       * Use {@link get_path()} or {@link get_path_range()} to access it.
  65       * Use {@link set_path()}, {@link append_path_level()} or {@link set_path_level()} to set it.
  66       *
  67       * @access protected
  68       * @var array
  69       */
  70      var $path = array();
  71  
  72      /**
  73       * The properties of the path entries.
  74       * Numbered Array of arrays.
  75       * The top level entry is at position 0. Selected submenu entries follow.
  76       *
  77       * Use {@link get_prop_for_path()} or {@link get_properties_for_path()} to access it
  78       * Use {@link set_path()}, {@link append_path_level()} or {@link set_path_level()} to set it.
  79       *
  80       * @access protected
  81       * @var array
  82       */
  83      var $pathProps = array();
  84  
  85      /**
  86       * The explicit title for the page.
  87       * @var string
  88       */
  89      var $title;
  90  
  91      /**
  92       * The explicit title for the titlearea (<h1>).
  93       * @var string
  94       */
  95      var $title_titlearea;
  96      var $title_titlearea_appendix = '';
  97  
  98      /**
  99       * Collection List buttons: title for 'all' button
 100       * @var string
 101       */
 102      var $coll_list_all_title = NULL;
 103      /**
 104       * Collection List buttons: url for 'all' button
 105       * @var string
 106       */
 107      var $coll_list_all_url = '';
 108      /**
 109       * Collection List buttons: permission name to test on to decide wether or not to display buttons
 110       * @var string
 111       */
 112      var $coll_list_permname = NULL;
 113      /**
 114       * Collection List buttons: minimum level required to display button
 115       * @var mixed
 116       */
 117      var $coll_list_permlevel = 1;
 118      /**
 119       * Collection List buttons: params of the url used for the buttons
 120       * @var array
 121       */
 122      var $coll_list_url_params = array();
 123      /**
 124       * Collection List buttons: javascript to execute on click of a button
 125       * @var string
 126       */
 127      var $coll_list_onclick = NULL;
 128  
 129  
 130      /**
 131       * Bread crumb path
 132       *
 133       * Note: These are not real breadcrumbs. It's just "so to speak" for a hierarchical path.
 134       */
 135      var $breadcrumbpath = array();
 136  
 137  
 138      /**
 139       * Titles of bread crumb paths
 140       *
 141       * Used to build a html <title> tag
 142       */
 143      var $breadcrumb_titles = array();
 144  
 145      /**
 146       * Constructor.
 147       */
 148  	function AdminUI_general()
 149      {
 150          global $mode; // TODO: make it a real property
 151          global $htsrv_url, $baseurl;
 152  
 153          $this->mode = $mode;
 154  
 155          $this->init_templates();
 156      }
 157  
 158  
 159      /**
 160       * This function should init the templates - like adding Javascript through the {@link add_headline()} method.
 161       */
 162  	function init_templates()
 163      {
 164          require_js( '#jquery#', 'rsc_url' );
 165          require_js( 'jquery/jquery.raty.min.js', 'rsc_url' );
 166      }
 167  
 168      /**
 169      * Note: These are not real breadcrumbs. It's just "so to speak" for a hierarchical path.
 170      *
 171      */
 172  	function breadcrumbpath_init( $add_blog = true )
 173      {
 174          global $Blog;
 175          $this->breadcrumbpath_add( T_('Dashboard'), '?ctrl=dashboard&amp;blog=0' );
 176          if( $add_blog && isset($Blog) )
 177          {
 178              $this->breadcrumbpath_add( $Blog->dget('shortname'), '?ctrl=dashboard&amp;blog=$blog$' );
 179          }
 180      }
 181  
 182      /**
 183      * Note: These are not real breadcrumbs. It's just "so to speak" for a hierarchical path.
 184      *
 185      * @param mixed $text
 186      * @param mixed $url
 187      */
 188  	function breadcrumbpath_add( $text, $url, $help = NULL )
 189      {
 190          global $Blog, $current_User;
 191  
 192          $blog_ID = isset($Blog) ? $Blog->ID : 0;
 193          $url = str_replace( '$blog$', $blog_ID, $url );
 194  
 195          $html = $text;
 196          if( $current_User->check_perm( 'admin', 'normal' ) )
 197          {
 198              $html = '<a href="'.$url.'">'.$text.'</a>';
 199          }
 200  
 201          if( !empty($help) )
 202          {
 203              $html .= ' <abbr title="'.$help.'">?</abbr>';
 204          }
 205  
 206          $this->breadcrumbpath[] = $html;
 207          $this->breadcrumb_titles[] = strip_tags( $text );
 208      }
 209  
 210  
 211  	function breadcrumbpath_get_html()
 212      {
 213          $r = '';
 214  
 215          if( $count = count($this->breadcrumbpath) )
 216          {
 217              $r = '<div class="breadcrumbpath">&bull; <strong>'.T_('You are here').':</strong> ';
 218  
 219              for( $i=0; $i<$count-1; $i++ )
 220              {
 221                  $r .= $this->breadcrumbpath[$i].' &gt; ';
 222              }
 223  
 224              $r .= '<strong>'.$this->breadcrumbpath[$i].'</strong>';
 225  
 226              $r .= "</div>\n";
 227          }
 228  
 229          return $r;
 230      }
 231  
 232      /**
 233       * Add menu entries to the beginning of the list for given path.
 234       *
 235       * @param NULL|string|array The path to add the entries to.
 236       * @param array Menu entries to add (key (string) => entry (array)).
 237       * @uses add_menu_entries()
 238       */
 239  	function unshift_menu_entries( $path, $entries )
 240      {
 241          // Get a reference to the node in the menu list.
 242          $node = & $this->get_node_by_path( $path, true );
 243  
 244          $node['entries'] = array_reverse( $node['entries'] );
 245  
 246          $this->add_menu_entries( $path, $entries );
 247  
 248          $node['entries'] = array_reverse( $node['entries'] );
 249      }
 250  
 251  
 252      /**
 253       * Get the <title> of the page.
 254       *
 255       * This is either {@link $title} or will be constructed from title/text properties
 256       * of the path entries.
 257       *
 258       * @param boolean If true, the fallback will be in reversed order
 259       * @return string
 260       */
 261  	function get_title( $reversedDefault = false )
 262      {
 263          if( isset( $this->title ) )
 264          {    // Explicit title has been set:
 265              return $this->title;
 266          }
 267          else
 268          {    // Fallback: implode title/text properties of the path
 269              /*$titles = $this->get_properties_for_path( $this->path, array( 'title', 'text' ) );
 270              if( $reversedDefault )
 271              { // We have asked for reverse order of the path elements:
 272                  $titles = array_reverse($titles);
 273              }*/
 274              $titles = $this->breadcrumb_titles;
 275              if( count( $titles ) > 1 )
 276              {    // Remove 'Dashboard' text from the title
 277                  array_shift( $titles );
 278              }
 279              return implode( ' &gt; ', $titles );
 280          }
 281      }
 282  
 283  
 284      /**
 285       * Get the title for the titlearea (<h1>).
 286       *
 287       * This is the current path in the site structure
 288       *
 289       * @return string
 290       */
 291  	function get_title_for_titlearea()
 292      {
 293          if( ! isset( $this->title_titlearea ) )
 294          { // Construct path:
 295              $titles = array();
 296              foreach( $this->path as $i => $lPath )
 297              {
 298                  if( false !== ($title_text = $this->get_prop_for_path( $i, array( 'title', 'text' ) )) )
 299                  {
 300                      $titles[] = '<a href="'.$this->get_prop_for_path( $i, array( 'href' ) ).'">'.$title_text.'</a>';
 301                  }
 302              }
 303  
 304              $this->title_titlearea = implode( $this->pathSeparator, $titles );
 305          }
 306  
 307          return $this->title_titlearea.$this->title_titlearea_appendix;
 308      }
 309  
 310  
 311      /**
 312       * Append a string at the end of the existing titlearea.
 313       *
 314       * We actually keep the appended stuff separate from the main title, because the main title
 315       * might in some occasions not be known immediately.
 316       *
 317       * @param string What to append to the titlearea
 318       */
 319  	function append_to_titlearea( $string )
 320      {
 321          $this->title_titlearea_appendix .= $this->pathSeparator.$string;
 322      }
 323  
 324  
 325      /**
 326       * Get the title for HTML <title> tag.
 327       *
 328       * If no explicit title has been specified, auto construct one from path.
 329       *
 330       * @return string
 331       */
 332  	function get_html_title()
 333      {
 334          global $app_shortname;
 335  
 336          if( $htmltitle = $this->get_prop_for_node( $this->path, array( 'htmltitle' ) ) )
 337          {    // Explicit htmltitle set:
 338              $r = $htmltitle;
 339          }
 340          else
 341          {    // No explicit title set, construct Title from path
 342              $r = $this->get_title();
 343          }
 344          $r .= ' &ndash; '.$app_shortname;
 345  
 346          return $r;
 347      }
 348  
 349  
 350      /**
 351       * Get a list of properties for a given path for a set of property names to check.
 352       * The result is a list of properties for each node down the path.
 353       *
 354       * The property names must be given in $prop_by_ref, ordered by preference.
 355       *
 356       * @param string|array The path. See {@link get_node_by_path()}.
 357       * @param array Alternative names of the property to receive (ordered by priority).
 358       * @return array List of the properties.
 359       */
 360  	function get_properties_for_path( $path, $prop_by_pref )
 361      {
 362          if( !is_array($path) )
 363          {
 364              $path = array( $path );
 365          }
 366          $r = array();
 367  
 368          $prevPath = array();
 369          foreach( $path as $i => $lPath )
 370          {
 371              if( false !== ($prop = $this->get_prop_for_path( $i, $prop_by_pref )) )
 372              {
 373                  $r[] = $prop;
 374              }
 375  
 376              $prevPath[] = $lPath;
 377          }
 378  
 379          return $r;
 380      }
 381  
 382  
 383      /**
 384       * Get a property of a node, given by path.
 385       *
 386       * @param string|array The path. See {@link get_node_by_path()}.
 387       * @param array Alternative names of the property to receive (ordered by priority).
 388       * @return mixed|false False if property is not set for the node, otherwise its value.
 389       */
 390  	function get_prop_for_node( $path, $prop_by_pref )
 391      {
 392          $node = & $this->get_node_by_path( $path );
 393  
 394          foreach( $prop_by_pref as $lProp )
 395          {
 396              if( isset($node[$lProp]) )
 397              {
 398                  return $node[$lProp];
 399              }
 400          }
 401  
 402          return false;
 403      }
 404  
 405  
 406      /**
 407       * Get a property for a specific path entry.
 408       *
 409       * @param int The numeric index of the path entry to query (0 is first).
 410       * @param array A list of properties to check, ordered by priority.
 411       * @return mixed|false The first found property or false if it does not exist
 412       */
 413  	function get_prop_for_path( $depth, $prop_by_pref )
 414      {
 415          if( $pathWithProps = $this->get_path( $depth, true ) )
 416          {
 417              foreach( $prop_by_pref as $lProp )
 418              {
 419                  if( isset($pathWithProps['props'][$lProp]) )
 420                  {
 421                      // echo "<br>path depth $depth property $lProp = ".$pathWithProps['props'][$lProp];
 422                      return $pathWithProps['props'][$lProp];
 423                  }
 424              }
 425          }
 426  
 427          return false;
 428      }
 429  
 430  
 431      /**
 432       * Display doctype + <head>...</head> section
 433       */
 434  	function disp_html_head()
 435      {
 436          if( is_ajax_content() )
 437          {    // Don't display this content on AJAX request
 438              return;
 439          }
 440  
 441          global $adminskins_path;
 442          require $adminskins_path.'_html_header.inc.php';
 443      }
 444  
 445  
 446      /**
 447       * Dsiplay the top of the HTML <body>...
 448       *
 449       * Typically includes title, menu, messages, etc.
 450       *
 451       * @param boolean Whether or not to display messages.
 452       */
 453  	function disp_body_top( $display_messages = true )
 454      {
 455          if( is_ajax_content() )
 456          {    // Don't display this content on AJAX request
 457              return;
 458          }
 459  
 460          global $skins_path, $mode;
 461  
 462          /**
 463           * @var Hit
 464           */
 465          global $Hit;
 466  
 467          // #body_win and .body_firefox (for example) can be used to customize CSS per plaform/browser
 468          echo '<body id="body_'.$Hit->get_agent_platform().'" class="body_'.$Hit->get_agent_name().'">'."\n";
 469  
 470          if( ! empty( $mode ) )
 471          {
 472              global $Messages;
 473  
 474              $mode = preg_replace( '~[^a-z]~', '', $mode );    // sanitize
 475              echo '<div id="'.$mode.'_wrapper">';
 476  
 477              if( $display_messages )
 478              { // Display info & error messages
 479                  $Messages->display( NULL, NULL, true, 'action_messages' );
 480              }
 481              return;
 482          }
 483  
 484          $skin_wrapper_class = 'skin_wrapper';
 485          if( is_logged_in() )
 486          { // user is logged in
 487              if( $this->get_show_evobar() )
 488              { // show evobar options is enabled for this admin skin
 489                  require $skins_path.'_toolbar.inc.php';
 490                  $skin_wrapper_class = $skin_wrapper_class.'_loggedin';
 491              }
 492          }
 493          else
 494          { // user is not logged in
 495              require $skins_path.'_toolbar.inc.php';
 496              $skin_wrapper_class = $skin_wrapper_class.'_anonymous';
 497          }
 498  
 499          echo "\n";
 500          echo '<div id="skin_wrapper" class="'.$skin_wrapper_class.'">';
 501  
 502          echo "\n<!-- Start of skin_wrapper -->\n";
 503  
 504          echo $this->get_body_top();
 505      }
 506  
 507  
 508      /**
 509       * Display body bottom, debug info and close </html>
 510       */
 511  	function disp_global_footer()
 512      {
 513          if( is_ajax_content() )
 514          {    // Don't display this content on AJAX request
 515              return;
 516          }
 517  
 518          global $adminskins_path, $mode;
 519  
 520          require $adminskins_path.'_html_footer.inc.php';
 521      }
 522  
 523  
 524      /**
 525       * Display the start of a payload block
 526       *
 527       * Note: it is possible to display several payload blocks on a single page.
 528       *       The first block uses the "sub" template, the others "block".
 529       *
 530       * @see disp_payload_end()
 531       */
 532  	function disp_payload_begin()
 533      {
 534          if( is_ajax_content() )
 535          {    // Don't display this content on AJAX request
 536              return;
 537          }
 538  
 539          global $Plugins;
 540  
 541          if( empty($this->displayed_sub_begin) )
 542          {    // We haven't displayed sub menus yet (tabs):
 543              $Plugins->trigger_event( 'AdminBeginPayload' );
 544  
 545              // Display submenu (this also opens a div class="panelblock" or class="panelblocktabs")
 546  
 547              //echo ' disp_submenu-BEGIN ';
 548              $path0 = $this->get_path(0);
 549              $r = $this->get_html_menu( $path0, 'sub' );
 550  
 551              echo $this->replace_vars( $r );
 552              //echo ' disp_submenu-END ';
 553  
 554              // Show 3rd level menu for settings tab
 555              $path1 = $this->get_path(1);
 556              echo $this->get_html_menu( array($path0, $path1), 'menu3' );
 557  
 558  
 559              $this->displayed_sub_begin = 1;
 560          }
 561          else
 562          {
 563              $template = $this->get_template( 'block' );
 564  
 565              echo $template['begin'];
 566          }
 567      }
 568  
 569  
 570      /**
 571       * Display the end of a payload block
 572       *
 573       * Note: it is possible to display several payload blocks on a single page.
 574       *       The first block uses the "sub" template, the others "block".
 575       * @see disp_payload_begin()
 576       */
 577  	function disp_payload_end()
 578      {
 579          if( is_ajax_content() )
 580          {    // Don't display this content on AJAX request
 581              return;
 582          }
 583  
 584          if( empty($this->displayed_sub_end) )
 585          {
 586              $name = 'sub';
 587              $this->displayed_sub_end = 1;
 588          }
 589          else
 590          {
 591              $name = 'block';
 592          }
 593  
 594          $template = $this->get_template( $name );
 595  
 596          echo $template['end'];
 597      }
 598  
 599  
 600      /**
 601       * Display a view
 602       *
 603       * Note: doing the require inside of a function has the side effect of forcing the view
 604       * to declare any global object it wants to use. This can be a little tedious but on the
 605       * other hand it has the advantage of clearly showing what objects are used and makes it
 606       * easier to audit the views in order to determine if they include more business logic
 607       * than they ought to.
 608       *
 609       * @param string
 610       * @param array params to be used in the view (optional)
 611       */
 612  	function disp_view( $view_name, $view_params = array() )
 613      {
 614          global $inc_path;
 615  
 616          // THESE ARE THE GLOBALS WE WANT TO MAKE AVAILABLE TO ALL VIEWS:
 617          global $action;
 618          global $ctrl;
 619  
 620          global $DB;    // Note: not sure it's agood idea to let the views hit on the db...
 621  
 622          global $current_User;
 623  
 624  
 625          require $inc_path.$view_name;
 626      }
 627  
 628  
 629      /**
 630       * Set params for blog list.
 631       *
 632       * @param string name of required permission needed to display the blog in the list
 633       * @param string level of required permission needed to display the blog in the list
 634       * @param string Url format string for elements, with %d for blog number.
 635       * @param string Title for "all" button
 636       * @param string URL for "all" button
 637       * @param string onclick attribute format string, with %s for blog number. (NOTE: %s so that we can use this.value when selected through list)
 638       */
 639  	function set_coll_list_params( $permname = 'blog_ismember', $permlevel = 1, $url_params = array(),
 640                              $all_title = NULL, $all_url = '', $onclick = NULL )
 641      {
 642          $this->coll_list_all_title = $all_title;
 643          $this->coll_list_all_url = $all_url;
 644          $this->coll_list_permname = $permname;
 645          $this->coll_list_permlevel = $permlevel;
 646          $this->coll_list_url_params = $url_params;
 647          $this->coll_list_onclick = $onclick;
 648      }
 649  
 650  
 651      /**
 652       * Returns list of buttons for available Collections (aka Blogs) to work on.
 653       *
 654       * @return string HTML
 655       */
 656  	function get_bloglist_buttons( $title = '' )
 657      {
 658          global $current_User, $blog, $pagenow;
 659  
 660          $max_buttons = 7;
 661  
 662          if( empty( $this->coll_list_permname ) )
 663          {    // We have not requested a list of blogs to be displayed
 664              return;
 665          }
 666  
 667          // Prepare url params:
 668          $url_params = '?';
 669          $form_params = '';
 670          foreach( $this->coll_list_url_params as $name => $value )
 671          {
 672              $url_params .= $name.'='.$value.'&amp;';
 673              $form_params .= '<input type="hidden" name="'.$name.'" value="'.$value.'" />';
 674          }
 675  
 676          $template = $this->get_template( 'CollectionList' );
 677  
 678          $BlogCache = & get_BlogCache();
 679  
 680          $blog_array = $BlogCache->load_user_blogs( $this->coll_list_permname, $this->coll_list_permlevel );
 681  
 682  
 683          $buttons = '';
 684          $select_options = '';
 685          $count = 0;
 686          $current_is_displayed = false;
 687  
 688          foreach( $blog_array as $l_blog_ID )
 689          {    // Loop through all blogs that match the requested permission:
 690  
 691              $l_Blog = & $BlogCache->get_by_ID( $l_blog_ID );
 692  
 693              $count++;
 694  
 695              if( $count < $max_buttons
 696                      || ($current_is_displayed && $count == $max_buttons )
 697                      || $l_blog_ID == $blog )
 698              {    // Not too many yet OR current blog, add blog as a button:
 699                  $buttons .= $template[ $l_blog_ID == $blog ? 'beforeEachSel' : 'beforeEach' ];
 700  
 701                  $buttons .= '<a href="'.$url_params.'blog='.$l_blog_ID
 702                              .'" class="'.( $l_blog_ID == $blog ? 'CurrentBlog' : 'OtherBlog' ).'"';
 703  
 704                  if( !is_null($this->coll_list_onclick) )
 705                  {    // We want to include an onclick attribute:
 706                      $buttons .= ' onclick="'.sprintf( $this->coll_list_onclick, $l_blog_ID ).'"';
 707                  }
 708  
 709                  $buttons .= '>'.$l_Blog->dget( 'shortname', 'htmlbody' ).'</a> ';
 710  
 711                  if( $l_blog_ID == $blog )
 712                  {
 713                      $current_is_displayed = true;
 714                      $buttons .= $template['afterEachSel'];
 715                  }
 716                  else
 717                  {
 718                      $buttons .= $template['afterEach'];
 719                  }
 720              }
 721  
 722              // Add item select list:
 723              $select_options .= '<option value="'.$l_blog_ID.'"';
 724              if( $l_blog_ID == $blog )
 725              {
 726                  $select_options .= ' selected="selected"';
 727              }
 728              $select_options .= '>'.$l_Blog->dget( 'shortname', 'formvalue' ).'</option>';
 729          }
 730  
 731          $r = $template['before'];
 732  
 733          $r .= $title;
 734  
 735          if( !empty($this->coll_list_all_title) )
 736          {    // We want to add an "all" button
 737              $r .= $template[ $blog == 0 ? 'beforeEachSel' : 'beforeEach' ];
 738              $r .= '<a href="'.$this->coll_list_all_url
 739                          .'" class="'.( $blog == 0 ? 'CurrentBlog' : 'OtherBlog' ).'">'
 740                          .$this->coll_list_all_title.'</a> ';
 741              $r .= $template[ $blog == 0 ? 'afterEachSel' : 'afterEach' ];
 742          }
 743  
 744          $r .= $template['buttons_start'];
 745          $r .= $buttons;
 746          $r .= $template['buttons_end'];
 747  
 748  
 749          $r .= $template['select_start'];
 750          if( $count > $max_buttons )
 751          {    // We could not display all blogs as buttons
 752              $r .= '<form action="'.$pagenow.'" method="get">';
 753              $r .= $form_params;
 754              $r .= '<select name="blog" onchange="';
 755              if( empty( $this->coll_list_onclick ) )
 756              {    // Just submit...
 757                  $r .= 'this.form.submit();';
 758              }
 759              else
 760              {
 761                  $r .= sprintf( $this->coll_list_onclick, 'this.value' );
 762              }
 763              $r .= '">'.$select_options.'</select>';
 764              $r .= '<noscript><input type="submit" value="Go" /></noscript></form>';
 765          }
 766          $r .= $template['select_end'];
 767  
 768  
 769          $r .= $template['after'];
 770  
 771          return $r;
 772      }
 773  
 774  
 775      /**
 776       * Get a template by name.
 777       *
 778       * This is a method (and not a member array) to allow dynamic generation and T_()
 779       *
 780       * @param string Name of the template ('main', 'sub')
 781       * @param integer Nesting level (start at 0)
 782       * @return array Associative array which defines layout and optionally properties.
 783       */
 784  	function get_template( $name, $level = 0 )
 785      {
 786          switch( $name )
 787          {
 788              case 'main':
 789                  return array(
 790                      'before' => '<div id="mainmenu"><ul>',
 791                      'after' => '</ul></div>',
 792                      'beforeEach' => '<li>',
 793                      'afterEach' => '</li>',
 794                      'beforeEachSel' => '<li class="current">',
 795                      'afterEachSel' => '</li>',
 796                      'beforeEachSelWithSub' => '<li class="parent">',
 797                      'afterEachSelWithSub' => '</li>',
 798                      '_props' => array(
 799                          /**
 800                           * @todo Move to new skin (recurse for subentries if an entry is selected)
 801                          'recurseSelected' => true,
 802                          */
 803                      ),
 804                  );
 805                  break;
 806  
 807  
 808              case 'sub':
 809                  // a payload block with embedded submenu
 810                  return array(
 811                          'before' => '<div class="pt">'
 812                              ."\n".'<ul class="hack">'
 813                              ."\n<li><!-- Yes, this empty UL is needed! It's a DOUBLE hack for correct CSS display --></li>"
 814                              // TODO: this hack MAY NOT be needed when not using pixels instead of decimal ems or exs in the CSS
 815                              ."\n</ul>"
 816                              ."\n".'<div class="panelblocktabs">$top_block$'
 817                              ."\n".'<ul class="tabs">',
 818                          'after' => "</ul>\n"
 819                              .'<span style="float:right">$global_icons$</span>'
 820                              ."</div>\n</div>"
 821                              ."\n".'<div class="tabbedpanelblock">',
 822                          'empty' => '<div class="panelblock">',
 823                          'beforeEach' => '<li>',
 824                          'afterEach'  => '</li>',
 825                          'beforeEachSel' => '<li class="current">',
 826                          'afterEachSel' => '</li>',
 827                          'end' => '</div>', // used to end payload block that opened submenu
 828                      );
 829  
 830  
 831              case 'menu3':
 832                  // level 3 submenu:
 833                  return array(
 834                              'before' => '<div class="menu3">',
 835                              'after' => '</div>',
 836                              'empty' => '',
 837                              'beforeEach' => '<span class="option3">',
 838                              'afterEach'  => '</span>',
 839                              'beforeEachSel' => '<span class="current">',
 840                              'afterEachSel' => '</span>',
 841                          );
 842  
 843  
 844              case 'block':
 845                  // an additional payload block, anywhere after the one with the submenu. Used by disp_payload_begin()/disp_payload_end()
 846                  return array(
 847                          'begin' => '<div class="panelblock">',
 848                          'end' => "\n</div>",
 849                      );
 850  
 851  
 852              case 'CollectionList':
 853                  // Template for a list of Collections (Blogs)
 854                  return array(
 855                          'before' => '<div id="coll_list"><ul>',
 856                          'after' => '</ul></div>',
 857                          'buttons_start' => '',
 858                          'buttons_end' => '',
 859                          'beforeEach' => '<li>',
 860                          'afterEach' => '</li>',
 861                          'beforeEachSel' => '<li class="current">',
 862                          'afterEachSel' => '</li>',
 863                          'select_start' => '<li class="collection_select">',
 864                          'select_end' => '</li>',
 865                      );
 866  
 867  
 868              case 'Results':
 869                  // Results list:
 870                  return array(
 871                      'page_url' => '', // All generated links will refer to the current page
 872                      'before' => '<div class="results">',
 873                      'content_start' => '<div id="$prefix$ajax_content">',
 874                      'header_start' => '<div class="results_nav">',
 875                          'header_text' => '<strong>'.T_('Pages').'</strong>: $prev$ $first$ $list_prev$ $list$ $list_next$ $last$ $next$',
 876                          'header_text_single' => '',
 877                      'header_end' => '</div>',
 878                      'head_title' => '<div class="table_title"><span style="float:right">$global_icons$</span>$title$</div>'."\n",
 879                      'filters_start' => '<div class="filters">',
 880                      'filters_end' => '</div>',
 881                      'list_start' => '<div class="table_scroll">'."\n"
 882                                     .'<table class="grouped" cellspacing="0">'."\n",
 883                          'head_start' => "<thead>\n",
 884                              'line_start_head' => '<tr>',  // TODO: fusionner avec colhead_start_first; mettre a jour admin_UI_general; utiliser colspan="$headspan$"
 885                              'colhead_start' => '<th $class_attrib$>',
 886                              'colhead_start_first' => '<th class="firstcol $class$">',
 887                              'colhead_start_last' => '<th class="lastcol $class$">',
 888                              'colhead_end' => "</th>\n",
 889                              'sort_asc_off' => get_icon( 'sort_asc_off' ),
 890                              'sort_asc_on' => get_icon( 'sort_asc_on' ),
 891                              'sort_desc_off' => get_icon( 'sort_desc_off' ),
 892                              'sort_desc_on' => get_icon( 'sort_desc_on' ),
 893                              'basic_sort_off' => '',
 894                              'basic_sort_asc' => get_icon( 'ascending' ),
 895                              'basic_sort_desc' => get_icon( 'descending' ),
 896                          'head_end' => "</thead>\n\n",
 897                          'tfoot_start' => "<tfoot>\n",
 898                          'tfoot_end' => "</tfoot>\n\n",
 899                          'body_start' => "<tbody>\n",
 900                              'line_start' => '<tr class="even">'."\n",
 901                              'line_start_odd' => '<tr class="odd">'."\n",
 902                              'line_start_last' => '<tr class="even lastline">'."\n",
 903                              'line_start_odd_last' => '<tr class="odd lastline">'."\n",
 904                                  'col_start' => '<td $class_attrib$>',
 905                                  'col_start_first' => '<td class="firstcol $class$">',
 906                                  'col_start_last' => '<td class="lastcol $class$">',
 907                                  'col_end' => "</td>\n",
 908                              'line_end' => "</tr>\n\n",
 909                              'grp_line_start' => '<tr class="group">'."\n",
 910                              'grp_line_start_odd' => '<tr class="odd">'."\n",
 911                              'grp_line_start_last' => '<tr class="lastline">'."\n",
 912                              'grp_line_start_odd_last' => '<tr class="odd lastline">'."\n",
 913                                          'grp_col_start' => '<td $class_attrib$ $colspan_attrib$>',
 914                                          'grp_col_start_first' => '<td class="firstcol $class$" $colspan_attrib$>',
 915                                          'grp_col_start_last' => '<td class="lastcol $class$" $colspan_attrib$>',
 916                                  'grp_col_end' => "</td>\n",
 917                              'grp_line_end' => "</tr>\n\n",
 918                          'body_end' => "</tbody>\n\n",
 919                          'total_line_start' => '<tr class="total">'."\n",
 920                              'total_col_start' => '<td $class_attrib$>',
 921                              'total_col_start_first' => '<td class="firstcol $class$">',
 922                              'total_col_start_last' => '<td class="lastcol $class$">',
 923                              'total_col_end' => "</td>\n",
 924                          'total_line_end' => "</tr>\n\n",
 925                      'list_end' => "</table></div>\n\n",
 926                      'footer_start' => '<div class="results_nav nav_footer">',
 927                      'footer_text' => '<strong>'.T_('Pages').'</strong>: $prev$ $first$ $list_prev$ $list$ $list_next$ $last$ $next$<br />$page_size$'
 928                                        /* T_('Page $scroll_list$ out of $total_pages$   $prev$ | $next$<br />'. */
 929                                        /* '<strong>$total_pages$ Pages</strong> : $prev$ $list$ $next$' */
 930                                        /* .' <br />$first$  $list_prev$  $list$  $list_next$  $last$ :: $prev$ | $next$') */,
 931                      'footer_text_single' => '$page_size$',
 932                      'footer_text_no_limit' => '', // Text if theres no LIMIT and therefor only one page anyway
 933                          'prev_text' => T_('Previous'),
 934                          'next_text' => T_('Next'),
 935                          'no_prev_text' => '',
 936                          'no_next_text' => '',
 937                          'list_prev_text' => T_('...'),
 938                          'list_next_text' => T_('...'),
 939                          'list_span' => 11,
 940                          'scroll_list_range' => 5,
 941                      'footer_end' => "</div>\n\n",
 942                      'no_results_start' => '<table class="grouped" cellspacing="0">'."\n",
 943                      'no_results_end'   => '<tr class="lastline"><td class="firstcol lastcol">$no_results$</td></tr>'
 944                                                  .'</table>'."\n\n",
 945                  'content_end' => '</div>',
 946                  'after' => '</div>',
 947                  'sort_type' => 'basic'
 948                  );
 949  
 950              case 'compact_results':
 951                  // Results list:
 952                  return array(
 953                      'page_url' => '', // All generated links will refer to the current page
 954                      'before' => '<div class="compact_results">',
 955                      'header_start' => '',
 956                          'header_text' => '',
 957                          'header_text_single' => '',
 958                      'header_end' => '',
 959                      'list_start' => '<table class="grouped" cellspacing="0">'."\n\n",
 960                          'head_start' => "<thead>\n",
 961                              'head_title' => '',
 962                              'filters_start' => '<tr class="filters"><td colspan="$nb_cols$">',
 963                              'filters_end' => '</td></tr>',
 964                              'line_start_head' => '<tr>',  // TODO: fusionner avec colhead_start_first; mettre a jour admin_UI_general; utiliser colspan="$headspan$"
 965                              'colhead_start' => '<th $class_attrib$ $title_attrib$>',
 966                              'colhead_start_first' => '<th class="firstcol $class$" $title_attrib$>',
 967                              'colhead_start_last' => '<th class="lastcol $class$" $title_attrib$>',
 968                              'colhead_end' => "</th>\n",
 969                              'sort_asc_off' => get_icon( 'sort_asc_off' ),
 970                              'sort_asc_on' => get_icon( 'sort_asc_on' ),
 971                              'sort_desc_off' => get_icon( 'sort_desc_off' ),
 972                              'sort_desc_on' => get_icon( 'sort_desc_on' ),
 973                              'basic_sort_off' => '',
 974                              'basic_sort_asc' => get_icon( 'ascending' ),
 975                              'basic_sort_desc' => get_icon( 'descending' ),
 976                          'head_end' => "</thead>\n\n",
 977                          'tfoot_start' => "<tfoot>\n",
 978                          'tfoot_end' => "</tfoot>\n\n",
 979                          'body_start' => "<tbody>\n",
 980                              'line_start' => '<tr class="even">'."\n",
 981                              'line_start_odd' => '<tr class="odd">'."\n",
 982                              'line_start_last' => '<tr class="even lastline">'."\n",
 983                              'line_start_odd_last' => '<tr class="odd lastline">'."\n",
 984                                  'col_start' => '<td $class_attrib$>',
 985                                  'col_start_first' => '<td class="firstcol $class$">',
 986                                  'col_start_last' => '<td class="lastcol $class$">',
 987                                  'col_end' => "</td>\n",
 988                              'line_end' => "</tr>\n\n",
 989                              'grp_line_start' => '<tr class="group">'."\n",
 990                              'grp_line_start_odd' => '<tr class="odd">'."\n",
 991                              'grp_line_start_last' => '<tr class="lastline">'."\n",
 992                              'grp_line_start_odd_last' => '<tr class="odd lastline">'."\n",
 993                                          'grp_col_start' => '<td $class_attrib$ $colspan_attrib$>',
 994                                          'grp_col_start_first' => '<td class="firstcol $class$" $colspan_attrib$>',
 995                                          'grp_col_start_last' => '<td class="lastcol $class$" $colspan_attrib$>',
 996                                  'grp_col_end' => "</td>\n",
 997                              'grp_line_end' => "</tr>\n\n",
 998                          'body_end' => "</tbody>\n\n",
 999                          'total_line_start' => '<tr class="total">'."\n",
1000                              'total_col_start' => '<td $class_attrib$>',
1001                              'total_col_start_first' => '<td class="firstcol $class$">',
1002                              'total_col_start_last' => '<td class="lastcol $class$">',
1003                              'total_col_end' => "</td>\n",
1004                          'total_line_end' => "</tr>\n\n",
1005                      'list_end' => "</table>\n\n",
1006                      'footer_start' => '<div class="results_nav">',
1007                      'footer_text' => '<strong>'.T_('Pages').'</strong>: $prev$ $first$ $list_prev$ $list$ $list_next$ $last$ $next$'
1008                                        /* T_('Page $scroll_list$ out of $total_pages$   $prev$ | $next$<br />'. */
1009                                        /* '<strong>$total_pages$ Pages</strong> : $prev$ $list$ $next$' */
1010                                        /* .' <br />$first$  $list_prev$  $list$  $list_next$  $last$ :: $prev$ | $next$') */,
1011                      'footer_text_single' => '',
1012                      'footer_text_no_limit' => '', // Text if theres no LIMIT and therefor only one page anyway
1013                          'prev_text' => T_('Previous'),
1014                          'next_text' => T_('Next'),
1015                          'no_prev_text' => '',
1016                          'no_next_text' => '',
1017                          'list_prev_text' => T_('...'),
1018                          'list_next_text' => T_('...'),
1019                          'list_span' => 11,
1020                          'scroll_list_range' => 5,
1021                      'footer_end' => "</div>\n\n",
1022                      'no_results_start' => '<table class="grouped" cellspacing="0">'."\n\n",
1023                      'no_results_end'   => '<tr class="lastline"><td class="firstcol lastcol">$no_results$</td></tr>'
1024                                                  .'</table>'."\n\n",
1025                  'after' => '</div>',
1026                  'sort_type' => 'basic'
1027                  );
1028  
1029  
1030              case 'blockspan_form':
1031                  // blockspan Form settings:
1032                  return array(
1033                      'layout' => 'blockspan',        // Temporary dirty hack
1034                      'formstart' => '',
1035                      'title_fmt' => '$title$'."\n", // TODO: icons
1036                      'no_title_fmt' => '',          //           "
1037                      'fieldset_begin' => '<fieldset $fieldset_attribs$>'."\n"
1038                                                              .'<legend $title_attribs$>$fieldset_title$</legend>'."\n",
1039                      'fieldset_end' => '</fieldset>'."\n",
1040                      'fieldstart' => '<span class="block" $ID$>',
1041                      'labelstart' => '',
1042                      'labelend' => "\n",
1043                      'labelempty' => '',
1044                      'inputstart' => '',
1045                      'infostart' => '',
1046                      'inputend' => "\n",
1047                      'fieldend' => '</span>'.get_icon( 'pixel' )."\n",
1048                      'buttonsstart' => '',
1049                      'buttonsend' => "\n",
1050                      'customstart' => '',
1051                      'customend' => "\n",
1052                      'formend' => '',
1053                  );
1054  
1055              case 'compact_form':
1056              case 'Form':
1057                  // Default Form settings:
1058                  return array(
1059                      'layout' => 'fieldset',
1060                      'formstart' => '',
1061                      'title_fmt' => '<span style="float:right">$global_icons$</span><h2>$title$</h2>'."\n",
1062                      'no_title_fmt' => '<span style="float:right">$global_icons$</span>'."\n",
1063                      'fieldset_begin' => '<div class="fieldset_wrapper $class$" id="fieldset_wrapper_$id$"><fieldset $fieldset_attribs$>'."\n"
1064                                                              .'<legend $title_attribs$>$fieldset_title$</legend>'."\n",
1065                      'fieldset_end' => '</fieldset></div>'."\n",
1066                      'fieldstart' => '<fieldset $ID$>'."\n",
1067                      'labelstart' => '<div class="label">',
1068                      'labelend' => "</div>\n",
1069                      'labelempty' => '<div class="label"></div>', // so that IE6 aligns DIV.input correcctly
1070                      'inputstart' => '<div class="input">',
1071                      'infostart' => '<div class="info">',
1072                      'inputend' => "</div>\n",
1073                      'fieldend' => "</fieldset>\n\n",
1074                      'buttonsstart' => '<fieldset><div class="input">',
1075                      'buttonsend' => "</div></fieldset>\n\n",
1076                      'customstart' => '<div class="custom_content">',
1077                      'customend' => "</div>\n",
1078                      'formend' => '',
1079                  );
1080  
1081              case 'file_browser':
1082                  return array(
1083                      'block_start' => '<div class="block_item"><h3><span style="float:right">$global_icons$</span>$title$</h3>',
1084                      'block_end' => '</div>',
1085                  );
1086  
1087              case 'block_item':
1088              case 'dash_item':
1089                  return array(
1090                      'block_start' => '<div class="block_item" id="styled_content_block"><h3><span style="float:right">$global_icons$</span>$title$</h3>',
1091                      'block_end' => '</div>',
1092                  );
1093  
1094              case 'side_item':
1095                  return array(
1096                      'block_start' => '<div class="browse_side_item"><h3><span style="float:right">$global_icons$</span>$title$</h3>',
1097                      'block_end' => '</div>',
1098                  );
1099  
1100              default:
1101                  debug_die( 'Unknown $name for AdminUI::get_template(): '.var_export($name, true) );
1102          }
1103      }
1104  
1105  
1106      /**
1107       * Get a path key by numeric key. Starts with 0.
1108       *
1109       * @param integer The numeric index of the path (0 is first).
1110       * @param boolean Also return properties?
1111       * @return string|array|false (depends on $withProps)
1112       */
1113  	function get_path( $which, $withProps = false )
1114      {
1115          if( $which === 'last' )
1116          {
1117              $which = count($this->path)-1;
1118          }
1119          if( !isset($this->path[$which]) )
1120          {
1121              return false;
1122          }
1123  
1124          if( $withProps )
1125          {
1126              return array(
1127                  'path' => $this->path[$which],
1128                  'props' => isset( $this->pathProps[$which] ) ? $this->pathProps[$which] : array(),
1129              );
1130          }
1131  
1132          return $this->path[$which];
1133      }
1134  
1135  
1136      /**
1137       * Get the list of path keys in a given range.
1138       *
1139       * @param integer start index
1140       * @param integer|NULL end index (NULL means same as start index)
1141       * @return array List of path keys.
1142       */
1143  	function get_path_range( $start, $end = NULL )
1144      {
1145          if( is_null($end) )
1146          {
1147              $end = $start;
1148          }
1149  
1150          $r = array();
1151          for( $i = $start; $i <= $end; $i++ )
1152          {
1153              $r[] = isset($this->path[$i]) ? $this->path[$i] : NULL;
1154          }
1155  
1156          return $r;
1157      }
1158  
1159  
1160      /**
1161       * Set a specific path level (specific depth).
1162       *
1163       * First level is 0, then the first subpath/submenu is level 1, etc.
1164       *
1165       * E.g., if plugins.php gets called, there could be a call to
1166       * $AdminUI->set_path_level( 0, 'plugins' ), which selects this entry from the menu.
1167       * If a specific tab is called inside of plugins.php, there could be a call to
1168       * $AdminUI->set_path_level( 1, $tab )
1169       *
1170       * Though, it is recommended to call the wrapper functions:
1171       *  - {@link append_path_level()}
1172       *  - {@link set_path()}
1173       *
1174       * This also marks the parent node as selected and checks for permissions.
1175       *
1176       * @param integer Path level to set (starts at 0)
1177       * @param array Either the key of the path or an array(keyname, propsArray).
1178       * @param array Properties for this path entry.
1179       * @return boolean DEPRECATED True if perm granted, false if not (and we're not exiting).
1180       */
1181  	function set_path_level( $level, $pathKey, $pathProps = array() )
1182      {
1183          // Get the parent node (the level above this one):
1184          if( $level == 0 )
1185          { // first level in menu-path: parent node is NULL
1186              $parentNode = & $this->get_node_by_path( NULL );
1187          }
1188          else
1189          { // parent node is the trunk from root to previous level
1190              $parentNode = & $this->get_node_by_path( $this->get_path_range( 0, $level-1 ) );
1191          }
1192          if( ! $parentNode )
1193          { // parent node does not exist:
1194              return false;
1195          }
1196  
1197          // Store the selected entry name in the parent node:
1198          $parentNode['selected'] = $pathKey;
1199  
1200          $this->path[$level] = $pathKey;
1201          $this->pathProps[$level] = $pathProps;
1202  
1203          // pre_dump( 'set_path_level: ', $level, $pathKey, $this->pathProps[$level] );
1204  
1205          return true;
1206      }
1207  
1208  
1209      /**
1210       * Append a selected menu entry to the current path of selected entries.
1211       *
1212       * @param string|array Either the key of the path or an array(keyname, propsArray).
1213       */
1214  	function append_path_level( $path, $pathProps = array() )
1215      {
1216          $search_path = $this->path;
1217          $search_path[] = $path;
1218          // auto-detect path props from menu entries
1219          if( $node = & $this->get_node_by_path( $search_path ) )
1220          {
1221              $pathProps = array_merge( $node, $pathProps );
1222          }
1223  
1224          // Set the path level right after the last existing one:
1225          return $this->set_path_level( count($this->path), $path, $pathProps );
1226      }
1227  
1228  
1229      /**
1230       * Set the full selected path.
1231       *
1232       * For example, this selects the tab/submenu 'plugins' in the main menu 'options':
1233       * <code>
1234       * set_path( 'options', 'plugins' );
1235       * </code>
1236       *
1237       * Use {@link append_path_level()} to append a single path element.
1238       *
1239       * This is an easy stub for {@link set_path_level()}.
1240       *
1241       * @param string|array,... VARIABLE NUMBER OF ARGUMENTS. Each is either the key of a path entry or an array(keyname, propsArray).
1242       */
1243  	function set_path(        )
1244      {
1245          $args = func_get_args();
1246  
1247          $i = 0;
1248          $prevPath = array();  // Remember the path we have walked through
1249  
1250          // Loop though all path levels to set:
1251          foreach( $args as $arg )
1252          {
1253              if( is_array($arg) )
1254              { // Path name and properties given
1255                  list( $pathName, $pathProps ) = $arg;
1256              }
1257              else
1258              { // Just the path name
1259                  $pathName = $arg;
1260                  $pathProps = array();
1261              }
1262  
1263              $this->init_menus();
1264  
1265              if( $node = & $this->get_node_by_path( array_merge( $prevPath, array($pathName) ) ) )
1266              { // the node exists in the menu entries: merge the properties
1267                  $pathProps = array_merge( $node, $pathProps );
1268              }
1269  
1270              if( ! $this->set_path_level( $i++, $pathName, $pathProps ) )
1271              {
1272                  return false;
1273              }
1274  
1275              $prevPath[] = $pathName;
1276          }
1277  
1278          return true;
1279      }
1280  
1281  
1282      /**
1283       * Init the menus.
1284       *
1285       * Do this as late as possible. Especially after determining the blog ID we work on.
1286       * This allows to check for proper permissions and build correct cross navigation links.
1287       *
1288       * Note: The menu structure is determined by the modules and the plugins.
1289       * Individual Admin skins can still override the whole menu. In a cumbersome way though.
1290       */
1291  	function init_menus()
1292      {
1293          global $Plugins;
1294  
1295          if( !empty($this->_menus) )
1296          {    // Already initialized!
1297              return;
1298          }
1299  
1300          // Let the modules construct the menu:
1301          // Part 1:
1302          modules_call_method( 'build_menu_1' );
1303  
1304          // Part 2:
1305          modules_call_method( 'build_menu_2' );
1306  
1307          // Part 3:
1308          modules_call_method( 'build_menu_3' );
1309  
1310          // Call AdminAfterMenuInit to notify Plugins that the menu is initialized
1311          // E.g. the livehits_plugin and weather_plugin use it for adding a menu entry.
1312          $Plugins->trigger_event( 'AdminAfterMenuInit' );
1313      }
1314  
1315  
1316      /**
1317       * Get the top of the HTML <body>.
1318       *
1319       * This is not called if {@link $mode} is set.
1320       *
1321       * @return string
1322       */
1323  	function get_body_top()
1324      {
1325          return '';
1326      }
1327  
1328  
1329      /**
1330       * Get the end of the HTML <body>. Close open divs, etc...
1331       *
1332       * This is not called if {@link $mode} is set.
1333       *
1334       * @return string
1335       */
1336  	function get_body_bottom()
1337      {
1338          return '';
1339      }
1340  
1341  
1342      /**
1343       * GLOBAL HEADER - APP TITLE, LOGOUT, ETC.
1344       *
1345       * @return string
1346       */
1347  	function get_page_head()
1348      {
1349          global $app_shortname, $app_version, $current_User, $htsrv_url_sensitive, $admin_url, $baseurl, $rsc_url;
1350  
1351          $secure_htsrv_url = get_secure_htsrv_url();
1352          $r = '
1353          <div id="header">
1354              <div id="headinfo">
1355                  <span id="headfunctions">'
1356                      // Note: if we log in with another user, we may not have the perms to come back to the same place any more, thus: redirect to admin home.
1357                      .'<a href="'.$secure_htsrv_url.'login.php?action=logout&amp;redirect_to='.rawurlencode(url_rel_to_same_host($admin_url, $secure_htsrv_url)).'">'.T_('Logout').'</a>
1358                      <img src="'.$rsc_url.'icons/close.gif" width="14" height="14" border="0" class="top" alt="" title="'
1359                      .T_('Logout').'" /></a>
1360                  </span>
1361  
1362                  '.$app_shortname.' v <strong>'.$app_version.'</strong>
1363              </div>
1364  
1365              <h1>'.$this->get_title_for_titlearea().'</h1>
1366          </div>
1367          ';
1368  
1369          return $r;
1370      }
1371  
1372  
1373      /**
1374       * Get the footer text
1375       *
1376       * @return string
1377       */
1378  	function get_footer_contents()
1379      {
1380          global $app_footer_text, $copyright_text;
1381  
1382          global $Hit;
1383  
1384          $r = '';
1385  
1386          if( $Hit->is_winIE() )
1387          {
1388           $r .= '<!--[if lt IE 7]>
1389  <div style="text-align:center; color:#f00; font-weight:bold; margin:1ex;">'.
1390              T_('WARNING: Internet Explorer 6 may not able to display this admin skin properly. We strongly recommend you upgrade to IE 7 or Firefox.').'</div>
1391  <![endif]-->';
1392          }
1393  
1394          $r .= '<div class="footer">'.$app_footer_text.' &ndash; '.$copyright_text."</div>\n\n";
1395  
1396          return $r;
1397      }
1398  
1399  
1400      /**
1401       * Get colors for page elements that can't be controlled by CSS (charts)
1402       *
1403       * @return string
1404       */
1405  	function get_color( $what )
1406      {
1407          switch( $what )
1408          {
1409              case 'payload_background':
1410                  return 'f1f6f8';
1411                  break;
1412          }
1413          debug_die( 'unknown color' );
1414      }
1415  
1416  
1417      /**
1418       * Display skin options.
1419       * There is no common skin option.
1420       */
1421  	function display_skin_settings( $Form, $user_ID )
1422      {
1423      }
1424  
1425  
1426      /**
1427       * Set skin specific options.
1428       * There is no common skin option.
1429       */
1430  	function set_skin_settings( $user_ID )
1431      {
1432      }
1433  
1434  
1435      /**
1436       * Get show evobar setting. Default true for every admin skin.
1437       * @return boolean 
1438       */
1439  	function get_show_evobar()
1440      {
1441          return true;
1442      }
1443  }
1444  
1445  ?>

title

Description

title

Description

title

Description

title

title

Body