<?php
  
class newposts {
  
  var $ipsclass;
  var $last_time;
  var $forums;
  
  var $page_title = 'Новое';

  var $cache_expire = 120;
  // Расширение слишком узкого диапазона поиска, т.е. в кеш ляжет минимум информация за сутки
  // Нужно будет посмотреть паттерн использования этой функции и, возможно, расширить диапазон еще больше,
  // для уменьшения промахов по кешу
  var $time_delta_min = 86400;
  // не будем искать более чем за 4 суток
  // зависит от активности форума и паттерна просмотра последних тем. К примеру, если пользователи редко
  // смотря более 10 страниц по 50 тем, т.е. 500 тем, и в день создается по 50 тем, то можно поставить 
  // 10 дней. Чем выше значение, тем более тяжелый поиск возможен.
  var $time_delta_max = 345600;
  
  function auto_run()
  {
    $result = $this->load_cache();
    
    if (is_null($result))
    {
      $result = $this->search_topics();
      $this->save_cache($result);
    }
    
    $result = $this->filter_result($result);
    
    $out = $this->show_result($result);
    
    $this->ipsclass->vars['is_forum_view'] = 1;
    $this->ipsclass->print->add_output($out);
    $this->ipsclass->print->do_output( array( 'TITLE' => $this->page_title, 'JS' => 0 ) );
  }

  function show_result($result)
  {
    $count = count($result);
    
    $this->ipsclass->load_language('lang_forum');
    $this->ipsclass->load_template('skin_global');
    $this->ipsclass->load_template('skin_forum');
    $this->ipsclass->load_template('skin_search');

    require_once( ROOT_PATH."sources/action_public/forums.php" );
    $this->forum_class = new forums();
    $this->forum_class->ipsclass =& $this->ipsclass;
    
    $page = (int)$this->ipsclass->input['st'];
    
    $links = $this->ipsclass->build_pagelinks( array( 
                           'TOTAL_POSS'  => $count,
                           'PER_PAGE'    => $this->ipsclass->vars['display_max_topics'],
                           'CUR_ST_VAL'  => $page,
                           'BASE_URL'    => $this->ipsclass->get_url_by_id( 0, "?act=newposts", false),
                           ));

    if ($links)
    {
      $result = array_slice($result, $page, $this->ipsclass->vars['display_max_topics']);
    }
                           
    $out = $this->ipsclass->compiled_templates['skin_search']->start( array( 'SHOW_PAGES' => $links ) );
    
    if (count($result) > 0)
    {
      foreach( $result as $row )
      {
        //$out .= $this->ipsclass->compiled_templates['skin_forum']->render_forum_row( $row );
        $out .= $this->forum_class->render_entry($row);
      }
    }
    else
    {
      $out .= $this->ipsclass->compiled_templates['skin_search']->no_results_row( );
    }
    
    $out .= $this->ipsclass->compiled_templates['skin_search']->end_results_table( array( 'SHOW_PAGES' => $links ) );
    
    return $out;     
  }
  
  /**
  * @desc Фильтрация форумов на основе разрешенных форумов и времени последнего посещения
  * @param $result - неассоциативный массив топиков, сортированный по last_post DESC
  * @param $forums - неасс. массив с ID разрешенных форумов
  * @param $last_time - юникстайм времени последнего посещения
  */
  function filter_result($result)
  {
    $last_time = $this->get_lasttime();
    $forums = $this->get_searchable_forums();

    $f_result = array();
    foreach ($result as $row)
    {
      if (!in_array($row['forum_id'], $forums))
        continue;
      if ($row['last_post'] < $last_time)
        break;
      $f_result[] = $row;
    }

    return $f_result;
  }
  
  /**
  * @desc Поиск всех топиков за заданное время
  */
  function search_topics()
  {
    $last_time = $this->round_lastime( $this->get_lasttime() );
    
    $this->ipsclass->DB->simple_construct( array( 'select' => 't.*',
                            'from'   => 'topics t',
                            'where'  => "t.approved=1 AND t.state != 'link' AND t.last_post >= {$last_time}",
                            'order'  => "t.last_post DESC" ) );
    $this->ipsclass->DB->simple_exec();
    
    $topics = array();
    while($row = $this->ipsclass->DB->fetch_row())
    {
      $topics[] = $row;
    }

    return $topics;
  }
  
  /**
  * @desc Запись массива топиков в кеш
  */
  function save_cache($result)
  {
    $last_time = $this->round_lastime( $this->get_lasttime() );
    $unique_id = $this->uniq_id();    
    
    $this->ipsclass->DB->do_delete('search_results', "id = '{$unique_id}'");
    return $this->ipsclass->DB->do_insert( 'search_results', array (
                         'id'          => $unique_id,
                         'search_date' => time(),
                         'post_max'    => $last_time,
                         'member_id'   => $this->ipsclass->member['id'],
                         'ip_address'  => $this->ipsclass->input['IP_ADDRESS'],
                         'query_cache' => serialize($result)
                         ));
  }
  
  /**
  * @desc Грузим кеш топиков и валидируем его на время жизни и на соответствие диапазону времени поиска
  */
  function load_cache()
  {
    $time = time() - $this->cache_expire;
    $last_time = $this->round_lastime( $this->get_lasttime() );
    $unique_id = $this->uniq_id();

    $this->ipsclass->DB->simple_construct( array( 'select' => '*',
                              'from'   => 'search_results',
                              'where'  => "id='{$unique_id}' AND search_date > {$time} AND post_max <= {$last_time}"  ) );
    $this->ipsclass->DB->simple_exec();
    $st = $this->ipsclass->DB->fetch_row();

    return ( is_array($st) && array_key_exists('id', $st) ? unserialize($st['query_cache']) : null);
  }
  
  /**
  * @desc Фиксирует last_time в границах min и max, установленных в свойствах класса  
  */
  function round_lastime($last_time)
  {
    $diff = time() - $last_time;

    if ( $diff < $this->time_delta_min)
      $last_time = time() - $this->time_delta_min;

    if ( $diff > $this->time_delta_max)
      $last_time = time() - $this->time_delta_max;
      
    return $last_time;
  }
  
  /**
  * @desc Время последнего визита на форум, начиная с которого нужно показывать топики
  */
  function get_lasttime()
  {
    if ($this->last_time)
      return $this->last_time;
    
    $last_time = $this->ipsclass->member['last_visit'];
    if ( $this->ipsclass->member['members_markers']['board'] > $last_time )
    {
      $last_time = $this->ipsclass->member['members_markers']['board'];
    }
    
    $this->last_time = (int)$last_time;
    return $this->last_time;
  }
  
  /**
  * @desc Получить форумы, доступные текущему пользователю для просмотра
  */
  function get_searchable_forums()
  {
    if ($this->forums)
      return $this->forums;
      
    $forums = array_values($this->ipsclass->forums->forums_get_all_allowed_forum_ids());
    $block_forums = explode( ',', $this->ipsclass->vars['vnp_block_forums'] );
    $forums = array_diff($forums, $block_forums);
    
    $this->forums = $forums;
    return $this->forums;
  }
  
  /**
  * @desc Уникальный ID поиска
  */
  function uniq_id()
  {
    // sort($forums, SORT_NUMERIC);
    // $unique_id = md5(implode(',', $forums));
    $unique_id = md5('newposts');
    return $unique_id;
  }
  
}
  
?>
