Location: PHPKode > projects > Simple Way to Usenet > libs/core/files/file_transfert.class.php
<?php
/**
 *  
 * @author  Benjamin Gillissen <hide@address.com>
 * 
 *	**************************************************************

	Copyright (C) 2009  Benjamin Gillissen
	
	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.
	
	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 at:
	http://www.gnu.org/copyleft/gpl.html

 *	**************************************************************
 */

class file_transfert {
	
	private $src_ref, $src_path, $dst_ref, $dst_path;
	private $src_abs, $dst_abs;
	private $src_hdl, $dst_hdl;
	
	private $setting = Array(	'isamove'=>FALSE, 
								'recursive'=>FALSE, 
								'exclude'=>Array(),
								'followlink'=>FALSE,
								'buffer'=>8192);
	
	private $Q;
	private $Q_mv;
	private $cursor;
	
	public function __construct($src_ref, $src_path, $dst_ref, $dst_path){
		$this->src_ref = $src_ref;
		$this->src_path = $src_path;
		$this->dst_ref = $dst_ref;
		$this->dst_path = $dst_path;
		$this->src_abs = new file_abstract($this->src_ref);
		$this->dst_abs = new file_abstract($this->dst_ref); 
	}
	
	public function set_option($opt, $val){
		if ( isset($this->Q) ){
			errors::raise("Transfert setting can only be changed before a compute_queue call", CORE_LOG_WARNING, 'FTRANSFERT');
			return FALSE;
		}
		if ( !isset($this->setting[$opt]) ){ 
			errors::raise("Unknow Transfert setting : $opt", CORE_LOG_WARNING, 'FTRANSFERT');
			return FALSE;
		}
		$this->setting[$opt] = $val;
		return TRUE;
	}
	
	public function get_option($opt){
		if ( !isset($this->setting[$opt]) ){ 
			errors::raise("Unknow Transfert setting : $opt", CORE_LOG_WARNING, 'FTRANSFERT');
			return FALSE;
		}
		return $this->setting[$opt];
	}
	
	public function get_options(){ return $this->setting; }
	
	private function path_to_path($path){
		$buf = split('/', $path);
		$f='';
		$last = count($buf) - 1;
		foreach($buf as $c => &$entry ){
			if ( $c != 0 ){
				$f .= '/'.$entry;
			} else {
				$f .= $entry;
			}
			if ( $entry !== '..' AND $entry !== '.' AND !empty($entry) AND $c != $last ){ 
				$o[] = $f;			
			}
			
		}
		if( isset($o) ){ return $o; }
		return Array();
	}
	
	public function compute_queue(){
		if ( FALSE === $this->src_abs->connect() ){ return FALSE; }
		if ( FALSE === $this->dst_abs->connect() ){ return FALSE; }
		if ( FALSE === $this->src_abs->exists($this->src_path) ){ return FALSE; }
		$this->Q=Array();
		$this->Q_mv=Array();
		if ( $this->src_abs->isfile($this->src_path) ){
			
			if ( $this->dst_abs->isdir($this->dst_path) ){
				$dst = $this->dst_path.'/'.basename($this->src_path); 
			} elseif ( $this->dst_abs->isfile($this->dst_path) ){
				$dst = $this->dst_path;
			} else { 
				$buf = $this->path_to_path($this->dst_path);
				foreach($buf as $c => &$f ){
					if ( FALSE === $this->dst_abs->isdir($f) ){ $this->Q_append('mkdir', $f); }
				}
				unset($buf, $c, $f);
				$dst = $this->dst_path;	
			}
			$this->Q_append('cp', $this->src_path, $dst);
			if ( $this->setting['isamove'] ){ $this->Q_append('rm', $this->src_path); }
			
		} elseif ( $this->src_abs->isdir($this->src_path) ){
			
			if ( FALSE === $this->dst_abs->isdir($this->dst_path) ){
				$buf = $this->path_to_path($this->dst_path);
				foreach($buf as $c => &$f ){
					if ( FALSE === $this->dst_abs->isdir($f) ){ $this->Q_append('mkdir', $f); }
				}
				unset($buf, $c, $f);
				$this->Q_append('mkdir', $this->dst_path); 
			}
			while (FALSE !== ( $entry = $this->src_abs->readdir($this->src_path) )){
				$src = $this->src_path.'/'.$entry;
				$dst = $this->dst_path.'/'.$entry;
				if ( TRUE === $this->setting['recursive'] ){
					$this->recur_populate($src, $dst);
				} elseif ( TRUE === $this->src_abs->isfile($src) ){ 
					$this->Q_append('cp', $src, $dst);
					if ( $this->setting['isamove'] ){ $this->Q_append('rm', $src); }
				}

			}
			
		}
		$this->Q = array_merge($this->Q, $this->Q_mv);
		//foreach($this->Q as $k => $act){ echo "Q	[$act[0]]	[$act[1]]	[$act[2]]\n"; }
		unset($this->Q_mv);
		return TRUE;
	}
	
	private function recur_populate($src, $dst){
		if ( $this->src_abs->isdir($src) ){
			if ( FALSE === $this->dst_abs->isdir($dst) ){ $this->Q_append('mkdir', $dst); }
			while (FALSE !== ( $entry = $this->src_abs->readdir($src) )){
				$this->recur_populate($src."/".$entry, $dst.'/'.$entry);
			}
			if ( $this->setting['isamove'] ){ $this->Q_append('rmdir', $src); }
		} else {
			$this->Q_append('cp', $src, $dst);
			if ( $this->setting['isamove'] ){ $this->Q_append('rm', $src); }
		}
		
	}
	
	private function Q_append($act, $src, $dst=NULL){
		if ( $act === 'rm' OR $act === 'rmdir' ){
			$this->Q_mv[CORE::hash()] = Array($act, $src, $dst);
		} else {
			$this->Q[CORE::hash()] = Array($act, $src, $dst);
		}
		 
	}
	
	public function list_queue(){
		if ( !isset($this->cursor) ){
			reset($this->Q);
		} elseif ( FALSE === next($this->Q) ){
			unset($this->cursor); 
			return FALSE; 
		}
		$this->cursor = current(&$this->Q);
		//echo "QACT	[".$this->cursor[0]."]	[".$this->cursor[1]."]	[".$this->cursor[2]."]\n";
		return TRUE;
	}
	
	public function process_item(){
		if ( !isset($this->cursor) ){ return FALSE; }
		$todo = &$this->cursor;
		switch($todo[0]){
			case 'cp' 		:   return $this->iocp($todo[1], $todo[2]); 
			case 'mkdir'	:   return $this->dst_abs->createdir($todo[1]);
			case 'mklink'	:	//to implement into file accessors
								break;
			case 'rm' 		:   return $this->src_abs->remove($todo[1], FALSE);
								break;
			case 'rmdir'	:	return $this->src_abs->remove($todo[1], FALSE);
								break;
			default :	return FALSE; 
		}
		
		
	}
	
	private function iocp($src, $dst){
		if ( !isset($this->src_hdl) ){
			$this->src_hdl = $this->src_abs->file_open($src, 'r');
			if ( FALSE === $this->src_hdl ){
				errors::raise("IOCP failed, source file could not be opened ( $this->src_ref:$src )", CORE_LOG_ERROR, 'FTRANSFERT');
				unset($this->src_hdl); 
				return FALSE; 
			}
			$this->dst_hdl = $this->dst_abs->file_open($dst, 'w');
			if ( FALSE === $this->dst_hdl ){ 
				errors::raise("IOCP failed, destination file could not be opened ( $this->dst_ref:$dst )", CORE_LOG_ERROR, 'FTRANSFERT');
				unset($this->src_hdl, $this->dst_hdl);
				return FALSE; 
			}
		}
		$feof = $this->src_abs->file_end($this->src_hdl);
		$buff = $this->src_abs->file_read($this->src_hdl, $this->setting['buffer']);
		if ( FALSE != $feof OR FALSE === $buff OR 0 === strlen($buff) ){ 
			$this->src_abs->file_close($this->src_hdl);
			$this->dst_abs->file_close($this->dst_hdl);
			unset($this->src_hdl, $this->dst_hdl);
			return TRUE;
		} 
		if ( FALSE === $this->dst_abs->file_put($this->dst_hdl, $buff) ){ 
			errors::raise("IOCP failed, Buffer could not be write to destination file ( $this->dst_ref:$dst ), removing incomplet file", CORE_LOG_ERROR, 'FTRANSFERT');
			$this->src_abs->file_close($this->src_hdl);
			$this->dst_abs->file_close($this->dst_hdl);
			$this->dst_abs->remove($dst);
			unset($this->src_hdl, $this->dst_hdl);
			return FALSE; 
		}
		return NULL;
	}
	
}
return TRUE;
Return current item: Simple Way to Usenet