b2evolution PHP Cross Reference Blogging Systems

Source: /inc/_core/ui/_uiwidget.class.php - 1126 lines - 30582 bytes - Summary - Text - Print

Description: This file implements the Widget class. This file is part of the evoCore framework - {@link http://evocore.net/} See also {@link http://sourceforge.net/projects/evocms/}.

   1  <?php
   2  /**
   3   * This file implements the Widget class.
   4   *
   5   * This file is part of the evoCore framework - {@link http://evocore.net/}
   6   * See also {@link http://sourceforge.net/projects/evocms/}.
   7   *
   8   * @copyright (c)2003-2014 by Francois Planque - {@link http://fplanque.com/}
   9   * Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}.
  10   *
  11   * {@internal License choice
  12   * - If you have received this file as part of a package, please find the license.txt file in
  13   *   the same folder or the closest folder above for complete license terms.
  14   * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)
  15   *   then you must choose one of the following licenses before using the file:
  16   *   - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
  17   *   - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php
  18   * }}
  19   *
  20   * {@internal Open Source relicensing agreement:
  21   * Daniel HAHLER grants Francois PLANQUE the right to license
  22   * Daniel HAHLER's contributions to this file and the b2evolution project
  23   * under any OSI approved OSS license (http://www.opensource.org/licenses/).
  24   * }}
  25   *
  26   * @package evocore
  27   *
  28   * {@internal Below is a list of authors who have contributed to design/coding of this file: }}
  29   * @author fplanque: Francois PLANQUE
  30   * @author blueyed: Daniel HAHLER
  31   *
  32   * @version $Id: _uiwidget.class.php 6136 2014-03-08 07:59:48Z manuel $
  33   */
  34  if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
  35  
  36  
  37  /**
  38   * Widget class which provides an interface to widget methods for other classes.
  39   *
  40   * It provides a method {@link replace_vars()} that can be used to replace object properties in given strings.
  41   * You can also register global action icons.
  42   *
  43   * @package evocore
  44   * @abstract
  45   */
  46  class Widget
  47  {
  48      /**
  49       * Display parameters.
  50       * Example params would be 'block_start' and 'block_end'.
  51       * Params may contain special variables that will be replaced by replace_vars()
  52       * Different types of Widgets will expect different parameters.
  53       * @var array
  54       */
  55      var $params = NULL;
  56  
  57      /**
  58       * Title of the widget (to be displayed)
  59       */
  60      var $title;
  61  
  62      /**
  63       * List of registered global action icons that get substituted through '$global_icons$'.
  64       * @see global_icon()
  65       */
  66      var $global_icons = array();
  67  
  68      /**
  69       * Top block which located near second level tabs
  70       */
  71      var $top_block = '';
  72  
  73      /**
  74       * Constructor
  75       *
  76       * @param string template name to get from $AdminUI
  77       */
  78  	function Widget( $ui_template = NULL )
  79      {
  80          global $AdminUI;
  81  
  82          if( !empty( $ui_template ) )
  83          { // Get template params from Admin Skin:
  84              $this->params = $AdminUI->get_template( $ui_template );
  85          }
  86      }
  87  
  88  
  89      /**
  90       * Registers a global action icon
  91       *
  92       * @param string TITLE text (IMG and A link)
  93       * @param string icon code for {@link get_icon()}
  94       * @param string URL to link to
  95       * @param integer 1-5: weight of the icon. the icon will be displayed only if its weight is >= than the user setting threshold
  96       * @param integer 1-5: weight of the word. the word will be displayed only if its weight is >= than the user setting threshold
  97       * @param array Additional attributes to the A tag. See {@link action_icon()}.
  98       */
  99  	function global_icon( $title, $icon, $url, $word = '', $icon_weight = 3, $word_weight = 2, $link_attribs = array( 'class'=>'action_icon' ) )
 100      {
 101          $this->global_icons[] = array(
 102              'title' => $title,
 103              'icon'  => $icon,
 104              'url'   => $url,
 105              'word'  => $word,
 106              'icon_weight'  => $icon_weight,
 107              'word_weight'  => $word_weight,
 108              'link_attribs' => $link_attribs );
 109      }
 110  
 111  
 112    /**
 113       * Display a template param without replacing variables
 114       */
 115  	function disp_template_raw( $param_name )
 116      {
 117          echo $this->params[ $param_name ];
 118      }
 119  
 120  
 121    /**
 122       * Display a template param with its variables replaced
 123       */
 124  	function disp_template_replaced( $param_name )
 125      {
 126          echo $this->replace_vars( $this->params[ $param_name ] );
 127      }
 128  
 129  
 130      /**
 131       * Replaces $vars$ with appropriate values.
 132       *
 133       * You can give an alternative string to display, if the substituted variable
 134       * is empty, like:
 135       * <code>$vars "Display if empty"$</code>
 136       *
 137       * @param string template
 138       * @param array optional params that are put into {@link $this->params}
 139       *              to be accessible by derived replace_callback() methods
 140       * @return string The substituted string
 141       */
 142  	function replace_vars( $template, $params = NULL )
 143      {
 144          if( !is_null( $params ) )
 145          {
 146              $this->params = $params;
 147          }
 148  
 149          return preg_replace_callback(
 150              '~\$([a-z_]+)(?:\s+"([^"]*)")?\$~', # pattern
 151              array( $this, 'replace_callback_wrapper' ), # callback
 152              $template );
 153      }
 154  
 155  
 156      /**
 157       * This is an additional wrapper to {@link replace_vars()} that allows to react
 158       * on the return value of it.
 159       *
 160       * Used by replace_callback()
 161       *
 162       * @param array {@link preg_match() preg match}
 163       * @return string
 164       */
 165  	function replace_callback_wrapper( $match )
 166      {
 167          // Replace the variable with its content (which will be computed on the fly)
 168          $r = $this->replace_callback( $match );
 169  
 170          if( empty($r) )
 171          {    // Empty result
 172              if( !empty($match[2]) )
 173              {
 174                  return $match[2]; // "display if empty"
 175              }
 176  
 177              // return $match[1];
 178          }
 179          return $r;
 180      }
 181  
 182  
 183      /**
 184       * Callback function used to replace only necessary values in template.
 185       *
 186       * This gets used by {@link replace_vars()} to replace $vars$.
 187       *
 188       * @param array {@link preg_match() preg match}. Index 1 is the template variable.
 189       * @return string to be substituted
 190       */
 191  	function replace_callback( $matches )
 192      {
 193          //echo $matches[1];
 194          switch( $matches[1] )
 195          {
 196              case 'global_icons' :
 197                  // Icons for the whole result set:
 198                  return $this->gen_global_icons();
 199  
 200              case 'title':
 201                  // Results title:
 202                  // Espace $title$ strings from the title to avoid infinite loop replacing
 203                  $escaped_title = str_replace( '$title$', '&#36;title&#36;', $this->title );
 204                  // Replace vars on the title
 205                  $result = $this->replace_vars( $escaped_title );
 206                  // Replace back the $title$ strings and return the result
 207                  return str_replace( '&#36;title&#36;', '$title$', $result );
 208  
 209              case 'no_results':
 210                  // No Results text:
 211                  return $this->no_results_text;
 212  
 213              case 'top_block':
 214                  // Top block:
 215                  return $this->top_block;
 216  
 217              case 'prefix' :
 218                  //prefix
 219                  return $this->param_prefix;
 220  
 221              default:
 222                  return '[Unknown:'.$matches[1].']';
 223          }
 224      }
 225  
 226  
 227      /**
 228       * Generate img tags for registered icons, through {@link global_icon()}.
 229       *
 230       * This is used by the default callback to replace '$global_icons$'.
 231       */
 232  	function gen_global_icons()
 233      {
 234          $r = '';
 235  
 236          foreach( $this->global_icons as $icon_params )
 237          {
 238              $r .= action_icon( $icon_params['title'], $icon_params['icon'], $icon_params['url'], $icon_params['word'],
 239                          $icon_params['icon_weight'], $icon_params['word_weight'], $icon_params['link_attribs'] );
 240          }
 241  
 242          return $r;
 243      }
 244  
 245  }
 246  
 247  
 248  /**
 249   * Class Table
 250   * @todo dh> shouldn't this be in a separate file?
 251   * @package evocore
 252   */
 253  class Table extends Widget
 254  {
 255      /**
 256       * Total number of pages
 257       */
 258      var $total_pages = 1;
 259  
 260      /**
 261       * Number of cols.
 262       */
 263      var $nb_cols;
 264  
 265      /**
 266       * Number of lines already displayed
 267       */
 268      var $displayed_lines_count;
 269  
 270      /**
 271       * Number of cols already displayed (in current line)
 272       */
 273      var $displayed_cols_count;
 274  
 275      /**
 276       * @var array
 277       */
 278      var $fadeout_array;
 279  
 280      var $fadeout_count = 0;
 281  
 282      /**
 283       * @var boolean
 284       */
 285      var $is_fadeout_line;
 286  
 287      var $no_results_text;
 288  
 289  
 290      /**
 291       * URL param names
 292       */
 293      var $param_prefix;
 294  
 295  
 296      /**
 297       * Parameters for the filter area:
 298       */
 299      var $filter_area;
 300  
 301  
 302      /**
 303       * Constructor
 304       *
 305       * @param string template name to get from $AdminUI
 306       * @param string prefix to differentiate page/order/filter params
 307       */
 308  	function Table( $ui_template = NULL, $param_prefix = '' )
 309      {
 310          parent::Widget( $ui_template );
 311  
 312          $this->param_prefix = $param_prefix;
 313  
 314          $this->no_results_text = T_('No results.');
 315      }
 316  
 317  
 318      /**
 319       * Initialize things in order to be ready for displaying.
 320       *
 321       * Lazy fills $this->params
 322       *
 323       * @param array ***please document***
 324       * @param array Fadeout settings array( 'key column' => array of values ) or 'session'
 325       */
 326  	function display_init( $display_params = NULL, $fadeout = NULL )
 327      {
 328          global $AdminUI, $Session, $Debuglog;
 329  
 330          if( empty( $this->params ) && isset( $AdminUI ) )
 331          { // Use default params from Admin Skin:
 332              $this->params = $AdminUI->get_template( 'Results' );
 333          }
 334  
 335          // Make sure we have display parameters:
 336          if( !is_null($display_params) )
 337          { // Use passed params:
 338              //$this->params = & $display_params;
 339              if( !empty( $this->params ) )
 340              {
 341                  $this->params = array_merge( $this->params, $display_params );
 342              }
 343              else
 344              {
 345                  $this->params = & $display_params;
 346              }
 347          }
 348  
 349  
 350          if( $fadeout == 'session' )
 351          {    // Get fadeout_array from session:
 352              if( ($this->fadeout_array = $Session->get('fadeout_array')) && is_array( $this->fadeout_array ) )
 353              {
 354                  $Debuglog->add( 'UIwidget: Got fadeout_array from session data.', 'results' );
 355                  $Session->delete( 'fadeout_array' );
 356              }
 357              else
 358              {
 359                  $this->fadeout_array = NULL;
 360              }
 361          }
 362          else
 363          {
 364              $this->fadeout_array = $fadeout;
 365          }
 366  
 367          if( !empty( $this->fadeout_array ) )
 368          { // Initialize fadeout javascript:
 369              global $rsc_url;
 370              echo '<script type="text/javascript" src="'.$rsc_url.'js/fadeout.js"></script>';
 371              echo '<script type="text/javascript">addEvent( window, "load", Fat.fade_all, false);</script>';
 372          }
 373  
 374      }
 375  
 376  
 377      /**
 378       * Display options area
 379       *
 380       * @param string name of the option ( ma_colselect, tsk_filter....)
 381       * @param string area name ( colselect_area, filter_area )
 382       * @param string option title
 383       * @param string submit button title
 384       * @param string default folde state when is empty in the session
 385       *
 386       */
 387  	function display_option_area( $option_name, $area_name, $option_title, $submit_title, $default_folde_state = 'expanded' )
 388      {
 389          global $debug, $Session;
 390  
 391          // Do we already have a form?
 392          $create_new_form = ! isset( $this->Form );
 393  
 394          echo $this->replace_vars( $this->params['filters_start'] );
 395  
 396          $fold_state = $Session->get( $option_name );
 397  
 398          if( empty( $fold_state ) )
 399          {
 400              $fold_state = $default_folde_state;
 401          }
 402  
 403          //__________________________________  Toogle link _______________________________________
 404  
 405          if( $fold_state == 'collapsed' )
 406          {
 407              echo '<a class="filters_title" href="'.regenerate_url( 'action,target', 'action=expand_filter&target='.$option_name ).'"
 408                                  onclick="return toggle_filter_area(\''.$option_name.'\');" >'
 409                          .get_icon( 'expand', 'imgtag', array( 'id' => 'clickimg_'.$option_name ) );
 410          }
 411          else
 412          {
 413              echo '<a class="filters_title" href="'.regenerate_url( 'action,target', 'action=collapse_filter&target='.$option_name ).'"
 414                                  onclick="return toggle_filter_area(\''.$option_name.'\');" >'
 415                          .get_icon( 'collapse', 'imgtag', array( 'id' => 'clickimg_'.$option_name ) );
 416          }
 417          echo $option_title.'</a>:';
 418  
 419          //____________________________________ Filters preset ____________________________________
 420  
 421          if( !empty( $this->{$area_name}['presets'] ) )
 422          { // We have preset filters
 423              $r = array();
 424              // Loop on all preset filters:
 425              foreach( $this->{$area_name}['presets'] as $key => $preset )
 426              {
 427                  if( method_exists( $this, 'is_filtered' ) && !$this->is_filtered()
 428                              && get_param( $this->param_prefix.'filter_preset' ) == $key )
 429                  { // The list is not filtered and the filter preset is selected, so no link on:
 430                      $r[] = '['.$preset[0].']';
 431                  }
 432                  else
 433                  {    // Display preset filter link:
 434                      if( isset( $preset[2] ) )
 435                      {    // Link with additional params
 436                          $r[] = '<span '.$preset[2].'>[<a href="'.$preset[1].'">'.$preset[0].'</a>]</span>';
 437                      }
 438                      else
 439                      {
 440                          $r[] = '[<a href="'.$preset[1].'">'.$preset[0].'</a>]';
 441                      }
 442                  }
 443              }
 444  
 445              echo ' '.implode( ' ', $r );
 446          }
 447  
 448          //_________________________________________________________________________________________
 449  
 450          if( $debug > 1 )
 451          {
 452              echo ' <span class="notes">('.$option_name.':'.$fold_state.')</span>';
 453              echo ' <span id="asyncResponse"></span>';
 454          }
 455  
 456          // Begining of the div:
 457          echo '<div id="clickdiv_'.$option_name.'"';
 458          if( $fold_state == 'collapsed' )
 459          {
 460              echo ' style="display:none;"';
 461          }
 462          echo '>';
 463  
 464          //_____________________________ Form and callback _________________________________________
 465  
 466          if( !empty($this->{$area_name}['callback']) )
 467          {    // We want to display filtering form fields:
 468  
 469              if( $create_new_form )
 470              {    // We do not already have a form surrounding the whole results list:
 471  
 472                  if( !empty( $this->{$area_name}['url_ignore'] ) )
 473                  {
 474                      $ignore = $this->{$area_name}['url_ignore'];
 475                  }
 476                  else
 477                  {
 478                      $ignore = $this->page_param;
 479                  }
 480  
 481  // fp> CHECKPOINT: If filters break, revert this to 'post'.
 482                  $this->Form = new Form( regenerate_url( $ignore, '', '', '&' ), $this->param_prefix.'form_search', 'get', 'blockspan' ); // COPY!!
 483  
 484                  $this->Form->begin_form( '' );
 485              }
 486  
 487              $submit_name = empty( $this->{$area_name}['submit'] ) ? 'colselect_submit' : $this->{$area_name}['submit'];
 488              $this->Form->submit( array( $submit_name, $submit_title, 'filter' ) );
 489  
 490              $func = $this->{$area_name}['callback'];
 491              $func( $this->Form );
 492  
 493              if( $create_new_form )
 494              {    // We do not already have a form surrounding the whole result list:
 495                  $this->Form->end_form( '' );
 496                  unset( $this->Form );    // forget about this temporary form
 497              }
 498          }
 499  
 500          echo '</div>';
 501  
 502          echo $this->params['filters_end'];
 503      }
 504  
 505  
 506      /**
 507       * Display the column selection
 508       */
 509  	function display_colselect()
 510      {
 511          if( empty( $this->colselect_area ) )
 512          {    // We don't want to display a col selection section:
 513              return;
 514          }
 515  
 516          $option_name = $this->param_prefix.'colselect';
 517  
 518          $this->display_option_area( $option_name, 'colselect_area', T_('Columns'), T_('Apply'), 'collapsed');
 519      }
 520  
 521  
 522      /**
 523       * Display the filtering form
 524       */
 525  	function display_filters()
 526      {
 527          if( empty( $this->filter_area ) )
 528          {    // We don't want to display a filters section:
 529              return;
 530          }
 531  
 532          if( empty( $this->param_prefix ) )
 533          {    // Deny to use a list without prefix
 534              debug_die( 'You must define a $param_prefix before you can use filters.' );
 535          }
 536  
 537          $option_name = $this->param_prefix.'filters';
 538  
 539          $submit_title = !empty( $this->filter_area['submit_title'] ) ? $this->filter_area['submit_title'] : T_('Filter list');
 540  
 541          $this->display_option_area( $option_name, 'filter_area', T_('Filters'), $submit_title, 'expanded' );
 542      }
 543  
 544  
 545      /**
 546       * Display list/table start.
 547       *
 548       * Typically outputs UL or TABLE tags.
 549       */
 550  	function display_list_start()
 551      {
 552          if( $this->total_pages == 0 )
 553          {    // There are no results! Nothing to display!
 554              echo $this->replace_vars( $this->params['no_results_start'] );
 555          }
 556          else
 557          {    // We have rows to display:
 558              echo $this->params['list_start'];
 559          }
 560      }
 561  
 562  
 563      /**
 564       * Display list/table end.
 565       *
 566       * Typically outputs </ul> or </table>
 567       */
 568  	function display_list_end()
 569      {
 570          if( $this->total_pages == 0 )
 571          { // There are no results! Nothing to display!
 572              echo $this->replace_vars( $this->params['no_results_end'] );
 573          }
 574          else
 575          {    // We have rows to display:
 576              echo $this->params['list_end'];
 577          }
 578      }
 579  
 580  
 581      /**
 582       * Display list/table head.
 583       *
 584       * This includes list head/title and filters.
 585       * EXPERIMENTAL: also dispays <tfoot>
 586       */
 587  	function display_head()
 588      {
 589          if( is_ajax_content() )
 590          {    // Don't display this content on AJAX request
 591              return;
 592          }
 593  
 594          // DISPLAY TITLE:
 595          if( isset($this->title) )
 596          { // A title has been defined for this result set:
 597              echo $this->replace_vars( $this->params['head_title'] );
 598          }
 599  
 600          // DISPLAY FILTERS:
 601          $this->display_filters();
 602  
 603          // DISPLAY COL SELECTION
 604          $this->display_colselect();
 605  
 606  
 607          // Experimental:
 608          /*echo $this->params['tfoot_start'];
 609          echo $this->params['tfoot_end'];*/
 610      }
 611  
 612  
 613  
 614      /**
 615       * Display column headers
 616       */
 617  	function display_col_headers()
 618      {
 619          echo $this->params['head_start'];
 620  
 621          if( isset( $this->cols ) )
 622          {
 623  
 624              if( !isset($this->nb_cols) )
 625              {    // Needed for sort strings:
 626                  $this->nb_cols = count($this->cols);
 627              }
 628  
 629  
 630              $th_group_activated = false;
 631  
 632              // Loop on all columns to see if we have th_group columns:
 633              foreach( $this->cols as $col )
 634              {
 635                  if( isset( $col['th_group'] )    )
 636                  {    // We have a th_group column, so break:
 637                      $th_group_activated = true;
 638                      break;
 639                  }
 640              }
 641  
 642              $current_th_group_colspan = 1;
 643              $current_th_colspan = 1;
 644              $current_th_group_title = NULL;
 645              $current_th_title = NULL;
 646              $header_cells = array();
 647  
 648              // Loop on all columns to get an array of header cells description
 649              // Each header cell will have a colspan and rowspan value
 650              // The line 0 is reserved for th_group
 651              // The line 1 is reserved for th
 652              foreach( $this->cols as $key=>$col )
 653              {
 654                  //_______________________________ TH GROUP __________________________________
 655  
 656                  if( isset( $col['th_group'] ) )
 657                  {    // The column has a th_group
 658                      if( is_null( $current_th_group_title ) || $col['th_group'] != $current_th_group_title )
 659                      {    // It's the begining of a th_group colspan (line0):
 660  
 661                          //Initialize current th_group colspan to 1 (line0):
 662                          $current_th_group_colspan = 1;
 663  
 664                          // Set colspan and rowspan colum for line0 to 1:
 665                          $header_cells[0][$key]['colspan'] = 1;
 666                          $header_cells[0][$key]['rowspan'] = 1;
 667                      }
 668                      else
 669                      {    // The column is part of a th group colspan
 670                          // Update the first th group colspan cell
 671                          $header_cells[0][$key-$current_th_group_colspan]['colspan']++;
 672  
 673                          // Set the colspan column to 0 to not display it
 674                          $header_cells[0][$key]['colspan'] = 0;
 675                          $header_cells[0][$key]['rowspan'] = 0;
 676  
 677                          //Update current th_group colspan to 1 (line0):
 678                          $current_th_group_colspan++;
 679                      }
 680  
 681                      // Update current th group title:
 682                      $current_th_group_title =     $col['th_group'];
 683                  }
 684  
 685                  //___________________________________ TH ___________________________________
 686  
 687                  if( is_null( $current_th_title ) || $col['th'] != $current_th_title )
 688                  {    // It's the begining of a th colspan (line1)
 689  
 690                      //Initialize current th colspan to 1 (line1):
 691                      $current_th_colspan = 1;
 692  
 693                      // Update current th title:
 694                      $current_th_title = $col['th'];
 695  
 696                      if( $th_group_activated  && !isset( $col['th_group'] ) )
 697                      { // We have to lines and the column has no th_group, so it will be a "rowspan2"
 698  
 699                          // Set the cell colspan and rowspan values for the line0:
 700                          $header_cells[0][$key]['colspan'] = 1;
 701                          $header_cells[0][$key]['rowspan'] = 2;
 702  
 703                          // Set the cell colspan and rowspan values for the line1, to do not display it:
 704                          $header_cells[1][$key]['colspan'] = 0;
 705                          $header_cells[1][$key]['rowspan'] = 0;
 706                      }
 707                      else
 708                      {    // The cell has no rowspan
 709                          $header_cells[1][$key]['colspan'] = 1;
 710                          $header_cells[1][$key]['rowspan'] = 1;
 711                      }
 712                  }
 713                  else
 714                  {    // The column is part of a th colspan
 715                      if( $th_group_activated && !isset( $col['th_group'] ) )
 716                      {    // We have to lines and the column has no th_group, the colspan is "a rowspan 2"
 717  
 718                          // Update the first th cell colspan in line0
 719                          $header_cells[0][$key-$current_th_colspan]['colspan']++;
 720  
 721                          // Set the cell colspan to 0 in line0 to not display it:
 722                          $header_cells[0][$key]['colspan'] = 0;
 723                          $header_cells[0][$key]['rowspan'] = 0;
 724                      }
 725                      else
 726                      { // Update the first th colspan cell in line1
 727                          $header_cells[1][$key-$current_th_colspan]['colspan']++;
 728                      }
 729  
 730                      // Set the cell colspan to 0 in line1 to do not display it:
 731                      $header_cells[1][$key]['colspan'] = 0;
 732                      $header_cells[1][$key]['rowspan'] = 0;
 733  
 734                      $current_th_colspan++;
 735                  }
 736              }
 737  
 738              // ________________________________________________________________________________
 739  
 740              if( !$th_group_activated )
 741              {    // We have only the "th" line to display
 742                  $start = 1;
 743              }
 744              else
 745              {    // We have the "th_group" and the "th" lines to display
 746                  $start = 0;
 747              }
 748  
 749              //__________________________________________________________________________________
 750  
 751              // Loop on all headers lines:
 752              for( $i = $start; $i <2 ; $i++ )
 753              {
 754                  echo $this->params['line_start_head'];
 755                  // Loop on all headers lines cells to display them:
 756                  foreach( $header_cells[$i] as $key=>$cell )
 757                  {
 758                      if( $cell['colspan'] )
 759                      {    // We have to dispaly cell:
 760                          if( $i == 0 && $cell['rowspan'] != 2 )
 761                          {    // The cell is a th_group
 762                              $th_title = $this->cols[$key]['th_group'];
 763                              $col_order = isset( $this->cols[$key]['order_group'] );
 764                          }
 765                          else
 766                          {    // The cell is a th
 767                              $th_title = $this->cols[$key]['th'];
 768                              $col_order = isset( $this->cols[$key]['order'] )
 769                              || isset( $this->cols[$key]['order_objects_callback'] )
 770                              || isset( $this->cols[$key]['order_rows_callback'] );
 771                          }
 772  
 773  
 774                          if( isset( $this->cols[$key]['th_class'] ) )
 775                          {    // We have a class for the th column
 776                              $class = $this->cols[$key]['th_class'];
 777                          }
 778                          else
 779                          {    // We have no class for the th column
 780                              $class = '';
 781                          }
 782  
 783                          if( $key == 0 && isset($this->params['colhead_start_first']) )
 784                          { // Display first column start:
 785                              $output = $this->params['colhead_start_first'];
 786  
 787                              // Add the total column class in the grp col start first param class:
 788                              $output = str_replace( '$class$', $class, $output );
 789                          }
 790                          elseif( ( $key + $cell['colspan'] ) == (count( $this->cols) ) && isset($this->params['colhead_start_last']) )
 791                          { // Last column can get special formatting:
 792                              $output = $this->params['colhead_start_last'];
 793  
 794                              // Add the total column class in the grp col start end param class:
 795                              $output = str_replace( '$class$', $class, $output );
 796                          }
 797                          else
 798                          { // Display regular colmun start:
 799                              $output = $this->params['colhead_start'];
 800  
 801                              // Replace the "class_attrib" in the grp col start param by the td column class
 802                              $output = str_replace( '$class_attrib$', 'class="'.$class.'"', $output );
 803                          }
 804  
 805                          // Replace column header title attribute
 806                          if( isset( $this->cols[$key]['th_title'] ) )
 807                          { // Column header title is set
 808                              $output = str_replace( '$title_attrib$', ' title="'.$this->cols[$key]['th_title'].'"', $output );
 809                          }
 810                          else
 811                          { // Column header title is not set, replace with empty string
 812                              $output = str_replace( '$title_attrib$', '', $output );
 813                          }
 814  
 815                          // Set colspan and rowspan values for the cell:
 816                          $output = preg_replace( '#(<)([^>]*)>$#', '$1$2 colspan="'.$cell['colspan'].'" rowspan="'.$cell['rowspan'].'">' , $output );
 817  
 818                          echo $output;
 819  
 820                          if( $col_order )
 821                          { // The column can be ordered:
 822                              $col_sort_values = $this->get_col_sort_values( $key );
 823  
 824  
 825                              // Determine CLASS SUFFIX depending on wether the current column is currently sorted or not:
 826                              if( !empty($col_sort_values['current_order']) )
 827                              { // We are currently sorting on the current column:
 828                                  $class_suffix = '_current';
 829                              }
 830                              else
 831                              {    // We are not sorting on the current column:
 832                                  $class_suffix = '_sort_link';
 833                              }
 834  
 835                              // Display title depending on sort type/mode:
 836                              if( $this->params['sort_type'] == 'single' )
 837                              { // single column sort type:
 838  
 839                                  // Title with toggle:
 840                                  echo '<a href="'.$col_sort_values['order_toggle'].'"'
 841                                              .' title="'.T_('Change Order').'"'
 842                                              .' class="single'.$class_suffix.'"'
 843                                              .'>'.$th_title.'</a>';
 844  
 845                                  // Icon for ascending sort:
 846                                  echo '<a href="'.$col_sort_values['order_asc'].'"'
 847                                              .' title="'.T_('Ascending order').'"'
 848                                              .'>'.$this->params['sort_asc_'.($col_sort_values['current_order'] == 'ASC' ? 'on' : 'off')].'</a>';
 849  
 850                                  // Icon for descending sort:
 851                                  echo '<a href="'.$col_sort_values['order_desc'].'"'
 852                                              .' title="'.T_('Descending order').'"'
 853                                              .'>'.$this->params['sort_desc_'.($col_sort_values['current_order'] == 'DESC' ? 'on' : 'off')].'</a>';
 854  
 855                              }
 856                              else
 857                              { // basic sort type (toggle single column):
 858  
 859                                  if( $col_sort_values['current_order'] == 'ASC' )
 860                                  { // the sorting is ascending and made on the current column
 861                                      $sort_icon = $this->params['basic_sort_asc'];
 862                                  }
 863                                  elseif( $col_sort_values['current_order'] == 'DESC' )
 864                                  { // the sorting is descending and made on the current column
 865                                      $sort_icon = $this->params['basic_sort_desc'];
 866                                  }
 867                                  else
 868                                  { // the sorting is not made on the current column
 869                                      $sort_icon = $this->params['basic_sort_off'];
 870                                  }
 871  
 872                                  // Toggle Icon + Title
 873                                  // Set link title only if the column header title was not set
 874                                  $link_title = isset( $this->cols[$key]['th_title'] ) ? '' : ' title="'.T_('Change Order').'"';
 875                                  echo '<a href="'.$col_sort_values['order_toggle'].'"'
 876                                              .$link_title
 877                                              .' class="basic'.$class_suffix.'"'
 878                                              .'>'.$sort_icon.' '.$th_title.'</a>';
 879  
 880                              }
 881  
 882                          }
 883                          elseif( $th_title )
 884                          { // the column can't be ordered, but we still have a header defined:
 885                              echo '<span>'.$th_title.'</span>';
 886                          }
 887                          // </td>
 888                          echo $this->params['colhead_end'];
 889                      }
 890                  }
 891                  // </tr>
 892                  echo $this->params['line_end'];
 893              }
 894          } // this->cols not set
 895  
 896          echo $this->params['head_end'];
 897      }
 898  
 899  
 900      /**
 901       *
 902       */
 903  	function display_body_start()
 904      {
 905          echo $this->params['body_start'];
 906  
 907          $this->displayed_lines_count = 0;
 908  
 909      }
 910  
 911  
 912      /**
 913       *
 914       */
 915  	function display_body_end()
 916      {
 917          echo $this->params['body_end'];
 918      }
 919  
 920  
 921      /**
 922       *
 923       */
 924  	function display_line_start( $is_last = false, $is_fadeout_line = false )
 925      {
 926          if( $this->displayed_lines_count % 2 )
 927          { // Odd line:
 928              if( $is_last )
 929                  echo $this->params['line_start_odd_last'];
 930              else
 931                  echo $this->params['line_start_odd'];
 932          }
 933          else
 934          { // Even line:
 935              if( $is_last )
 936                  echo $this->params['line_start_last'];
 937              else
 938                  echo $this->params['line_start'];
 939          }
 940  
 941          $this->displayed_cols_count = 0;
 942  
 943          $this->is_fadeout_line = $is_fadeout_line;
 944      }
 945  
 946  
 947      /**
 948       *
 949       */
 950  	function display_line_end()
 951      {
 952          echo $this->params['line_end'];
 953  
 954          $this->displayed_lines_count ++;
 955      }
 956  
 957  
 958      /**
 959       * Start a column (data).
 960       *
 961       * @param array Additional attributes for the <td> tag (attr_name => attr_value).
 962       */
 963  	function display_col_start( $extra_attr = array() )
 964      {
 965          // Get colum definitions for current column:
 966          $col = $this->cols[$this->displayed_cols_count];
 967  
 968          if( isset( $col['td_class'] ) )
 969          {    // We have a class for the total column
 970              $class = $col['td_class'];
 971          }
 972          else
 973          {    // We have no class for the total column
 974              $class = '';
 975          }
 976  
 977          /**
 978           * Update class and add a fadeout ID for fadeout list results
 979           */
 980          if( $this->is_fadeout_line )
 981          {
 982              // echo ' fadeout '.$this->fadeout_count;
 983              $class .= ' fadeout-ffff00" id="fadeout-'.$this->fadeout_count;
 984              $this->fadeout_count++;
 985          }
 986  
 987          if( ($this->displayed_cols_count == 0) && isset($this->params['col_start_first']) )
 988          { // Display first column column start:
 989              $output = $this->params['col_start_first'];
 990              // Add the total column class in the col start first param class:
 991              $output = str_replace( '$class$', $class, $output );
 992          }
 993          elseif( ( $this->displayed_cols_count == count($this->cols)-1) && isset($this->params['col_start_last']) )
 994          { // Last column can get special formatting:
 995              $output = $this->params['col_start_last'];
 996              // Add the total column class in the col start end param class:
 997              $output = str_replace( '$class$', $class, $output );
 998          }
 999          else
1000          { // Display regular colmun start:
1001              $output = $this->params['col_start'];
1002              // Replace the "class_attrib" in the total col start param by the td column class
1003              $output = str_replace( '$class_attrib$', 'class="'.$class.'"', $output );
1004          }
1005  
1006          // Custom attributes:
1007          // Tblue> TODO: Make this more elegant (e. g.: replace "$extra_attr$" with the attributes string).
1008          if( $extra_attr )
1009          {
1010              if ( ! isset ($extra_attr['format_to_output']))
1011              {
1012                  $output = substr( $output, 0, -1 ).get_field_attribs_as_string( $extra_attr ).'>';
1013              }
1014              else
1015              {
1016                  $format_to_output = $extra_attr['format_to_output'];
1017                  unset($extra_attr['format_to_output']);
1018                  $output = substr( $output, 0, -1 ).get_field_attribs_as_string( $extra_attr, $format_to_output ).'>';
1019  
1020  
1021              }
1022  
1023          }
1024          // Check variables in column declaration:
1025          $output = $this->parse_class_content( $output );
1026          echo $output;
1027      }
1028  
1029  
1030    /**
1031       *
1032       */
1033  	function display_col_end()
1034      {
1035          echo $this->params['col_end'];
1036  
1037          $this->displayed_cols_count ++;
1038      }
1039  
1040  
1041      /**
1042       * Widget callback for template vars.
1043       *
1044       * This allows to replace template vars, see {@link Widget::replace_callback()}.
1045       *
1046       * @return string
1047       */
1048  	function replace_callback( $matches )
1049      {
1050          // echo '['.$matches[1].']';
1051          switch( $matches[1] )
1052          {
1053              case 'nb_cols' :
1054                  // Number of columns in result:
1055                  if( !isset($this->nb_cols) )
1056                  {
1057                      $this->nb_cols = count($this->cols);
1058                  }
1059                  return $this->nb_cols;
1060  
1061              default :
1062                  return parent::replace_callback( $matches );
1063          }
1064      }
1065  
1066      /**
1067       * Handle variable subtitutions for class column contents.
1068       *
1069       * This is one of the key functions to look at when you want to use the Results class.
1070       * - #var#
1071       */
1072  	function parse_class_content( $content )
1073      {
1074          // Make variable substitution for RAWS:
1075          while (preg_match('!\# (\w+) \#!ix', $content, $matchesarray))
1076          { // Replace all matches to the content of the current row's cell. That means that several variables can be inserted to the class.
1077              if (! empty($this->rows[$this->current_idx]->$matchesarray[1]))
1078              {
1079                  $content = str_replace($matchesarray[0],$this->rows[$this->current_idx]->$matchesarray[1] , $content);
1080              }
1081              else
1082              {
1083                  $content = str_replace($matchesarray[0], 'NULL' , $content);
1084              }
1085          }
1086  
1087          while (preg_match('#% (.+?) %#ix', $content, $matchesarray))
1088          {
1089               eval('$result = '.$matchesarray[1].';');
1090               $content = str_replace($matchesarray[0],$result, $content);
1091          }
1092  
1093          return $content;
1094      }
1095  
1096  
1097      /**
1098       * Init results params from skin template params. It's used when Results table is filled from ajax result.
1099       *
1100       * @param string the template param which can have values( 'admin', 'front' )
1101       * @param string the name of the skin
1102       */
1103  	function init_params_by_skin( $skin_type, $skin_name )
1104      {
1105          switch( $skin_type )
1106          {
1107              case 'admin': // admin skin type
1108                  global $adminskins_path;
1109                  require_once $adminskins_path.$skin_name.'/_adminUI.class.php';
1110                  $this->params = AdminUI::get_template( 'Results' );
1111                  break;
1112  
1113              case 'front': // front office skin type
1114                  global $skins_path;
1115                  require_once $skins_path.$skin_name.'/_skin.class.php';
1116                  $this->params = Skin::get_template( 'Results' );
1117                  break;
1118  
1119              default:
1120                  debug_die( 'Invalid results template param!' );
1121          }
1122      }
1123  
1124  }
1125  
1126  ?>

title

Description

title

Description

title

Description

title

title

Body