コード例 #1
0
 /**
  * Skip to previous/next Item
  *
  * If several items share the same spot (like same issue datetime) then they'll get all skipped at once.
  *
  * @param string prev | next  (relative to the current sort order)
  */
 function &get_prevnext_Item($direction = 'next', $types = '', $featured = NULL, $post_navigation = 'same_blog')
 {
     global $DB, $ItemCache, $posttypes_specialtypes;
     if (!$this->single_post) {
         // We are not on a single post:
         $r = NULL;
         return $r;
     }
     /**
      * @var Item
      */
     $current_Item = $this->get_by_idx(0);
     if (is_null($current_Item)) {
         // This happens if we are on a single post that we do not actually have permission to view
         $r = NULL;
         return $r;
     }
     if (in_array($current_Item->ptyp_ID, $posttypes_specialtypes)) {
         // We are not on a REGULAR post -- we cannot navigate:
         $r = NULL;
         return $r;
     }
     if (!empty($this->prevnext_Item[$direction][$post_navigation])) {
         return $this->prevnext_Item[$direction][$post_navigation];
     }
     $next_Query = new ItemQuery($this->Cache->dbtablename, $this->Cache->dbprefix, $this->Cache->dbIDname);
     // GENERATE THE QUERY:
     /*
      * filtering stuff:
      */
     $next_Query->where_chapter2($this->Blog, $this->filters['cat_array'], $this->filters['cat_modifier'], $this->filters['cat_focus']);
     $next_Query->where_author($this->filters['authors']);
     $next_Query->where_author_logins($this->filters['authors_login']);
     $next_Query->where_assignees($this->filters['assignees']);
     $next_Query->where_assignees_logins($this->filters['assignees_login']);
     $next_Query->where_author_assignee($this->filters['author_assignee']);
     $next_Query->where_locale($this->filters['lc']);
     $next_Query->where_statuses($this->filters['statuses']);
     // types param is kept only for the case when some custom types should be displayed
     $next_Query->where_types(!empty($types) ? $types : $this->filters['types']);
     $next_Query->where_keywords($this->filters['keywords'], $this->filters['phrase'], $this->filters['exact']);
     // $next_Query->where_ID( $this->filters['post_ID'], $this->filters['post_title'] );
     $next_Query->where_datestart($this->filters['ymdhms'], $this->filters['week'], $this->filters['ymdhms_min'], $this->filters['ymdhms_max'], $this->filters['ts_min'], $this->filters['ts_max']);
     $next_Query->where_visibility($this->filters['visibility_array']);
     $next_Query->where_featured($featured);
     /*
      * ORDER BY stuff:
      */
     if ($direction == 'next' && $this->filters['order'] == 'DESC' || $direction == 'prev' && $this->filters['order'] == 'ASC') {
         $order = 'DESC';
         $operator = ' < ';
     } else {
         $order = 'ASC';
         $operator = ' > ';
     }
     $orderby = str_replace(' ', ',', $this->filters['orderby']);
     $orderby_array = explode(',', $orderby);
     // Format each order param with default column names:
     $orderbyorder_array = preg_replace('#^(.+)$#', $this->Cache->dbprefix . '$1 ' . $order, $orderby_array);
     // Add an ID parameter to make sure there is no ambiguity in ordering on similar items:
     $orderbyorder_array[] = $this->Cache->dbIDname . ' ' . $order;
     $order_by = implode(', ', $orderbyorder_array);
     // Special case for RAND:
     $order_by = str_replace($this->Cache->dbprefix . 'RAND ', 'RAND() ', $order_by);
     $next_Query->order_by($order_by);
     // LIMIT to 1 single result
     $next_Query->LIMIT('1');
     // fp> TODO: I think some additional limits need to come back here (for timespans)
     /*
      * Position right after the current element depending on current sorting params
      *
      * If there are several items on the same issuedatetime for example, we'll then differentiate on post ID
      * WARNING: you cannot combine criterias with AND here; you need stuf like a>a0 OR (a=a0 AND b>b0)
      */
     switch ($orderby_array[0]) {
         case 'datestart':
             // special var name:
             $next_Query->WHERE_and($this->Cache->dbprefix . $orderby_array[0] . $operator . $DB->quote($current_Item->issue_date) . ' OR ( ' . $this->Cache->dbprefix . $orderby_array[0] . ' = ' . $DB->quote($current_Item->issue_date) . ' AND ' . $this->Cache->dbIDname . $operator . $current_Item->ID . ')');
             break;
         case 'title':
         case 'ptyp_ID':
         case 'datecreated':
         case 'datemodified':
         case 'last_touched_ts':
         case 'urltitle':
         case 'priority':
             $next_Query->WHERE_and($this->Cache->dbprefix . $orderby_array[0] . $operator . $DB->quote($current_Item->{$orderby_array[0]}) . ' OR ( ' . $this->Cache->dbprefix . $orderby_array[0] . ' = ' . $DB->quote($current_Item->{$orderby_array[0]}) . ' AND ' . $this->Cache->dbIDname . $operator . $current_Item->ID . ')');
             break;
         case 'order':
             // We have to integrate a rounding error margin
             $comp_order_value = $current_Item->order;
             $and_clause = '';
             if (is_null($comp_order_value)) {
                 // current Item has NULL order
                 if ($operator == ' < ') {
                     // This is needed when browsing through a descending ordered list and we reach the limit where orders are not set/NULL (ex: b2evo screenshots)
                     $and_clause .= $this->Cache->dbprefix . $orderby_array[0] . ' IS NULL AND ';
                 } else {
                     // This is needed when browsing through a descending ordered list and we want to browse back into the posts that have numbers (pb appears if first NULL posts is the highest ID)
                     $and_clause .= $this->Cache->dbprefix . $orderby_array[0] . ' IS NOT NULL OR ';
                 }
                 $and_clause .= $this->Cache->dbIDname . $operator . $current_Item->ID;
             } else {
                 if ($operator == ' < ') {
                     // This is needed when browsing through a descending ordered list and we reach the limit where orders are not set/NULL (ex: b2evo screenshots)
                     $and_clause .= $this->Cache->dbprefix . $orderby_array[0] . ' IS NULL OR ';
                 }
                 $and_clause .= $this->Cache->dbprefix . $orderby_array[0] . $operator . ($operator == ' < ' ? $comp_order_value - 1.0E-9 : $comp_order_value + 1.0E-9) . ' OR ( ' . $this->Cache->dbprefix . $orderby_array[0] . ($operator == ' < ' ? ' <= ' . ($comp_order_value + 1.0E-9) : ' >= ' . ($comp_order_value - 1.0E-9)) . ' AND ' . $this->Cache->dbIDname . $operator . $current_Item->ID . ')';
             }
             $next_Query->WHERE_and($and_clause);
             break;
         case 'RAND':
             // Random order. Don't show current item again.
             $next_Query->WHERE_and($this->Cache->dbprefix . 'ID <> ' . $current_Item->ID);
             break;
         default:
             echo 'WARNING: unhandled sorting: ' . htmlspecialchars($orderby_array[0]);
     }
     // GET DATA ROWS:
     // We are going to proceed in two steps (we simulate a subquery)
     // 1) we get the IDs we need
     // 2) we get all the other fields matching these IDs
     // This is more efficient than manipulating all fields at once.
     // Step 1:
     $step1_sql = 'SELECT DISTINCT ' . $this->Cache->dbIDname . $next_Query->get_from() . $next_Query->get_where() . $next_Query->get_group_by() . $next_Query->get_order_by() . $next_Query->get_limit();
     //echo $DB->format_query( $step1_sql );
     // Get list of the IDs we need:
     $next_ID = $DB->get_var($step1_sql, 0, 0, 'Get ID of next item');
     //pre_dump( $next_ID );
     // Step 2: get the item (may be NULL):
     $this->prevnext_Item[$direction][$post_navigation] =& $ItemCache->get_by_ID($next_ID, true, false);
     return $this->prevnext_Item[$direction][$post_navigation];
 }