<?php
// $Revision: 1.1.2.8 $
// ------------------------------------------------------------------------- //
//  XooNIps - Neuroinformatics Base Platform System                          //
//  Copyright (C) 2005-2011 RIKEN, Japan All rights reserved.                //
//  http://xoonips.sourceforge.jp/                                           //
// ------------------------------------------------------------------------- //
//  This program is free software; you can redistribute it and/or modify     //
//  it under the terms of the GNU General Public License as published by     //
//  the Free Software Foundation; either version 2 of the License, or        //
//  (at your option) any later version.                                      //
//                                                                           //
//  You may not change or alter any portion of this comment or credits       //
//  of supporting developers from this source code or any supporting         //
//  source code which is considered copyrighted (c) material of the          //
//  original comment or credit authors.                                      //
//                                                                           //
//  This program is distributed in the hope that it will be useful,          //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of           //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            //
//  GNU General Public License for more details.                             //
//                                                                           //
//  You should have received a copy of the GNU General Public License        //
//  along with this program; if not, write to the Free Software              //
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA //
// ------------------------------------------------------------------------- //
if ( ! defined( 'XOOPS_ROOT_PATH' ) ) {
  exit();
}

require_once dirname( __FILE__ ).'/xoonips_ranking.class.php';

class XooNIpsAdminRankingHandler extends XooNIpsRankingHandler {

  function XooNIpsAdminRankingHandler() {
    parent::XooNIpsRankingHandler();
  }

  /**
   * delete group ranking data for group deletion
   *
   * @access public
   * @param int $gid group id
   * @return bool false if failure
   */
  function deleteGroupRankings( $gid ) {
    $names = array(
      'active_group',
      'new_group',
      'sum_active_group',
      'sum_new_group',
    );
    // lock ranking data
    $h = $this->_lock();
    $criteria = new Criteria( 'gid', $gid );
    foreach ( $names as $name ) {
      if ( ! $this->handlers[$name]->deleteAll( $criteria ) ) {
        $this->_unlock( $h );
        return false;
      }
    }
    // unlock ranking data
    $this->_unlock( $h );
    return true;
  }

  /**
   * rebuild ranking data
   *
   * @access public
   * @return bool false if failure
   */
  function rebuild() {
    // lock ranking data
    $h = $this->_lock();
    if ( $h === false ) {
      return false;
    }
    // rebuild ranking
    $ret = $this->_recalc( false );
    // unlock ranking data
    $this->_unlock( $h );
    return $ret;
  }

  /**
   * create sum file
   *
   * @access public
   * @return string zip compressed sum file path
   */
  function create_sum_file() {
    // STEP1 : fill sum data from event_log during all time range
    //                                     v last_update
    //                   v sum_last_update       v now
    //        --------------log------------------+
    //        ---sum-----+
    //                   +-----------------------+  // add this to sum
    //   ranking_sum_last_update = now;
    //
    //   if ( days_enabled == true ){
    //                          +---cache----+      // before
    //       update cache.
    //                             +----cache----+  // after
    //    } else {
    //        ----------------------cache----+      // before
    //       copy sum to cache.
    //        ----------------------cache--------+  // after
    //    }
    //
    // lock ranking data
    $h = $this->_lock();
    if ( $h === false ) {
      return false;
    }
    // set ranking_sum_start, ranking_sum_last_update
    $config_names = array(
      'sum_start',
      'sum_last_update',
    );
    $config = array();
    foreach ( $config_names as $name ) {
      $config[$name] = $this->_get_config( $name );
    }
    if ( $config['sum_start'] == 0 ) {
      $field = 'MIN(timestamp)';
      $objs =& $this->handlers['event_log']->getObjects( null, false, $field );
      if ( count( $objs ) == 1 ) {
        $config['sum_start'] = $objs[0]->getExtraVar( $field );
        $this->_set_config( 'sum_start', $config['sum_start'] );
      }
    }
    if ( $config['sum_last_update'] == 0 ) {
      $config['sum_last_update'] = $config['sum_start'];
      $this->_set_config( 'sum_last_update', $config['sum_last_update'] );
    }
    // update sum table
    $now = time();
    $add_days_criteria = new CriteriaCompo();
    $sub_days_criteria = new CriteriaCompo();
    // condition : $sum_last_update <= timestamp and timestamp < $now
    $add_days_criteria->add( new Criteria( 'timestamp', $config['sum_last_update'], '>=' ) );
    $add_days_criteria->add( new Criteria( 'timestamp', $now, '<' ) );
    $this->_recalc_sql( $add_days_criteria, $sub_days_criteria, true );
    $config['sum_last_update'] = $now;
    $this->_set_config( 'sum_last_update', $config['sum_last_update'] );
    // synchronize ranking table
    $days_enabled = $this->_get_config( 'days_enabled' );
    if ( $days_enabled ) {
      $this->_recalc( true );
    } else {
      // copy data of ranking_sum_* table into ranking_* table.
      foreach ( $this->basenames as $basename ) {
        if ( ! $this->handlers[$basename]->deleteAll( null, true ) ) {
          die( 'fatal error in '.__FILE__.' at '.__LINE__ );
        }
        if ( ! $this->handlers[$basename]->copy_from_sum_table() ) {
          die( 'fatal error in '.__FILE__.' at '.__LINE__ );
        }
      }
    }
    // unlock ranking data
    $this->_unlock( $h );

    // STEP2 : create sum zip file from sum tables for downloading file
    // create zip file
    $dirutil =& xoonips_getutility( 'directory' );
    $zip_file_path = $dirutil->tempnam( $dirutil->get_tempdir(), 'xnp_ranking_zip' );
    if ( $zip_file_path === false ) {
      // faled to create empty zip file
      return false;
    }
    $zip =& xoonips_getutility( 'zip' );
    // open zip data
    $zip->open( $zip_file_path );
    // add sum table
    foreach ( $this->basenames as $basename ) {
      $tmp_file_path = $dirutil->get_template( 'xnp_ranking_sum_'.$basename );
      $fh = $dirutil->mkstemp( $tmp_file_path );
      if ( $fh === false ) {
        // faled to create temporary file
        $zip->close();
        unlink( $zip_file_path );
        return false;
      }
      $sum_basename = 'sum_'.$basename;
      $res =& $this->handlers[$sum_basename]->open();
      while ( $obj =& $this->handlers[$sum_basename]->getNext( $res ) ) {
        $cols = $this->handlers[$sum_basename]->get_columns();
        $ar = array();
        foreach ( $cols as $col ) {
          $val = $obj->getVar( $col, 'n' );
          $ar[] = is_numeric( $val ) ? $val : urlencode( $val );
        }
        fputs( $fh, implode( ',', $ar )."\n" );
      }
      fclose( $fh );
      $this->handlers[$sum_basename]->close( $res );
      $zip->add( $tmp_file_path, $basename );
      unlink( $tmp_file_path );
    }
    // add config data
    $tmp_file_path = $dirutil->get_template( 'xnp_ranking_config' );
    $fh = $dirutil->mkstemp( $tmp_file_path );
    if ( $fh === false ) {
      // faled to create temporary file
      $zip->close();
      unlink( $zip_file_path );
      return false;
    }
    foreach ( $config_names as $key ) {
      fputs( $fh, 'ranking_'.$key.','.$config[$key]."\n" );
    }
    fclose( $fh );
    $zip->add( $tmp_file_path, 'config' );
    unlink( $tmp_file_path );
    // close zip data
    $zip->close();
    return $zip_file_path;
  }

  /**
   * load sum file
   *
   * @access public
   * @param string $file_path uploaded sum file path
   * @return bool false if failure
   */
  function load_sum_file( $file_path ) {
    $config_names = array(
      'ranking_sum_last_update',
      'ranking_sum_start',
    );

    // lock ranking data
    $h = $this->_lock();
    if ( $h === false ) {
      return false;
    }

    $unzip =& xoonips_getutility( 'unzip' );
    if ( ! $unzip->open( $file_path ) ) {
      die( 'can\'t open file '.$uploadfile );
    }
    $filenames = $unzip->get_file_list();
    foreach ( $filenames as $name ) {
      if ( substr( $name, - 1 ) == '/' ) {
        // ignore directory
        continue;
      }
      $data = $unzip->get_data( $name );
      $lines = explode( "\n", $data );
      unset( $data );
      if ( $name == 'config' ) {
        foreach ( $lines as $line ) {
          if ( $line === '' ) {
            continue;
          }
          list( $key, $val ) = explode( ',', $line );
          if ( in_array( $key, $config_names ) ) {
            $ckey = str_replace( 'ranking_sum_', 'sum_', $key );
            $this->_set_config( $ckey, $val );
          }
        }
      } else if ( in_array( $name, $this->basenames ) ) {
        // write csv lines to sum table. must be post request
        $this->handlers['sum_'.$name]->deleteAll();
        foreach ( $lines as $line ) {
          if ( $line === '' ) {
            continue;
          }
          $ar = explode( ',', $line );
          $obj =& $this->handlers['sum_'.$name]->create();
          $cols = $this->handlers['sum_'.$name]->get_columns();
          foreach ( $cols as $num => $key ) {
            $val = $ar[$num];
            $val = is_numeric( $val ) ? floor( $val ) : urldecode( $val );
            $obj->set( $key, $val );
          }
          $this->handlers['sum_'.$name]->insert( $obj );
        }
      } else {
        die( 'unknown ranking data found '.$name );
      }
    }
    $unzip->close();
    // rebuild ranking
    $ret = $this->_recalc( false );
    // unlock ranking data
    $this->_unlock( $h );
    return $ret;
  }

  /**
   * clear sum data
   *
   * @access public
   * @return bool false if failure
   */
  function clear_sum_data() {
    $config_names = array(
      'sum_start',
      'sum_last_update',
    );

    // lock ranking data
    $h = $this->_lock();
    if ( $h === false ) {
      return false;
    }
    // clear sum data
    foreach ( $this->basenames as $basename ) {
      // must be post request
      $this->handlers['sum_'.$basename]->deleteAll();
    }
    foreach ( $config_names as $config_name ) {
      $this->_set_config( $config_name, 0 );
    }
    // rebuild ranking
    $res = $this->_recalc( false );
    // unlock ranking data
    $this->_unlock( $h );
    return $res;
  }
}

?>
