b2evolution PHP Cross Reference Blogging Systems

Source: /inc/items/model/_itemlistlight.class.php - 1537 lines - 52998 bytes - Summary - Text - Print

Description: This file implements the ItemListLight class. This object handles item/post/article lists WITHOUT FULL FUNCTIONNALITY but with a LOWER MEMORY FOOTPRINT.

   1  <?php
   2  /**
   3   * This file implements the ItemListLight class.
   4   *
   5   * This object handles item/post/article lists WITHOUT FULL FUNCTIONNALITY
   6   * but with a LOWER MEMORY FOOTPRINT.
   7   *
   8   * This file is part of the evoCore framework - {@link http://evocore.net/}
   9   * See also {@link http://sourceforge.net/projects/evocms/}.
  10   *
  11   * @copyright (c)2003-2014 by Francois Planque - {@link http://fplanque.com/}
  12   *
  13   * {@internal License choice
  14   * - If you have received this file as part of a package, please find the license.txt file in
  15   *   the same folder or the closest folder above for complete license terms.
  16   * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)
  17   *   then you must choose one of the following licenses before using the file:
  18   *   - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
  19   *   - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php
  20   * }}
  21   *
  22   * {@internal Open Source relicensing agreement:
  23   * }}
  24   *
  25   * @package evocore
  26   *
  27   * {@internal Below is a list of authors who have contributed to design/coding of this file: }}
  28   * @author fplanque: Francois PLANQUE.
  29   *
  30   * @version $Id: _itemlistlight.class.php 6136 2014-03-08 07:59:48Z manuel $
  31   */
  32  if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
  33  
  34  load_class( '_core/model/dataobjects/_dataobjectcache.class.php', 'DataObjectCache' );
  35  load_class( '_core/model/dataobjects/_dataobjectlist2.class.php', 'DataObjectList2' );
  36  load_class( 'items/model/_item.class.php', 'Item' );
  37  load_funcs('items/model/_item.funcs.php');
  38  
  39  /**
  40   * Item List Class LIGHT
  41   *
  42   * Contrary to ItemList2, we only do 1 query here and we extract only a few selected params.
  43   * Basically all we want is being able to generate permalinks.
  44   *
  45   * @package evocore
  46   */
  47  class ItemListLight extends DataObjectList2
  48  {
  49      /**
  50       * SQL object for the Query
  51       */
  52      var $ItemQuery;
  53  
  54      /**
  55       * Blog object this ItemList refers to
  56       */
  57      var $Blog;
  58  
  59      /**
  60       * list unit: 'posts' or 'days'
  61       */
  62      var $unit;
  63  
  64      /**
  65       * Did we request a single post?
  66       */
  67       var $single_post = false;
  68  
  69      /**
  70       * Last date that has been output by date_if_changed()
  71       */
  72      var $last_displayed_date = '';
  73  
  74      /**
  75       * Lazy filled
  76       * @access private
  77       */
  78      var $advertised_start_date;
  79      var $advertised_stop_date;
  80      /**
  81       * Anti infinite loops:
  82       */
  83      var $getting_adv_start_date = false;
  84      var $getting_adv_stop_date = false;
  85  
  86      var $group_by_cat = 0;
  87  
  88  
  89      /**
  90       * Constructor
  91       *
  92       * @todo  add param for saved session filter set
  93       *
  94       * @param Blog
  95       * @param mixed Default filter set: Do not show posts before this timestamp, can be 'now'
  96       * @param mixed Default filter set: Do not show posts after this timestamp, can be 'now'
  97       * @param integer|NULL Limit
  98       * @param string name of cache to be used (for table prefix info)
  99       * @param string prefix to differentiate page/order params when multiple Results appear one same page
 100       * @param array restrictions for itemlist (position, contact, firm, ...) key: restriction name, value: ID of the restriction
 101       */
 102  	function ItemListLight(
 103              & $Blog,
 104              $timestamp_min = NULL,       // Do not show posts before this timestamp
 105              $timestamp_max = NULL,            // Do not show posts after this timestamp
 106              $limit = 20,
 107              $cache_name = 'ItemCacheLight',     // name of cache to be used (for table prefix info)
 108              $param_prefix = '',
 109              $filterset_name = ''                // Name to be used when saving the filterset (leave empty to use default for collection)
 110          )
 111      {
 112          global $Settings, $posttypes_specialtypes;
 113  
 114          // Call parent constructor:
 115          parent::DataObjectList2( get_Cache($cache_name), $limit, $param_prefix, NULL );
 116  
 117          // The SQL Query object:
 118          $this->ItemQuery = new ItemQuery( $this->Cache->dbtablename, $this->Cache->dbprefix, $this->Cache->dbIDname );
 119  
 120          $this->Blog = & $Blog;
 121  
 122          if( !empty( $filterset_name ) )
 123          {    // Set the filterset_name with the filterset_name param
 124              $this->filterset_name = 'ItemList_filters_'.$filterset_name;
 125          }
 126          else
 127          {    // Set a generic filterset_name
 128              $this->filterset_name = 'ItemList_filters_coll'.( !is_null( $this->Blog ) ? $this->Blog->ID : '0' );
 129          }
 130  
 131          $this->page_param = $param_prefix.'paged';
 132  
 133          // Initialize the default filter set:
 134          $this->set_default_filters( array(
 135                  'filter_preset' => NULL,
 136                  'ts_min' => $timestamp_min,
 137                  'ts_max' => $timestamp_max,
 138                  'ts_created_max' => NULL,
 139                  'cat_array' => array(),
 140                  'cat_modifier' => NULL,
 141                  'cat_focus' => 'wide',                    // Search in extra categories, not just main cat
 142                  'tags' => NULL,
 143                  'authors' => NULL,
 144                  'authors_login' => NULL,
 145                  'assignees' => NULL,
 146                  'assignees_login' => NULL,
 147                  'author_assignee' => NULL,
 148                  'lc' => 'all',                                    // Filter on requested locale
 149                  'keywords' => NULL,
 150                  'phrase' => 'AND',
 151                  'exact' => 0,
 152                  'post_ID' => NULL,
 153                  'post_ID_list' => NULL,
 154                  'post_title' => NULL,
 155                  'ymdhms' => NULL,
 156                  'week' => NULL,
 157                  'ymdhms_min' => NULL,
 158                  'ymdhms_max' => NULL,
 159                  'statuses' => NULL,
 160                  'types' => '-'.implode(',',$posttypes_specialtypes),    // Keep content post types, Exclide pages, intros, sidebar links and ads
 161                  'visibility_array' => get_inskin_statuses(),
 162                  'orderby' => !is_null( $this->Blog ) ? $this->Blog->get_setting('orderby') : 'datestart',
 163                  'order' => !is_null( $this->Blog ) ? $this->Blog->get_setting('orderdir') : 'DESC',
 164                  'unit' => !is_null( $this->Blog ) ? $this->Blog->get_setting('what_to_show'): 'posts',
 165                  'posts' => $this->limit,
 166                  'page' => 1,
 167                  'featured' => NULL,
 168              ) );
 169      }
 170  
 171  
 172      /**
 173       * Reset the query -- EXPERIMENTAL
 174       *
 175       * Useful to requery with a slighlty moidified filterset
 176       */
 177  	function reset()
 178      {
 179          // The SQL Query object:
 180          $this->ItemQuery = new ItemQuery( $this->Cache->dbtablename, $this->Cache->dbprefix, $this->Cache->dbIDname );
 181  
 182          parent::reset();
 183      }
 184  
 185  
 186      /**
 187       * Set/Activate filterset
 188       *
 189       * This will also set back the GLOBALS !!! needed for regenerate_url().
 190       *
 191       * @param array
 192       * @param boolean
 193       */
 194  	function set_filters( $filters, $memorize = true )
 195      {
 196          if( !empty( $filters ) )
 197          { // Activate the filterset (fallback to default filter when a value is not set):
 198              $this->filters = array_merge( $this->default_filters, $filters );
 199          }
 200  
 201          // Activate preset filters if necessary:
 202          $this->activate_preset_filters();
 203  
 204          // Funky oldstyle params:
 205          $this->limit = $this->filters['posts']; // for compatibility with parent class
 206          $this->page = $this->filters['page'];
 207  
 208  
 209          if( $memorize )
 210          {    // set back the GLOBALS !!! needed for regenerate_url() :
 211  
 212              /*
 213               * Selected filter preset:
 214               */
 215              memorize_param( $this->param_prefix.'filter_preset', 'string', $this->default_filters['filter_preset'], $this->filters['filter_preset'] );  // List of authors to restrict to
 216  
 217  
 218              /*
 219               * Blog & Chapters/categories restrictions:
 220               */
 221              // Get chapters/categories (and compile those values right away)
 222              memorize_param( 'cat', '/^[*\-]?([0-9]+(,[0-9]+)*)?$/', $this->default_filters['cat_modifier'], $this->filters['cat_modifier'] );  // List of authors to restrict to
 223              memorize_param( 'catsel', 'array', $this->default_filters['cat_array'], $this->filters['cat_array'] );
 224              memorize_param( $this->param_prefix.'cat_focus', 'string', $this->default_filters['cat_focus'], $this->filters['cat_focus'] );  // Categories to search on
 225              // TEMP until we get this straight:
 226              // fp> this would only be used for the categories widget and setting it here overwtrites the interesting values when a post list widget is tirggered
 227              // fp> if we need it here we want to use a $set_globals params to this function
 228              // global $cat_array, $cat_modifier;
 229              // $cat_array = $this->default_filters['cat_array'];
 230              // $cat_modifier = $this->default_filters['cat_modifier'];
 231  
 232  
 233              /*
 234               * Restrict to selected tags:
 235               */
 236              memorize_param( $this->param_prefix.'tags', 'string', $this->default_filters['tags'], $this->filters['tags'] );
 237  
 238  
 239              /*
 240               * Restrict to selected authors:
 241               */
 242              // List of authors users IDs to restrict to
 243              memorize_param( $this->param_prefix.'author', 'string', $this->default_filters['authors'], $this->filters['authors'] );
 244              // List of authors users logins to restrict to
 245              memorize_param( $this->param_prefix.'author_login', 'string', $this->default_filters['authors_login'], $this->filters['authors_login'] );
 246  
 247              /*
 248               * Restrict to selected assignees:
 249               */
 250              // List of assignees users IDs to restrict to
 251              memorize_param( $this->param_prefix.'assgn', 'string', $this->default_filters['assignees'], $this->filters['assignees'] );
 252              // List of assignees users logins to restrict to
 253              memorize_param( $this->param_prefix.'assgn_login', 'string', $this->default_filters['assignees_login'], $this->filters['assignees_login'] );
 254  
 255              /*
 256               * Restrict to selected author OR assignee:
 257               */
 258              memorize_param( $this->param_prefix.'author_assignee', 'string', $this->default_filters['author_assignee'], $this->filters['author_assignee'] );
 259  
 260              /*
 261               * Restrict to selected locale:
 262               */
 263              memorize_param( $this->param_prefix.'lc', 'string', $this->default_filters['lc'], $this->filters['lc'] );  // Locale to restrict to
 264  
 265              /*
 266               * Restrict to selected statuses:
 267               */
 268              memorize_param( $this->param_prefix.'status', 'string', $this->default_filters['statuses'], $this->filters['statuses'] );  // List of statuses to restrict to
 269  
 270              /*
 271               * Restrict to selected item type:
 272               */
 273              memorize_param( $this->param_prefix.'types', 'integer', $this->default_filters['types'], $this->filters['types'] );  // List of item types to restrict to
 274  
 275              /*
 276               * Restrict by keywords
 277               */
 278              memorize_param( $this->param_prefix.'s', 'string', $this->default_filters['keywords'], $this->filters['keywords'] );             // Search string
 279              memorize_param( $this->param_prefix.'sentence', 'string', $this->default_filters['phrase'], $this->filters['phrase'] ); // Search for sentence or for words
 280              memorize_param( $this->param_prefix.'exact', 'integer', $this->default_filters['exact'], $this->filters['exact'] );     // Require exact match of title or contents
 281  
 282              /*
 283               * Specific Item selection?
 284               */
 285              memorize_param( $this->param_prefix.'m', '/^\d{4}(0[1-9]|1[0-2])?(?(1)(0[1-9]|[12][0-9]|3[01])?)(?(2)([01][0-9]|2[0-3])?)(?(3)([0-5][0-9]){0,2})$/', $this->default_filters['ymdhms'], $this->filters['ymdhms'] );          // YearMonth(Day) to display
 286              memorize_param( $this->param_prefix.'w', '/^(0?[0-9]|[1-4][0-9]|5[0-3])$/', $this->default_filters['week'], $this->filters['week'] );            // Week number
 287              memorize_param( $this->param_prefix.'dstart', 'integer', $this->default_filters['ymdhms_min'], $this->filters['ymdhms_min'] ); // YearMonth(Day) to start at
 288              memorize_param( $this->param_prefix.'dstop', 'integer', $this->default_filters['ymdhms_max'], $this->filters['ymdhms_max'] ); // YearMonth(Day) to start at
 289  
 290              // TODO: show_past/future should probably be wired on dstart/dstop instead on timestamps -> get timestamps out of filter perimeter
 291              if( is_null($this->default_filters['ts_min'])
 292                  && is_null($this->default_filters['ts_max'] ) )
 293              {    // We have not set a strict default -> we allow overridding:
 294                  memorize_param( $this->param_prefix.'show_past', 'integer', 0, ($this->filters['ts_min'] == 'now') ? 0 : 1 );
 295                  memorize_param( $this->param_prefix.'show_future', 'integer', 0, ($this->filters['ts_max'] == 'now') ? 0 : 1 );
 296              }
 297  
 298              /*
 299               * Restrict to the statuses we want to show:
 300               */
 301              // Note: oftentimes, $show_statuses will have been preset to a more restrictive set of values
 302              memorize_param( $this->param_prefix.'show_statuses', 'array', $this->default_filters['visibility_array'], $this->filters['visibility_array'] );    // Array of sharings to restrict to
 303  
 304              /*
 305               * OLD STYLE orders:
 306               */
 307              memorize_param( $this->param_prefix.'order', 'string', $this->default_filters['order'], $this->filters['order'] );           // ASC or DESC
 308              // This order style is OK, because sometimes the commentList is not displayed on a table so we cannot say we want to order by a specific column. It's not a crap.
 309              memorize_param( $this->param_prefix.'orderby', 'string', $this->default_filters['orderby'], $this->filters['orderby'] );  // list of fields to order by (TODO: change that crap)
 310  
 311              /*
 312               * Paging limits:
 313               */
 314              memorize_param( $this->param_prefix.'unit', 'string', $this->default_filters['unit'], $this->filters['unit'] );            // list unit: 'posts' or 'days'
 315  
 316              memorize_param( $this->param_prefix.'posts', 'integer', $this->default_filters['posts'], $this->filters['posts'] );             // # of units to display on the page
 317  
 318              // 'paged'
 319              memorize_param( $this->page_param, 'integer', 1, $this->filters['page'] );      // List page number in paged display
 320          }
 321      }
 322  
 323  
 324      /**
 325       * Init filter params from Request params
 326       *
 327       * @param boolean do we want to use saved filters ?
 328       * @return boolean true if we could apply a filterset based on Request params (either explicit or reloaded)
 329       */
 330  	function load_from_Request( $use_filters = true )
 331      {
 332          // fp> 2007-09-23> Let's always start with clean filters.
 333          // If we don't do this, then $this->filters will end up with filters in a different order than $this->default_filters.
 334          // And orders are different, then $this->is_filtered() will say it's filtered even if it's not.
 335          $this->filters = $this->default_filters;
 336  
 337          if( $use_filters )
 338          {
 339              // Do we want to restore filters or do we want to create a new filterset
 340              $filter_action = param( /*$this->param_prefix.*/'filter', 'string', 'save' );
 341              // echo ' filter action: ['.$filter_action.'] ';
 342              switch( $filter_action )
 343              {
 344                  case 'restore':
 345                      return $this->restore_filterset();
 346                      /* BREAK */
 347  
 348                  case 'reset':
 349                      // We want to reset the memorized filterset:
 350                      global $Session;
 351                      $Session->delete( $this->filterset_name );
 352  
 353                      // Memorize global variables:
 354                      $this->set_filters( array(), true );
 355  
 356                      // We have applied no filterset:
 357                      return false;
 358                      /* BREAK */
 359              }
 360  
 361              /**
 362               * Filter preset
 363               */
 364              $this->filters['filter_preset'] = param( $this->param_prefix.'filter_preset', 'string', $this->default_filters['filter_preset'], true );
 365  
 366              // Activate preset default filters if necessary:
 367              $this->activate_preset_filters();
 368          }
 369  
 370  
 371          // fp> TODO: param( 'loc', 'string', '', true );                            // Locale of the posts (all by default)
 372  
 373  
 374          /*
 375           * Blog & Chapters/categories restrictions:
 376           */
 377          // Get chapters/categories (and compile those values right away)
 378          param_compile_cat_array( /* TODO: check $this->Blog->ID == 1 ? 0 :*/ !is_null( $this->Blog ) ? $this->Blog->ID : 0,
 379                                  $this->default_filters['cat_modifier'], $this->default_filters['cat_array'] );
 380  
 381          $this->filters['cat_array'] = get_param( 'cat_array' );
 382          $this->filters['cat_modifier'] = get_param( 'cat_modifier' );
 383  
 384          $this->filters['cat_focus'] = param( $this->param_prefix.'cat_focus', 'string', $this->default_filters['cat_focus'], true );
 385  
 386  
 387          /*
 388           * Restrict to selected tags:
 389           */
 390          $this->filters['tags'] = param( $this->param_prefix.'tag', 'string', $this->default_filters['tags'], true );
 391  
 392  
 393          /*
 394           * Restrict to selected authors:
 395           */
 396          // List of authors users IDs to restrict to
 397          $this->filters['authors'] = param( $this->param_prefix.'author', '/^-?[0-9]+(,[0-9]+)*$/', $this->default_filters['authors'], true );
 398          // List of authors users logins to restrict to
 399          $this->filters['authors_login'] = param( $this->param_prefix.'author_login', '/^-?[A-Za-z0-9_\.]+(,[A-Za-z0-9_\.]+)*$/', $this->default_filters['authors_login'], true );
 400  
 401  
 402          /*
 403           * Restrict to selected assignees:
 404           */
 405          // List of assignees users IDs to restrict to
 406          $this->filters['assignees'] = param( $this->param_prefix.'assgn', '/^(-|-[0-9]+|[0-9]+)(,[0-9]+)*$/', $this->default_filters['assignees'], true );
 407          // List of assignees users logins to restrict to
 408          $this->filters['assignees_login'] = param( $this->param_prefix.'assgn_login', '/^(-|-[A-Za-z0-9_\.]+|[A-Za-z0-9_\.]+)(,[A-Za-z0-9_\.]+)*$/', $this->default_filters['assignees_login'], true );
 409  
 410  
 411          /*
 412           * Restrict to selected author or assignee:
 413           */
 414          $this->filters['author_assignee'] = param( $this->param_prefix.'author_assignee', '/^[0-9]+$/', $this->default_filters['author_assignee'], true );
 415  
 416  
 417          /*
 418           * Restrict to selected locale:
 419           */
 420          $this->filters['lc'] = param( $this->param_prefix.'lc', 'string', $this->default_filters['lc'], true );
 421  
 422  
 423          /*
 424           * Restrict to selected statuses:
 425           */
 426          $this->filters['statuses'] = param( $this->param_prefix.'status', '/^(-|-[0-9]+|[0-9]+)(,[0-9]+)*$/', $this->default_filters['statuses'], true );      // List of statuses to restrict to
 427  
 428          /*
 429           * Restrict to selected types:
 430           */
 431          $this->filters['types'] = param( $this->param_prefix.'types', '/^(-|-[0-9]+|[0-9]+)(,[0-9]+)*$/', $this->default_filters['types'], true );      // List of types to restrict to
 432  
 433  
 434          /*
 435           * Restrict by keywords
 436           */
 437          $this->filters['keywords'] = param( $this->param_prefix.'s', 'string', $this->default_filters['keywords'], true );         // Search string
 438          $this->filters['phrase'] = param( $this->param_prefix.'sentence', 'string', $this->default_filters['phrase'], true );         // Search for sentence or for words
 439          $this->filters['exact'] = param( $this->param_prefix.'exact', 'integer', $this->default_filters['exact'], true );        // Require exact match of title or contents
 440  
 441  
 442          /*
 443           * Specific Item selection?
 444           */
 445          $this->filters['post_ID'] = param( $this->param_prefix.'p', 'integer', $this->default_filters['post_ID'] );          // Specific post number to display
 446          $this->filters['post_title'] = param( $this->param_prefix.'title', 'string', $this->default_filters['post_title'] );      // urtitle of post to display
 447  
 448  
 449          /*
 450           * multiple Item selection ?
 451           */
 452          $this->filters['post_ID_list'] = param( $this->param_prefix.'pl', 'string', $this->default_filters['post_ID_list'] );  // Specific list of post numbers to display
 453  
 454  
 455          $this->single_post = !empty($this->filters['post_ID']) || !empty($this->filters['post_title']);
 456  
 457  
 458          /*
 459           * If a timeframe is specified in the querystring, restrict to that timeframe:
 460           */
 461          $this->filters['ymdhms'] = param( $this->param_prefix.'m', '/^\d{4}(0[1-9]|1[0-2])?(?(1)(0[1-9]|[12][0-9]|3[01])?)(?(2)([01][0-9]|2[0-3])?)(?(3)([0-5][0-9]){0,2})$/', $this->default_filters['ymdhms'], true ); // YearMonth(Day) to display
 462          $this->filters['week'] = param( $this->param_prefix.'w', '/^(0?[0-9]|[1-4][0-9]|5[0-3])$/', $this->default_filters['week'], true ); // Week number (0?0-53)
 463  
 464          $this->filters['ymdhms_min'] = param_compact_date( $this->param_prefix.'dstart', $this->default_filters['ymdhms_min'], true, T_( 'Invalid date' ) ); // YearMonth(Day) to start at
 465          $this->filters['ymdhms_max'] = param_compact_date( $this->param_prefix.'dstop', $this->default_filters['ymdhms_max'], true, T_( 'Invalid date' ) ); // YearMonth(Day) to stop at
 466  
 467  
 468          // TODO: show_past/future should probably be wired on dstart/dstop instead on timestamps -> get timestamps out of filter perimeter
 469          // So far, these act as SILENT filters. They will not advertise their filtering in titles etc.
 470          $this->filters['ts_min'] = $this->default_filters['ts_min'];
 471          $this->filters['ts_max'] = $this->default_filters['ts_max'];
 472          if( is_null($this->default_filters['ts_min'])
 473              && is_null($this->default_filters['ts_max'] ) )
 474          {    // We have not set a strict default -> we allow overridding:
 475              $show_past = param( $this->param_prefix.'show_past', 'integer', 0, true );
 476              $show_future = param( $this->param_prefix.'show_future', 'integer', 0, true );
 477              if( $show_past != $show_future )
 478              {    // There is a point in overridding:
 479                  $this->filters['ts_min'] = ( $show_past == 0 ) ? 'now' : '';
 480                  $this->filters['ts_max'] = ( $show_future == 0 ) ? 'now' : '';
 481              }
 482          }
 483  
 484          /*
 485           * Restrict to the statuses we want to show:
 486           */
 487          // Note: oftentimes, $show_statuses will have been preset to a more restrictive set of values
 488          $this->filters['visibility_array'] = param( $this->param_prefix.'show_statuses', 'array/string', $this->default_filters['visibility_array']
 489                          , true, false, true, false );    // Array of sharings to restrict to
 490  
 491          /*
 492           * Ordering:
 493           */
 494          $this->filters['order'] = param( $this->param_prefix.'order', '/^(ASC|asc|DESC|desc)$/', $this->default_filters['order'], true );        // ASC or DESC
 495          // This order style is OK, because sometimes the commentList is not displayed on a table so we cannot say we want to order by a specific column. It's not a crap.
 496          $this->filters['orderby'] = param( $this->param_prefix.'orderby', '/^([A-Za-z0-9_]+([ ,][A-Za-z0-9_]+)*)?$/', $this->default_filters['orderby'], true );   // list of fields to order by (TODO: change that crap)
 497  
 498          /*
 499           * Paging limits:
 500           */
 501          $this->filters['unit'] = param( $this->param_prefix.'unit', 'string', $this->default_filters['unit'], true );            // list unit: 'posts' or 'days'
 502  
 503          $this->filters['posts'] = param( $this->param_prefix.'posts', 'integer', $this->default_filters['posts'], true );             // # of units to display on the page
 504          $this->limit = $this->filters['posts']; // for compatibility with parent class
 505  
 506          // 'paged'
 507          $this->filters['page'] = param( $this->page_param, 'integer', 1, true );      // List page number in paged display
 508          $this->page = $this->filters['page'];
 509  
 510          if( param_errors_detected() )
 511          {
 512              return false;
 513          }
 514  
 515          if( $this->single_post )
 516          {    // We have requested a specific post
 517              // Do not attempt to save or load any filterset:
 518              return true;
 519          }
 520  
 521          //echo ' Got filters from URL?:'.($this->is_filtered() ? 'YES' : 'NO');
 522          //pre_dump( $this->default_filters );
 523          //pre_dump( $this->filters );
 524  
 525          if( $use_filters && $filter_action == 'save' )
 526          {
 527              $this->save_filterset();
 528          }
 529  
 530          return true;
 531      }
 532  
 533  
 534      /**
 535       *
 536       *
 537       * @todo count?
 538       */
 539  	function query_init()
 540      {
 541          global $current_User;
 542  
 543          if( empty( $this->filters ) )
 544          {    // Filters have not been set before, we'll use the default filterset:
 545              // If there is a preset filter, we need to activate its specific defaults:
 546              $this->filters['filter_preset'] = param( $this->param_prefix.'filter_preset', 'string', $this->default_filters['filter_preset'], true );
 547              $this->activate_preset_filters();
 548  
 549              // Use the default filters:
 550              $this->set_filters( $this->default_filters );
 551          }
 552  
 553  
 554          // echo '<br />ItemListLight query';
 555          //pre_dump( $this->filters );
 556  
 557          // GENERATE THE QUERY:
 558  
 559          /*
 560           * filtering stuff:
 561           */
 562          if( !is_null( $this->Blog ) )
 563          { // Get the posts only for current Blog
 564              $this->ItemQuery->where_chapter2( $this->Blog, $this->filters['cat_array'], $this->filters['cat_modifier'],
 565                                                                              $this->filters['cat_focus'] );
 566          }
 567          else // $this->Blog == NULL
 568          { // If we want to get the posts from all blogs
 569              // Save for future use (permission checks..)
 570              $this->ItemQuery->blog = 0;
 571              $this->ItemQuery->Blog = $this->Blog;
 572          }
 573          $this->ItemQuery->where_tags( $this->filters['tags'] );
 574          $this->ItemQuery->where_author( $this->filters['authors'] );
 575          $this->ItemQuery->where_author_logins( $this->filters['authors_login'] );
 576          $this->ItemQuery->where_assignees( $this->filters['assignees'] );
 577          $this->ItemQuery->where_assignees_logins( $this->filters['assignees_login'] );
 578          $this->ItemQuery->where_author_assignee( $this->filters['author_assignee'] );
 579          $this->ItemQuery->where_locale( $this->filters['lc'] );
 580          $this->ItemQuery->where_statuses( $this->filters['statuses'] );
 581          $this->ItemQuery->where_types( $this->filters['types'] );
 582          $this->ItemQuery->where_keywords( $this->filters['keywords'], $this->filters['phrase'], $this->filters['exact'] );
 583          $this->ItemQuery->where_ID( $this->filters['post_ID'], $this->filters['post_title'] );
 584          $this->ItemQuery->where_ID_list( $this->filters['post_ID_list'] );
 585          $this->ItemQuery->where_datestart( $this->filters['ymdhms'], $this->filters['week'],
 586                                             $this->filters['ymdhms_min'], $this->filters['ymdhms_max'],
 587                                             $this->filters['ts_min'], $this->filters['ts_max'] );
 588          $this->ItemQuery->where_datecreated( $this->filters['ts_created_max'] );
 589          $this->ItemQuery->where_visibility( $this->filters['visibility_array'] );
 590          $this->ItemQuery->where_featured( $this->filters['featured'] );
 591  
 592  
 593          /*
 594           * ORDER BY stuff:
 595           */
 596          if( $this->filters['post_ID_list'] && $this->filters['orderby'] == 'ID_list' )
 597          {
 598              $order_by = 'FIELD('.$this->Cache->dbIDname.', '.$this->filters['post_ID_list'].')';
 599          }
 600          elseif( $this->filters['orderby'] == 'ID_list' )
 601          {    // Use blog setting here because 'orderby' might be set to 'ID_list' as default filter
 602              $this->filters['orderby'] = $this->Blog->get_setting('orderby');
 603          }
 604  
 605          if( empty($order_by) )
 606          {
 607              $order_by = gen_order_clause( $this->filters['orderby'], $this->filters['order'], $this->Cache->dbprefix, $this->Cache->dbIDname );
 608          }
 609  
 610          $this->ItemQuery->order_by( $order_by );
 611  
 612  
 613  
 614          /*
 615           * GET TOTAL ROW COUNT:
 616           */
 617          if( $this->single_post )   // p or title
 618          { // Single post: no paging required!
 619              $this->total_rows = 1;
 620              $this->total_pages = 1;
 621              $this->page = 1;
 622          }
 623          /*
 624          elseif( !empty($this->filters['ymdhms']) // no restriction if we request a month... some permalinks may point to the archive!
 625          */
 626          elseif( $this->filters['unit'] == 'days'  // We are going to limit to x days: no limit
 627               || $this->filters['unit'] == 'all' ) // We want ALL results!
 628          {
 629              $this->total_rows = NULL; // unknown!
 630              $this->total_pages = 1;
 631              $this->page = 1;
 632          }
 633          elseif( $this->filters['unit'] == 'posts' )
 634          { // Calculate a count of the posts
 635              if( $this->ItemQuery->get_group_by() == '' )
 636              { // SQL query without GROUP BY clause
 637                  $sql_count = 'SELECT COUNT( DISTINCT '.$this->Cache->dbIDname.' )'
 638                      .$this->ItemQuery->get_from()
 639                      .$this->ItemQuery->get_where()
 640                      .$this->ItemQuery->get_limit();
 641              }
 642              else
 643              { // SQL query with GROUP BY clause, Summarize a count of each grouped result
 644                  $sql_count = 'SELECT SUM( cnt_tbl.cnt ) FROM (
 645                          SELECT COUNT( DISTINCT '.$this->Cache->dbIDname.' ) AS cnt '
 646                          .$this->ItemQuery->get_from()
 647                          .$this->ItemQuery->get_where()
 648                          .$this->ItemQuery->get_group_by()
 649                          .$this->ItemQuery->get_limit().'
 650                      ) AS cnt_tbl ';
 651              }
 652  
 653              parent::count_total_rows( $sql_count );
 654          }
 655          else
 656          {
 657              debug_die( 'Unhandled LIMITING mode in ItemList:'.$this->filters['unit'].' (paged mode is obsolete)' );
 658          }
 659  
 660  
 661          /*
 662           * Paging LIMITs:
 663           */
 664          if( $this->single_post )   // p or title
 665          { // Single post: no paging required!
 666          }
 667          /*
 668              fp> 2007-11-25 : a very high post count can now be configured in the admin for this. Default is 100.
 669              elseif( !empty($this->filters['ymdhms']) )
 670              { // no restriction if we request a month... some permalinks may point to the archive!
 671                  // echo 'ARCHIVE - no limits';
 672              }
 673          */
 674          elseif( $this->filters['unit'] == 'all' )
 675          {    // We want ALL results!
 676          }
 677          elseif( $this->filters['unit'] == 'posts' )
 678          {
 679              // TODO: dh> check if $limit is NULL!? - though it should not arrive at $page>1 then..
 680              // echo 'LIMIT POSTS ';
 681              $pgstrt = '';
 682              if( $this->page > 1 )
 683              { // We have requested a specific page number
 684                  $pgstrt = (intval($this->page) -1) * $this->limit. ', ';
 685              }
 686              $this->ItemQuery->LIMIT( $pgstrt.$this->limit );
 687          }
 688          elseif( $this->filters['unit'] == 'days' )
 689          { // We are going to limit to x days:
 690              // echo 'LIMIT DAYS ';
 691              if( empty( $this->filters['ymdhms_min'] ) )
 692              { // We have no start date, we'll display the last x days:
 693                  if( !empty($this->filters['keywords'])
 694                      || !empty($this->filters['cat_array'])
 695                      || !empty($this->filters['authors']) )
 696                  { // We are in DAYS mode but we can't restrict on these! (TODO: ?)
 697                      $limits = '';
 698                  }
 699                  else
 700                  { // We are going to limit to LAST x days:
 701                      $lastpostdate = $this->get_lastpostdate();
 702                      $lastpostdate = mysql2date('Y-m-d 00:00:00',$lastpostdate);
 703                      $lastpostdate = mysql2date('U',$lastpostdate);
 704                      // go back x days
 705                      $otherdate = date('Y-m-d H:i:s', ($lastpostdate - (($this->limit-1) * 86400)));
 706                      $this->ItemQuery->WHERE_and( $this->Cache->dbprefix.'datestart > \''. $otherdate.'\'' );
 707                  }
 708              }
 709              else
 710              { // We have a start date, we'll display x days starting from that point:
 711                  // $dstart_mysql has been calculated earlier
 712  
 713                  // TODO: this is redundant with previous dstart processing:
 714                  // Add trailing 0s: YYYYMMDDHHMMSS
 715                  $dstart0 = $this->filters['ymdhms_min'].'00000000000000';
 716  
 717                  $dstart_mysql = substr($dstart0,0,4).'-'.substr($dstart0,4,2).'-'.substr($dstart0,6,2).' '
 718                                                  .substr($dstart0,8,2).':'.substr($dstart0,10,2).':'.substr($dstart0,12,2);
 719                  $dstart_ts = mysql2timestamp( $dstart_mysql );
 720                  // go forward x days
 721                  $enddate_ts = date('Y-m-d H:i:s', ($dstart_ts + ($this->limit * 86400)));
 722                  $this->ItemQuery->WHERE_and( $this->Cache->dbprefix.'datestart < \''. $enddate_ts.'\'' );
 723              }
 724          }
 725          else
 726              debug_die( 'Unhandled LIMITING mode in ItemList:'.$this->filters['unit'].' (paged mode is obsolete)' );
 727      }
 728  
 729  
 730    /**
 731       * Run Query: GET DATA ROWS *** LIGHT ***
 732       *
 733       * Contrary to ItemList2, we only do 1 query here and we extract only a few selected params.
 734       * Basically all we want is being able to generate permalinks.
 735       */
 736  	function query()
 737      {
 738          global $DB;
 739  
 740          if( !is_null( $this->rows ) )
 741          { // Query has already executed:
 742              return;
 743          }
 744  
 745          // INNIT THE QUERY:
 746          $this->query_init();
 747  
 748          // QUERY:
 749          $this->sql = 'SELECT DISTINCT '.$this->Cache->dbIDname.', post_datestart, post_datemodified, post_title, post_url,
 750                                      post_excerpt, post_urltitle, post_canonical_slug_ID, post_tiny_slug_ID, post_main_cat_ID, post_ptyp_ID '
 751                                      .$this->ItemQuery->get_from()
 752                                      .$this->ItemQuery->get_where()
 753                                      .$this->ItemQuery->get_group_by()
 754                                      .$this->ItemQuery->get_order_by()
 755                                      .$this->ItemQuery->get_limit();
 756  
 757          // echo $DB->format_query( $this->sql );
 758  
 759          parent::query( false, false, false, 'ItemListLight::query()' );
 760      }
 761  
 762  
 763  
 764  
 765      /**
 766       * Get datetime of the last post/item
 767       * @todo dh> Optimize this, if this can be said after having done {@link query()} already.
 768       * @todo dh> Cache result
 769       * @param string Date format (see {@link date()})
 770       * @return string 'Y-m-d H:i:s' formatted; If there are no items this will be {@link $localtimenow}.
 771       */
 772  	function get_lastpostdate($dateformat = 'Y-m-d H:i:s')
 773      {
 774          global $localtimenow, $DB;
 775  
 776          if( empty( $this->filters ) )
 777          {    // Filters have no been set before, we'll use the default filterset:
 778              // echo ' Query:Setting default filterset ';
 779              $this->set_filters( $this->default_filters );
 780          }
 781  
 782          // GENERATE THE QUERY:
 783  
 784          // The SQL Query object:
 785          $lastpost_ItemQuery = new ItemQuery( $this->Cache->dbtablename, $this->Cache->dbprefix, $this->Cache->dbIDname );
 786  
 787          /*
 788           * filtering stuff:
 789           */
 790          $lastpost_ItemQuery->where_chapter2( $this->Blog, $this->filters['cat_array'], $this->filters['cat_modifier'],
 791                                                                                   $this->filters['cat_focus']  );
 792          $lastpost_ItemQuery->where_author( $this->filters['authors'] );
 793          $lastpost_ItemQuery->where_author_logins( $this->filters['authors_login'] );
 794          $lastpost_ItemQuery->where_assignees( $this->filters['assignees'] );
 795          $lastpost_ItemQuery->where_assignees_logins( $this->filters['assignees_login'] );
 796          $lastpost_ItemQuery->where_locale( $this->filters['lc'] );
 797          $lastpost_ItemQuery->where_statuses( $this->filters['statuses'] );
 798          $lastpost_ItemQuery->where_types( $this->filters['types'] );
 799          $lastpost_ItemQuery->where_keywords( $this->filters['keywords'], $this->filters['phrase'], $this->filters['exact'] );
 800          $lastpost_ItemQuery->where_ID( $this->filters['post_ID'], $this->filters['post_title'] );
 801          $lastpost_ItemQuery->where_datestart( $this->filters['ymdhms'], $this->filters['week'],
 802                                             $this->filters['ymdhms_min'], $this->filters['ymdhms_max'],
 803                                             $this->filters['ts_min'], $this->filters['ts_max'] );
 804          $lastpost_ItemQuery->where_visibility( $this->filters['visibility_array'] );
 805  
 806          /*
 807           * order by stuff:
 808           * LAST POST FIRST!!! (That's the whole point!)
 809           */
 810          $lastpost_ItemQuery->order_by( $this->Cache->dbprefix.'datestart DESC' );
 811  
 812          /*
 813           * Paging limits:
 814           * ONLY THE LAST POST!!!
 815           */
 816          $lastpost_ItemQuery->LIMIT( '1' );
 817  
 818          // Select the datestart:
 819          $lastpost_ItemQuery->select( $this->Cache->dbprefix.'datestart' );
 820  
 821          $lastpostdate = $DB->get_var( $lastpost_ItemQuery->get(), 0, 0, 'Get last post date' );
 822  
 823          if( empty( $lastpostdate ) )
 824          {
 825              // echo 'we have no last item';
 826              $lastpostdate = date($dateformat, $localtimenow);
 827          }
 828          elseif( $dateformat != 'Y-m-d H:i:s' )
 829          {
 830              $lastpostdate = date($dateformat, strtotime($lastpostdate));
 831          }
 832  
 833          // echo $lastpostdate;
 834  
 835          return $lastpostdate;
 836      }
 837  
 838  
 839      /**
 840       * Generate a title for the current list, depending on its filtering params
 841       *
 842       * @todo cleanup some displays
 843       * @todo implement HMS part of YMDHMS
 844       *
 845       * @return array List of titles to display, which are escaped for HTML display
 846       *               (dh> only checked this for 'authors'/?authors=, where the output was not escaped)
 847       */
 848  	function get_filter_titles( $ignore = array(), $params = array() )
 849      {
 850          global $month;
 851  
 852          $params = array_merge( array(
 853                  'category_text' => T_('Category').': ',
 854                  'categories_text' => T_('Categories').': ',
 855                  // 'tag_text' => T_('Tag').': ',
 856                  'tags_text' => T_('Tags').': ',
 857              ), $params );
 858  
 859          if( empty( $this->filters ) )
 860          {    // Filters have no been set before, we'll use the default filterset:
 861              // echo ' setting default filterset ';
 862              $this->set_filters( $this->default_filters );
 863          }
 864  
 865          $title_array = array();
 866  
 867          if( $this->single_post )
 868          {    // We have requested a specific post:
 869              // Should be in first position
 870              $Item = & $this->get_by_idx( 0 );
 871  
 872              if( is_null($Item) )
 873              {
 874                  $title_array[] = T_('Invalid request');
 875              }
 876              else
 877              {
 878                  $title_array[] = $Item->get_titletag();
 879              }
 880              return $title_array;
 881          }
 882  
 883  
 884          // CATEGORIES:
 885          if( !empty($this->filters['cat_array']) )
 886          { // We have requested specific categories...
 887              $cat_names = array();
 888              $ChapterCache = & get_ChapterCache();
 889              foreach( $this->filters['cat_array'] as $cat_ID )
 890              {
 891                  if( ($my_Chapter = & $ChapterCache->get_by_ID($cat_ID, false) ) !== false )
 892                  { // It is almost never meaningful to die over an invalid cat when generating title
 893                      $cat_names[] = $my_Chapter->name;
 894                  }
 895              }
 896              if( $this->filters['cat_modifier'] == '*' )
 897              {
 898                  $cat_names_string = '"'.implode( '" '.T_('and').' "', $cat_names ).'"';
 899              }
 900              else
 901              {
 902                  $cat_names_string = '"'.implode( '" '.T_('or').' "', $cat_names ).'"';
 903              }
 904              if( !empty( $cat_names_string ) )
 905              {
 906                  if( $this->filters['cat_modifier'] == '-' )
 907                  {
 908                      $cat_names_string = T_('All but ').' '.$cat_names_string;
 909                      $title_array['cats'] = $params['categories_text'].$cat_names_string;
 910                  }
 911                  else
 912                  {
 913                      if( count($this->filters['cat_array']) > 1 )
 914                          $title_array['cats'] = $params['categories_text'].$cat_names_string;
 915                      else
 916                          $title_array['cats'] = $params['category_text'].$cat_names_string;
 917                  }
 918              }
 919          }
 920  
 921  
 922          // ARCHIVE TIMESLOT:
 923          if( !empty($this->filters['ymdhms']) )
 924          {    // We have asked for a specific timeframe:
 925  
 926              $my_year = substr($this->filters['ymdhms'],0,4);
 927  
 928              if( strlen($this->filters['ymdhms']) > 4 )
 929              { // We have requested a month too:
 930                  $my_month = T_($month[substr($this->filters['ymdhms'],4,2)]);
 931              }
 932              else
 933              {
 934                  $my_month = '';
 935              }
 936  
 937              // Requested a day?
 938              $my_day = substr($this->filters['ymdhms'],6,2);
 939  
 940              $arch = T_('Archives for').': '.$my_month.' '.$my_year;
 941  
 942              if( !empty( $my_day ) )
 943              {    // We also want to display a day
 944                  $arch .= ', '.$my_day;
 945              }
 946  
 947              if( !empty($this->filters['week']) || ($this->filters['week'] === 0) ) // Note: week # can be 0
 948              {    // We also want to display a week number
 949                  $arch .= ', '.T_('week').' '.$this->filters['week'];
 950              }
 951  
 952              $title_array['ymdhms'] = $arch;
 953          }
 954  
 955  
 956          // KEYWORDS:
 957          if( ! empty( $this->filters['keywords'] ) )
 958          {
 959              if( $this->filters['phrase'] == 'OR' || $this->filters['phrase'] == 'AND' )
 960              {
 961                  $keywords = trim( preg_replace( '/("|, *)/', ' ', $this->filters['keywords'] ) );
 962                  $keywords = explode( ' ', $keywords );
 963                  $keywords_count = count( $keywords );
 964                  $keywords = '"'.implode( '" '.( $this->filters['phrase'] == 'OR' ? T_('or') : T_('and') ).' "', $keywords ).'"';
 965              }
 966              else
 967              {
 968                  $keywords = '"'.$this->filters['keywords'].'"';
 969                  $keywords_count = 1;
 970              }
 971              $title_array['keywords'] = ( $keywords_count == 1 ? T_('Keyword') : T_('Keywords') ).': '
 972                  .( $this->filters['exact'] ? T_('Exact match').' ' : '' )
 973                  .$keywords;
 974          }
 975  
 976  
 977          // TAGS:
 978          if( !empty($this->filters['tags']) )
 979          {
 980              $title_array[] = $params['tags_text'].$this->filters['tags'];
 981          }
 982  
 983  
 984          // AUTHORS:
 985          if( ! empty( $this->filters['authors'] ) || ! empty( $this->filters['authors_login'] ) )
 986          {
 987              $authors = trim( $this->filters['authors'].','.get_users_IDs_by_logins( $this->filters['authors_login'] ), ',' );
 988              $exclude_authors = false;
 989              if( substr( $authors, 0, 1 ) == '-' )
 990              { // Authors are excluded
 991                  $authors = substr( $authors, 1 );
 992                  $exclude_authors = true;
 993              }
 994              $authors = preg_split( '~\s*,\s*~', $authors, -1, PREG_SPLIT_NO_EMPTY );
 995              $author_names = array();
 996              if( $authors )
 997              {
 998                  $UserCache = & get_UserCache();
 999                  foreach( $authors as $author_ID )
1000                  {
1001                      if( $tmp_User = $UserCache->get_by_ID( $author_ID, false, false ) )
1002                      {
1003                          $author_names[] = $tmp_User->get_identity_link( array( 'link_text' => 'login' ) );
1004                      }
1005                  }
1006              }
1007              if( count( $author_names ) > 0 )
1008              { // Display info of filter by authors
1009                  if( $exclude_authors )
1010                  { // 
1011                      $title_array[] = sprintf( T_('All authors except: %s'), implode( ' '.T_('and').' ', $author_names ) );
1012                  }
1013                  else
1014                  { // 
1015                      $title_array[] = ( count( $author_names ) == 1 ? T_('Author') : T_('Authors') )
1016                          .': '.implode( ', ', $author_names );
1017                  }
1018              }
1019          }
1020  
1021  
1022          // ASSIGNEES:
1023          if( ! empty( $this->filters['assignees'] ) || ! empty( $this->filters['assignees_login'] ) )
1024          {
1025              if( $this->filters['assignees'] == '-' )
1026              {
1027                  $title_array[] = T_('Not assigned');
1028              }
1029              else
1030              {
1031                  $assignees = trim( $this->filters['assignees'].','.get_users_IDs_by_logins( $this->filters['assignees_login'] ), ',' );
1032                  $assignees = preg_split( '~\s*,\s*~', $assignees, -1, PREG_SPLIT_NO_EMPTY );
1033                  $assignees_names = array();
1034                  if( $assignees )
1035                  {
1036                      $UserCache = & get_UserCache();
1037                      foreach( $assignees as $user_ID )
1038                      {
1039                          if( $tmp_User = & $UserCache->get_by_ID( $user_ID, false, false ) )
1040                          {
1041                              $assignees_names[] = $tmp_User->get_identity_link( array( 'link_text' => 'login' ) );
1042                          }
1043                      }
1044                  }
1045                  $title_array[] = T_('Assigned to').': '.implode( ', ', $assignees_names );
1046              }
1047          }
1048  
1049  
1050          // LOCALE:
1051          if( $this->filters['lc'] != 'all' )
1052          {
1053              $title_array[] = T_('Locale').': '.$this->filters['lc'];
1054          }
1055  
1056  
1057          // EXTRA STATUSES:
1058          if( !empty($this->filters['statuses']) )
1059          {
1060              if( $this->filters['statuses'] == '-' )
1061              {
1062                  $title_array[] = T_('Without status');
1063              }
1064              else
1065              {
1066                  $status_IDs = explode( ',', $this->filters['statuses'] );
1067                  $ItemStatusCache = & get_ItemStatusCache();
1068                  $statuses = array();
1069                  foreach( $status_IDs as $status_ID )
1070                  {
1071                      if( $ItemStatus = & $ItemStatusCache->get_by_ID( $status_ID ) )
1072                      {
1073                          $statuses[] = $ItemStatus->get_name();
1074                      }
1075                  }
1076                  $title_array[] = ( count( $statuses ) > 1 ? T_('Statuses') : T_('Status') )
1077                      .': '.implode( ', ', $statuses );
1078              }
1079          }
1080  
1081  
1082          // SHOW STATUSES
1083          if( !in_array( 'visibility', $ignore ) )
1084          {
1085              $post_statuses = get_visibility_statuses();
1086              if( count( $this->filters['visibility_array'] ) != count( $post_statuses ) )
1087              { // Display it only when visibility filter is changed
1088                  $status_titles = array();
1089                  foreach( $this->filters['visibility_array'] as $status )
1090                  {
1091                      $status_titles[] = $post_statuses[$status];
1092                  }
1093                  $title_array[] = T_('Visibility').': '.implode( ', ', $status_titles );
1094              }
1095          }
1096  
1097  
1098          // START AT
1099          if( !empty($this->filters['ymdhms_min'] ) )
1100          {
1101              $title_array['ymdhms_min'] = T_('Start at').': '.$this->filters['ymdhms_min'] ;
1102          }
1103          if( !empty($this->filters['ts_min'] ) )
1104          {
1105              if( $this->filters['ts_min'] == 'now' )
1106              {
1107                  $title_array['ts_min'] = T_('Hide past');
1108              }
1109              else
1110              {
1111                  $title_array['ts_min'] = T_('Start at').': '.$this->filters['ts_min'];
1112              }
1113          }
1114  
1115  
1116          // STOP AT
1117          if( !empty($this->filters['ymdhms_max'] ) )
1118          {
1119              $title_array['ymdhms_max'] = T_('Stop at').': '.$this->filters['ymdhms_max'];
1120          }
1121          if( !empty($this->filters['ts_max'] ) )
1122          {
1123              if( $this->filters['ts_max'] == 'now' )
1124              {
1125                  if( !in_array( 'hide_future', $ignore ) )
1126                  {
1127                      $title_array['ts_max'] = T_('Hide future');
1128                  }
1129              }
1130              else
1131              {
1132                  $title_array['ts_max'] = T_('Stop at').': '.$this->filters['ts_max'];
1133              }
1134          }
1135  
1136  
1137          // LIMIT TO
1138          if( $this->single_post )   // p or title
1139          { // Single post: no paging required!
1140          }
1141          elseif( !empty($this->filters['ymdhms']) )
1142          { // no restriction if we request a month... some permalinks may point to the archive!
1143          }
1144          elseif( $this->filters['unit'] == 'posts' || $this->filters['unit'] == 'all' )
1145          { // We're going to page, so there's no real limit here...
1146          }
1147          elseif( $this->filters['unit'] == 'days' )
1148          { // We are going to limit to x days:
1149              // echo 'LIMIT DAYS ';
1150              if( empty( $this->filters['ymdhms_min'] ) )
1151              { // We have no start date, we'll display the last x days:
1152                  if( !empty($this->filters['keywords'])
1153                      || !empty($this->filters['cat_array'])
1154                      || !empty($this->filters['authors']) )
1155                  { // We are in DAYS mode but we can't restrict on these! (TODO: ?)
1156                  }
1157                  else
1158                  { // We are going to limit to LAST x days:
1159                      // TODO: rename 'posts' to 'limit'
1160                      $title_array['posts'] = sprintf( T_('Limited to %d last days'), $this->limit );
1161                  }
1162              }
1163              else
1164              { // We have a start date, we'll display x days starting from that point:
1165                  $title_array['posts'] = sprintf( T_('Limited to %d days'), $this->limit );
1166              }
1167          }
1168          else
1169          {
1170              debug_die( 'Unhandled LIMITING mode in ItemList:'.$this->filters['unit'].' (paged mode is obsolete)' );
1171          }
1172  
1173          return $title_array;
1174      }
1175  
1176  
1177      /**
1178       * Return total number of posts
1179       *
1180       * This is basically just a stub for backward compatibility
1181       *
1182       * @deprecated
1183       */
1184  	function get_total_num_posts()
1185      {
1186          return $this->total_rows;
1187      }
1188  
1189  
1190      /**
1191       * If the list is sorted by category...
1192       *
1193       * Note: this only supports one level of categories (nested cats will be flatened)
1194       */
1195      function & get_category_group()
1196      {
1197          global $row;
1198  
1199          if( empty( $this->current_Obj ) )
1200          {    // Very first call
1201              // Do a normal get_next()
1202              parent::get_next();
1203          }
1204  
1205          if( empty( $this->current_Obj ) )
1206          {    // We have reached the end of the list
1207              return $this->current_Obj;
1208          }
1209  
1210          $this->group_by_cat = 1;
1211  
1212          // Memorize main cat
1213          $this->main_cat_ID = $this->current_Obj->main_cat_ID;
1214  
1215          return $this->current_Obj;
1216      }
1217  
1218  
1219      /**
1220       * If the list is sorted by category...
1221        *
1222        * This is basically just a stub for backward compatibility
1223       */
1224      function & get_item()
1225      {
1226          if( $this->group_by_cat == 1 )
1227          {    // This is the first call to get_item() after get_category_group()
1228              $this->group_by_cat = 2;
1229              // Return the object we already got in get_category_group():
1230              return $this->current_Obj;
1231          }
1232  
1233          $Item = & $this->get_next();
1234  
1235          if( !empty($Item) && $this->group_by_cat == 2 && $Item->main_cat_ID != $this->main_cat_ID )
1236          {    // We have just hit a new category!
1237              $this->group_by_cat == 0; // For info only.
1238              $r = false;
1239              return $r;
1240          }
1241  
1242          //pre_dump( $Item );
1243  
1244          return $Item;
1245      }
1246  
1247  
1248      /**
1249       * Get the adverstised start date (does not include timestamp_min)
1250       *
1251       * Note: there is a priority order in the params to determine the start date:
1252       *  -dstart
1253       *  -week + m
1254       *  -m
1255       *  -dstop - x days
1256       * @see ItemQuery::where_datestart()
1257       */
1258  	function get_advertised_start_date()
1259      {
1260          if( $this->getting_adv_start_date )
1261          {    // We would be entering an infinite loop, stop now:
1262              // We cannot determine a start date, save an empty string (to differentiate from NULL)
1263              $this->advertised_start_date = '';
1264  
1265              // Reset anti infinite loop:
1266              $this->getting_adv_start_date = false;
1267  
1268              return $this->advertised_start_date;
1269          }
1270  
1271          // Anti infinite loop:
1272          $this->getting_adv_start_date = true;
1273  
1274  
1275          if( is_null( $this->advertised_start_date ) )
1276          {    // We haven't determined the start date yet:
1277  
1278              if( !empty( $this->filters['ymdhms_min'] ) )
1279              {    // We have requested start date (8 digits)
1280                  $m = $this->filters['ymdhms_min'];
1281                  $this->advertised_start_date = mktime( 0, 0, 0, substr($m,4,2), substr($m,6,2), substr($m,0,4) );
1282              }
1283              elseif( !is_null($this->filters['week'])         // note: 0 is a valid week number
1284                          && !empty( $this->filters['ymdhms'] ) )
1285              {    // we want to restrict on a specific week
1286                  $this->advertised_start_date = get_start_date_for_week( substr($this->filters['ymdhms'],0,4), $this->filters['week'], locale_startofweek() );
1287              }
1288              elseif( strlen( $this->filters['ymdhms'] ) >= 4 )
1289              {    // We have requested an interval
1290                  $m = $this->filters['ymdhms'].'0101';
1291                  $this->advertised_start_date = mktime( 0, 0, 0, substr($m,4,2), substr($m,6,2), substr($m,0,4) );
1292              }
1293              elseif( $this->filters['unit'] == 'days'
1294                          && ($stop_date = $this->get_advertised_stop_date()) != '' )
1295              {    // We want to restrict on a specific number of days after the start date:
1296                  $this->advertised_start_date = $stop_date - ($this->limit-1) * 86400;
1297              }
1298              else
1299              {    // We cannot determine a start date, save an empty string (to differentiate from NULL)
1300                  $this->advertised_start_date = '';
1301              }
1302  
1303          }
1304  
1305          // Reset anti infinite loop:
1306          $this->getting_adv_start_date = false;
1307  
1308          return $this->advertised_start_date;
1309      }
1310  
1311  
1312      /**
1313       * Get the adverstised stop date (does not include timestamp_max)
1314       *
1315       * Note: there is a priority order in the params to determine the stop date.
1316       *  -dstop
1317       *  -week + m
1318       *  -m
1319       *  -dstart + x days
1320       */
1321  	function get_advertised_stop_date()
1322      {
1323          if( $this->getting_adv_stop_date )
1324          {    // We would be entering an infinite loop, stop now:
1325              // We cannot determine a stop date, save an empty string (to differentiate from NULL)
1326              $this->advertised_stop_date = '';
1327  
1328              // Reset anti infinite loop:
1329              $this->getting_adv_stop_date = false;
1330  
1331              return $this->advertised_stop_date;
1332          }
1333  
1334          // Anti infinite loop:
1335          $this->getting_adv_stop_date = true;
1336  
1337  
1338          if( is_null( $this->advertised_stop_date ) )
1339          {    // We haven't determined the stop date yet:
1340  
1341              if( !empty( $this->filters['ymdhms_max'] ) )
1342              {    // We have requested an end date (8 digits)
1343                  $m = $this->filters['ymdhms_max'];
1344                  $this->advertised_stop_date = mktime( 0, 0, 0, substr($m,4,2), substr($m,6,2), substr($m,0,4) );
1345              }
1346              elseif( !is_null($this->filters['week'])         // note: 0 is a valid week number
1347                          && !empty( $this->filters['ymdhms'] ) )
1348              {    // we want to restrict on a specific week
1349                  $this->advertised_stop_date = get_start_date_for_week( substr($this->filters['ymdhms'],0,4), $this->filters['week'], locale_startofweek() );
1350                  $this->advertised_stop_date += 518400; // + 6 days
1351              }
1352              elseif( !empty( $this->filters['ymdhms'] ) )
1353              {    // We want to restrict on an interval:
1354                  if( strlen( $this->filters['ymdhms'] ) >= 8 )
1355                  {    // We have requested a day interval
1356                      $m = $this->filters['ymdhms'];
1357                      $this->advertised_stop_date = mktime( 0, 0, 0, substr($m,4,2), substr($m,6,2), substr($m,0,4) );
1358                  }
1359                  elseif( strlen( $this->filters['ymdhms'] ) == 6 )
1360                  { // We want to go to the end of the month:
1361                      $m = $this->filters['ymdhms'];
1362                      $this->advertised_stop_date = mktime( 0, 0, 0, substr($m,4,2)+1, 0, substr($m,0,4) ); // 0th day of next mont = last day of month
1363                  }
1364                  elseif( strlen( $this->filters['ymdhms'] ) == 4 )
1365                  { // We want to go to the end of the year:
1366                      $m = $this->filters['ymdhms'];
1367                      $this->advertised_stop_date = mktime( 0, 0, 0, 12, 31, substr($m,0,4) );
1368                  }
1369              }
1370              elseif( $this->filters['unit'] == 'days'
1371                          && ($start_date = $this->get_advertised_start_date()) != '' )
1372              {    // We want to restrict on a specific number of days after the start date:
1373                  $this->advertised_stop_date = $start_date + ($this->limit-1) * 86400;
1374              }
1375              else
1376              {    // We cannot determine a stop date, save an empty string (to differentiate from NULL)
1377                  $this->advertised_stop_date = '';
1378              }
1379  
1380          }
1381  
1382          // Reset anti infinite loop:
1383          $this->getting_adv_stop_date = false;
1384  
1385          return $this->advertised_stop_date;
1386      }
1387  
1388  
1389      /**
1390       * Make sure date displaying starts at the beginning of the current filter interval
1391       *
1392       * Note: we're talking about strict dates (no times involved)
1393       */
1394  	function set_start_date( )
1395      {
1396          $start_date = $this->get_advertised_start_date();
1397  
1398          if( !empty( $start_date ) )
1399          {    // Memorize the last displayed as the day BEFORE the one we're going to display
1400              //echo ' start at='.date( locale_datefmt(), $start_date );
1401              $this->last_displayed_date = $start_date - 86400;
1402          }
1403      }
1404  
1405  
1406      /**
1407       * Template function: display potentially remaining empty days until the end of the filter interval
1408       *
1409       * @param string string to display before the date (if changed)
1410       * @param string string to display after the date (if changed)
1411       * @param string date/time format: leave empty to use locale default time format
1412       */
1413  	function dates_to_end( $before_empty_day = '<h2>', $after_empty_day = '</h2>', $format = '' )
1414      {
1415          $stop_date = $this->get_advertised_stop_date();
1416  
1417          if( !is_null( $stop_date ) )
1418          {    // There is a stop date, we want to display days:
1419              //echo ' - stop at='.date( locale_datefmt(), $stop_date );
1420              //echo ' - last displayed='.date( locale_datefmt(), $this->last_displayed_date );
1421              while( $this->last_displayed_date < $stop_date )
1422              {
1423                  $this->last_displayed_date += 86400;    // Add one day's worth of seconds
1424                  echo date_sprintf( $before_empty_day, $this->last_displayed_date )
1425                          .date_i18n( $format, $this->last_displayed_date )
1426                          .date_sprintf( $after_empty_day, $this->last_displayed_date );
1427              }
1428          }
1429      }
1430  
1431  
1432      /**
1433       * Template tag: Display the date if it has changed since last call
1434       *
1435       * Optionally also displays empty dates in between.
1436       *
1437       * @param array
1438       */
1439  	function date_if_changed( $params = array() )
1440      {
1441          if( $this->current_Obj->ptyp_ID == 1000 )
1442          {    // This is not applicable to pages
1443              return;
1444          }
1445  
1446          // Make sure we are not missing any param:
1447          $params = array_merge( array(
1448                  'before'      => '<h2>',
1449                  'after'       => '</h2>',
1450                  'empty_day_display' => false,
1451                  'empty_day_before' => '<h2>',
1452                  'empty_day_after'  => '</h2>',
1453                  'date_format' => '#',
1454              ), $params );
1455  
1456          // Get a timestamp for the date WITHOUT the time:
1457          $current_item_date = mysql2datestamp( $this->current_Obj->issue_date );
1458  
1459          if( $current_item_date != $this->last_displayed_date )
1460          {    // Date has changed...
1461  
1462  
1463              if( $params['date_format'] == '#' )
1464              {    // No format specified, use default locale format:
1465                  $params['date_format'] = locale_datefmt();
1466              }
1467  
1468              if( $params['empty_day_display'] && !empty($this->last_displayed_date) )
1469              {    // We want to display ALL dates from the previous to the current:
1470                  while( $this->last_displayed_date < $current_item_date-86400 )
1471                  {
1472                      $this->last_displayed_date += 86400;    // Add one day's worth of seconds
1473                      echo date_sprintf( $params['empty_day_before'], $this->last_displayed_date )
1474                              .date_i18n( $params['date_format'], $this->last_displayed_date )
1475                              .date_sprintf( $params['empty_day_after'], $this->last_displayed_date );
1476                  }
1477              }
1478  
1479              // Display the new current date:
1480              echo date_sprintf( $params['before'], $this->last_displayed_date )
1481                      .date_i18n( $params['date_format'], $current_item_date )
1482                      .date_sprintf( $params['after'], $this->last_displayed_date );
1483  
1484              $this->last_displayed_date = $current_item_date;
1485          }
1486      }
1487  
1488  
1489      /**
1490       * Template tag
1491       */
1492  	function page_links( $params = array() )
1493      {
1494          $default_params = array(
1495                  'block_start' => '<p class="center">',
1496                  'block_end' => '</p>',
1497                  'block_single' => '',
1498                  'links_format' => '#',
1499                  'page_url' => '', // All generated links will refer to the current page
1500                  'prev_text' => '&lt;&lt;',
1501                  'next_text' => '&gt;&gt;',
1502                  'no_prev_text' => '',
1503                  'no_next_text' => '',
1504                  'list_prev_text' => '...',
1505                  'list_next_text' => '...',
1506                  'list_span' => 11,
1507                  'scroll_list_range' => 5,
1508              );
1509  
1510          // Use defaults + overrides:
1511          $params = array_merge( $default_params, $params );
1512  
1513          if( $this->total_pages <= 1 || $this->page > $this->total_pages )
1514          {    // Single page:
1515              echo $params['block_single'];
1516              return;
1517          }
1518  
1519          if( $params['links_format'] == '#' )
1520          {
1521              $params['links_format'] = '$prev$ $first$ $list_prev$ $list$ $list_next$ $last$ $next$';
1522          }
1523  
1524           if( $this->Blog->get_setting( 'paged_nofollowto' ) )
1525          {    // We prefer robots not to follow to pages:
1526              $this-> nofollow_pagenav = true;
1527          }
1528  
1529          echo $params['block_start'];
1530          echo $this->replace_vars( $params['links_format'], $params );
1531          echo $params['block_end'];
1532      }
1533  
1534  
1535  }
1536  
1537  ?>

title

Description

title

Description

title

Description

title

title

Body