Hi, just wondering if anyone with a little time could take a look over this little non-blocking ftp client I've written and give me your thoughts.

PHP Code:
<?php

define
'DEBUG'true );
class 
NBFTPException extends Exception {}
/**
 * Main Non-blocking FTP class
 *
 * @author Rob Young
 */
class NBFTP {
    private
        
$server null,
        
$user   null,
        
$pass   null,
        
$conn   null,
        
$transactions = array(),
        
$pool   null;
    
    
/**
     * Sets variables and makes one "control" connection to the ftp server for utility functions such as fs navigation. Also instantiates the pool class
     *
     * @param string $server
     * @param string $user
     * @param string $pass
     */
    
public function __construct$server$user$pass ) {
        
// Do some sanity checks here
        
$this->server $server;
        
$this->user   $user;
        
$this->pass   $pass;

        
// We need to have a control connection for navigating around the server
        
$this->conn $this->getNewConnection();

        
$this->pool = new NBFTP_Pool$this );
    }

    
/**
     * Get a new ftp connection resource
     *
     */
    
public function getNewConnection() {
        if( !
$conn ftp_connect$this->server12345 ) ) throw new NBFTPException"Failed to connect to the server" );
        if( !
ftp_login$conn$this->user$this->pass ) ) throw new NBFTPException"Failed to login to server" );
        return 
$conn;
    }
    
    
/**
     * Allow some of the ftp functions to be mirrored through this class
     */
    
public function __call$method$args ) {
        
$ftp_func 'ftp_' $method;
        if( 
in_array$method, array( 'chup''chdir''chmod''delete''exec''mdtm''mkdir''nlist''pwd''rename''rmdir') ) && function_exists$ftp_func ) ) {
            
// Prepend the connection resource on to the argument list
            
array_unshift$args$this->conn );
            return 
call_user_func_array$ftp_func$args );
        }
    }

    
/**
     * Add an non-blocking ftp put transaction to the transaction list
     *
     * @param string $local
     * @param string $remote
     * @param string $type
     */
    
public function addPut$local$remote$type FTP_BINARY ) {
        
$this->addTransaction( new NBFTP_PutTransaction$local$remote$type ) );
    }

    
/**
     * Add a non-blocking ftp get transaction to the transaction list
     *
     * @param string $remote
     * @param string $local
     * @param string $type
     */
    
public function addGet$remote$local$type FTP_BINARY ) {
        
$this->addTransaction( new NBFTP_GetTransaction$local$remote$type ) );
    }

    
/**
     * Add a transaction object to the transaction list
     *
     * @param NBFTP_Transaction $transaction
     */
    
public function addTransactionNBFTP_Transaction $transaction ) {
        
$this->transactions[] = $transaction;
    }

    
/**
     * Actually run all the transactions that you've queued up
     *
     */
    
public function commit() {
        
$active = array();
        
$transactions_c count$this->transactions );
        
$done_c 0;
        while( 
$done_c $transactions_c ) {
            while( 
count$this->transactions ) && $conn $this->pool->next() ) {
                
$transaction array_pop$this->transactions );
                
$transaction->assign$conn );
                
$transaction->start();
                
$active[] = $transaction;
                
// Unset the local references so that we don't get weird **** going on
                
unset( $conn$transaction );
            }

            while( !
$this->pool->hasNext() || ( !count($this->transactions) && count$active ) ) ) {
                for( 
$i=0$i count$active ); $i++ ) {
                    if(!
$active[$i]->run$this->pool )) { 
                        unset( 
$active[$i] ); 
                        
$active array_values$active );
                        
$done_c++;
                    }
                }
            }
        }
    }
    
    
/**
     * Close all the connections associated with this object
     */
    
public function close() {
        
ftp_close$this->conn );
        
$this->pool->close();
    }
}

/**
 * Class to describe a unit of transfer between the client and the server ( a get or a put )
 */
abstract class NBFTP_Transaction {
    protected
        
$conn   null,
        
$local  null,
        
$remote null,
        
$type   null,
        
$status null;
    
    
/**
     * Prehapse this should be handled by the child classes otherwise I'm locking further extension into providing these parameters.
     *
     * @param string $local
     * @param string $remote
     * @param int    $type 
     */
    
public function __construct$local$remote$type ) {
        
$this->local  $local;
        
$this->remote $remote;
        
$this->type   $type;
    }

    
/**
     * Assign a connection to this transaction
     *
     * @param ftp_connection $conn
     */
    
public function assign$conn ) {
        
$this->conn $conn;
    }
    
    
/**
     * This is where the child classes actually call their respective function
     */
    
abstract public function start( );

    
/**
     * Run this transaction for another iteration, if it's finished add the connection back into the pool and return false.
     *
     * @param NBFTP_Pool $pool
     */
    
public function runNBFTP_Pool $pool ) {
        if(
DEBUG) echo("Continuing {$this->conn}\n");
        if( 
$this->status == null || $this->conn == null ) throw new NBFTPException"Bad Transaction parameters" );
        
        switch( 
$this->status ) {
            case 
FTP_MOREDATA:
                
$this->status ftp_nb_continue$this->conn );
                return 
true;
            case 
FTP_FINISHED:
                
$pool->add$this->conn );
                return 
false;
            default:
                throw new 
NBFTPException"Unrecognized transaction status" );
        } 
    }

    public function 
__toString() {
        return 
__CLASS__ ':' $this->local ':' $this->remote ':' $this->type;
    }
}

/**
 * Handles FTP Puts
 */
class NBFTP_PutTransaction extends NBFTP_Transaction {
    public function 
start() {
        if( 
DEBUG ) echo("Starting PUT ({$this->conn}) transaction...\n");
        if( !
$this->status ftp_nb_put$this->conn$this->remote$this->local$this->type ) ) throw new NBFTPException"Transaction Failed ... " $this->__toString() );
    }
}

/**
 * Handles FTP Gets
 */
class NBFTP_GetTransaction extends NBFTP_Transaction {
    public function 
start() {
        if( 
DEBUG ) echo("Starting GET ({$this->conn}) transaction...\n");
        if( !
$this->status ftp_nb_get$this->conn$this->local$this->remote$this->type )) throw new NBFTPException"Transaction Failed ... " $this->__toString() );
    }
}

/**
 * Manages the connection pool
 */
class NBFTP_Pool {
    const 
MAX_CONNECTIONS 20;
    private
        
$ftp    null,
        
$pool   = array(),
        
$count  0;

    public function 
__constructNBFTP $ftp ) {    
        
$this->ftp $ftp;
    }
    
    public function 
add$conn ) {
        
array_push$this->pool$conn );
    }

    public function 
next() {
        if(
DEBUG) echo("Pool::next() ");
        
$c count$this->pool );
        if( 
$c == ) {
            if( 
$this->count self::MAX_CONNECTIONS ) {
                
$this->count++;
                if(
DEBUG) echo("new\n");
                return 
$this->ftp->getNewConnection();
            } else {
                if(
DEBUG) echo("false\n");
                return 
false;
            }
        } else {
            if(
DEBUG) echo("pop\n");
            return 
array_pop$this->pool );
        }
    }

    public function 
hasNext() {
        if(
DEBUG) echo("Pool::hasNext()\n");
        if( 
$this->count self::MAX_CONNECTIONS || count$this->pool ) > ) return true;
        return 
false;
    }

    public function 
close() {
        foreach( 
$this->pool as $conn ) {
            
ftp_close$conn );
        }
    }
}

if( 
$_SERVER['argc'] != ) die("Expecting 6 parameters got {$_SERVER['argc']}\n" print_r($_SERVER['argv'], true));

$server $_SERVER['argv'][1];
$user   $_SERVER['argv'][2];
$pass   $_SERVER['argv'][3];
$local  $_SERVER['argv'][4];
$remote $_SERVER['argv'][5];

$ftp = new NBFTP$server$user$pass );

$files $ftp->nlist$remote );

foreach( 
$files as $file ) {
    
$ftp->addGet$remote.'/'.$file$local '/' $file); // or $ftp->addTransaction( new NBFTP_GetTransaction( '/destination/', $file, FTP_BINARY ) );
}

$ftp->commit();
$ftp->close();
?>
Cheers
Rob