<?php
// $Revision: 1.1.4.1.2.16 $
// ------------------------------------------------------------------------- //
//  XooNIps - Neuroinformatics Base Platform System                          //
//  Copyright (C) 2005-2008 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();
}

// for xnpGetFileInfo
include_once dirname( dirname( dirname( __FILE__ ) ) ).'/include/lib.php';

/**
 *
 * @brief data object of file
 *
 * @li getVar('file_id') :
 * @li getVar('item_id') :
 * @li getVar('original_file_name') :
 * @li getVar('mime_type') :
 * @li getVar('file_name') :
 * @li getVar('file_size') :
 * @li getVar('thumbnail_file') :
 * @li getVar('caption') :
 * @li getVar('sess_id') :
 * @li getVar('file_type_id') :
 * @li getVar('search_module_name') :
 * @li getVar('search_module_version') :
 * @li getVar('header') :
 * @li getVar('timestamp') :
 * @li getVar('is_deleted') :
 * @li getVar('download_count') :
 *
 */
class XooNIpsOrmFile extends XooNIpsTableObject {

  /**
   * file path string of this file
   *
   */
  var $filepath = null;
  function XooNIpsOrmFile() {
    parent::XooNIpsTableObject();
    $this->initVar( 'file_id', XOBJ_DTYPE_INT, 0, false );
    $this->initVar( 'item_id', XOBJ_DTYPE_INT, null, false );
    $this->initVar( 'original_file_name', XOBJ_DTYPE_TXTBOX, null, true, 255 );
    $this->initVar( 'mime_type', XOBJ_DTYPE_TXTBOX, null, false, 255 );
    $this->initVar( 'file_name', XOBJ_DTYPE_TXTBOX, null, false, 10 );
    $this->initVar( 'file_size', XOBJ_DTYPE_INT, null, false );
    $this->initVar( 'thumbnail_file', XOBJ_DTYPE_OTHER, null, false, 65535 );
    $this->initVar( 'caption', XOBJ_DTYPE_TXTBOX, null, false, 255 );
    $this->initVar( 'sess_id', XOBJ_DTYPE_TXTBOX, null, false, 32 );
    $this->initVar( 'file_type_id', XOBJ_DTYPE_INT, null, true );
    $this->initVar( 'search_module_name', XOBJ_DTYPE_TXTBOX, null, false, 255 );
    $this->initVar( 'search_module_version', XOBJ_DTYPE_OTHER, null, false );
    $this->initVar( 'header', XOBJ_DTYPE_TXTBOX, null, false, 32 );
    $this->initVar( 'timestamp', XOBJ_DTYPE_TXTBOX, null, false, 19 );
    $this->initVar( 'is_deleted', XOBJ_DTYPE_INT, 0, false );
    $this->initVar( 'download_count', XOBJ_DTYPE_INT, 0, false );
  }

  function setFilepath( $path ) {
    $this->filepath = $path;
  }
  function getFilepath() {
    return $this->filepath;
  }
}

/**
 * @brief data object of file
 */
class XooNIpsOrmFileHandler extends XooNIpsTableObjectHandler {
  function XooNIpsOrmFileHandler( &$db ) {
    parent::XooNIpsTableObjectHandler( $db );
    $this->__initHandler( 'XooNIpsOrmFile', 'xoonips_file', 'file_id' );
  }

  /**
   * @todo define upload_dir key name
   */
  function createFilepath( $file ) {
    // copy file to $upload_dir
    $xconfig_handler =& xoonips_getormhandler( 'xoonips', 'config' );
    $upload_dir = $xconfig_handler->getValue( 'upload_dir' );
    if ( substr( $upload_dir, - 1 ) == '/' ) {
      $dstfilepath = $upload_dir.$file->get( 'file_id' );
    } else {
      $dstfilepath = $upload_dir.'/'.$file->get( 'file_id' );
    }
    return $dstfilepath;
  }

  /**
   * insert a metadata of file and move a file to sysytem's upload_dir
   *
   * @param XooNIpsOrmFile $file file to be inserted
   * @return boolean false if failure
   */
  function insert( &$file ) {
    if ( ! $file->isDirty() ) {
      // nothing to do
      return true;
    }
    // fill thumbnail field if empty
    if ( $file->isNew() ) {
      $thumbnail = $file->get( 'thumbnail_file' );
      if ( empty( $thumbnail ) ) {
        $this->_set_thumbnail( $file );
      }
    }
    if ( parent::insert( $file ) ) {
      if ( ! $file->isNew() ) {
        // no need to move file if update
        return true;
      }
      if ( ! $file->get( 'is_deleted' ) ) {
        // move file in the only case of not deleted file
        return $this->moveFile( $file );
      } else {
        return true;
      }
    }
    return false;
  }

  /**
   * delete a metadata of file and remove a file
   *
   * @param XooNIpsOrmFile $file file to delete
   * @return boolean false if failure
   */
  function delete( &$file ) {
    if ( parent::delete( $file ) ) {
      return true;
    }
    return false;
  }

  /**
   * get a metadata of file. returned object has a file path of this file.
   *
   * @param XooNIpsOrmFile $file file to be inserted
   * @return boolean false if failure
   */
  function &get( $id ) {
    $file = parent::get( $id );
    if ( $file ) {
      $file->setFilepath( $this->createFilepath( $file ) );
    }
    return $file;
  }

  /**
   * gets File objects join xoonips_file_type.
   *
   * @access public
   * @param object $criteria
   * @param bool $id_as_key
   * @param string $fieldlist fieldlist for distinct select
   * @param bool $distinct
   * @param XooNIpsJoinCriteria $joindef join criteria object
   * @return array objects
   */
  function &getObjects( $criteria = null, $id_as_key = false, $fieldlist = '', $distinct = false, $joindef = null ) {
    if ( is_null( $joindef ) || ! ( is_subclass_of( $joindef, 'xoonipsjoincriteria' ) || strtolower( get_class( $joindef ) ) == 'xoonipsjoincriteria' ) ) {
      $joindef = new XooNIpsJoinCriteria( 'xoonips_file_type', 'file_type_id', 'file_type_id' );
    } else {
      $joindef->cascade( new XooNIpsJoinCriteria( 'xoonips_file_type', 'file_type_id', 'file_type_id' ), 'xoonips_file' );
    }
    $table = $this->db->prefix( 'xoonips_file' );
    $fieldlist = "$table.file_id, $table.item_id, $table.original_file_name, $table.mime_type, $table.file_name, $table.file_size, $table.thumbnail_file, $table.caption, $table.sess_id, $table.file_type_id, $table.search_module_name, $table.search_module_version, $table.header, $table.timestamp, $table.is_deleted, $table.download_count";
    $files = parent::getObjects( $criteria, $id_as_key, $fieldlist, $distinct, $joindef );
    if ( $files ) {
      for ( $i = 0; $i < count( $files ); $i++ ) {
        $files[$i]->setFilepath( $this->createFilepath( $files[$i] ) );
      }
    }
    return $files;
  }

  /**
   * move file
   * $file must have file id.
   *
   * @todo define upload_dir key name
   * @param XooNIpsOrmFile $file XooNIpsOrmFile object
   * @return boolean false if fault
   */
  function moveFile( $file ) {
    $file_id = $file->get( 'file_id' );
    if ( empty( $file_id ) ) {
      return false;
    }
    if ( rename( $file->getFilepath(), $this->createFilepath( $file ) ) ) {
      $file->setFilepath( $this->createFilepath( $file ) );
      return true;
    }
    trigger_error( 'can\'t move file: file_id='.$file->get( 'file_id' ) );
    return false;
  }

  /**
   * delete file
   * $file must have file id.
   * Notice that the function returns true if file has been already deleted.
   *
   * @param XooNIpsOrmFile $file XooNIpsOrmFile object
   * @return boolean false if file id is empty.
   */
  function deleteFile( $file ) {
    $file_id = $file->get( 'file_id' );
    if ( ! file_exists( $this->createFilepath( $file ) ) ) {
      return true;
    }
    if ( empty( $file_id ) ) {
      return false;
    }
    if ( unlink( $this->createFilepath( $file ) ) ) {
      return true;
    }
    return false;
  }

  /**
   * clone file information and copy file
   *
   * @param XooNIpsOrmFile $file XooNIpsOrmFile object
   * @return reference of cloned file orm object
   */
  function &fileClone( $file ) {
    // clone file orm
    $copyfile =& $file->xoopsClone();
    $copyfile->setFilepath( tempnam( '/tmp', 'XNP' ) );

    // copy file
    copy( $this->createFilepath( $file ), $copyfile->getFilepath() );

    return $copyfile;
  }

  /**
   * get total download count of specified file type of item.
   *
   * @param integer $item_id item id to get total download count
   * @param integer $file_type_nameid file id to get total download count
   * @param integer total donwload count
   */
  function getTotalDownloadCount( $item_id, $file_type_name ) {
    list( $tmp ) = xnpGetFileInfo( 'sum(t_file.download_count)', 't_file_type.name=\''.addslashes( $file_type_name ).'\' and sess_id is NULL ', $item_id );
    return $tmp[0];
  }

  /**
   * get total file size of items.

   * @param array item_ids item_id[]
   * @return int size(bytes)
   */
  function getTotalSizeOfItems( $item_ids ) {
    $total_size = 0;
    if ( count( $item_ids ) ) {
      $criteria = new CriteriaCompo();
      $criteria->add( new Criteria( 'item_id', '('.implode( ',', $item_ids ).')', 'in' ) );
      $criteria->add( new Criteria( 'is_deleted', 0 ) );
      $files =& $this->getObjects( $criteria );
      foreach ( $files as $file ) {
        $total_size += $file->get( 'file_size' );
      }
    }
    return $total_size;
  }

  /**
   * set and create thumbnail
   *
   * @access private
   * @param object &$file
   * @return bool if created thumbnail
   */
  function _set_thumbnail( &$file ) {
    $file_path = $file->getFilepath();
    $image_id = '';
    switch ( $file->get( 'mime_type' ) ) {
    case 'image/png':
      $image_id = @imagecreatefrompng( $file_path );
      break;
    case 'image/gif':
      $image_id = @imagecreatefromgif( $file_path );
      break;
    case 'image/jpeg':
      $image_id = @imagecreatefromjpeg( $file_path );
      break;
    }
    if ( $image_id === '' ) {
      return false;
    }
    $width = imagesx( $image_id );
    $height = imagesy( $image_id );
    // maximum file size in thumbnail
    $max_width = 100;
    $max_height = 100;
    if ( $max_width < $width || $max_height < $height ) {
      // If size of image file is too large, need to reduce it.
      $scale_x = $max_width / $width;
      $scale_y = $max_height / $height;
      $scale = min( $scale_x, $scale_y );
      $new_width = round( $width * $scale );
      $new_height = round( $height * $scale );
      // resize
      $new_Image_id = imagecreatetruecolor( $new_width, $new_height );
      $result = imagecopyresized( $new_image_id, $image_id, 0, 0, 0, 0, $new_width, $new_height, $width, $height );
      imagedestroy( $image_id );
      $image_id = $new_image_id;
      $width = $new_width;
      $height = $new_height;
    }
    $tmpfile = tempnam( '/tmp', 'XooNIpsThumbnail' );
    if ( $tmpfile === false ) {
      return false;
    }
    @unlink( $tmpfile );
    $result = imagepng( $image_id, $tmpfile );
    imagedestroy( $image_id );
    if ( $result == false ) {
      return false;
    }
    $thumbnail = file_get_contents( $tmpfile );
    @unlink( $tmpfile );
    $file->set( 'thumbnail_file', $thumbnail );
    return true;
  }
}
?>
