<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
 * FIT FileRunner
 *
 * $Id$
 *
 * @author gERD Schaufelberger <gerd@php-tools.net>
 * @package FIT
 * @subpackage FileRunner
 * @license LGPL http://www.gnu.org/copyleft/lesser.html
 */

/**
 * load exception class: FileIO
 */
require_once  'Testing/FIT/Exception/FileIO.php';

/**
 * load exception class: Parser
 */
require_once  'Testing/FIT/Exception/Parser.php';


/**
 * FIT Runner
 *
 * Run fit-tests from tables stored in HTML files.
 * FileRunner provides a simple interface to process tests from CLI or
 * "remote controlled" from anther application.
 *
 * @see main()
 * @see run()
 *
 * @version 0.1.1
 * @package FIT
 * @subpackage FileRunner
 */
class Testing_FIT_Runner 
{
   /**
    * Emulate c-stylish main() function to run applicattion on command line
    *
    * The most common usage from any script. 
    * <code> 
    *  FileRunner::main( $_SERVER['argv'] );
    * </code>
    * 
    * return codes:
    *  - 0 everything went alright
    *  - 1 invalid number of arguments
    *  - 2 file io problem
    *  - 3 parse exception
    *  - 127 unexpected exception
    * 
    * @param array argv
    * @return int 0 on success, or value greater 1 on error 
    * @see run()
    */
	public static function main( $argv ) {

       /**
        * open stderr for writing
        * required for NON CLI misuse of FileRunner::main()
        */
        if( !defined( 'STDERR' ) ) {
            throw new Testing_FIT_Exception_FileIO( 'STDERR is not defined - use PHP-CLI to call this method', 'STDERR' );
        }

        if( count( $argv ) != 3 ) {
            fwrite( STDERR, "Invalid number of arguments. input file and output file expected\n" );
            return 1;
        }

		try {		
			$fr = new Testing_FIT_Runner();
			$fr->run( $argv[1], $argv[2] );
		} 
        catch( Testing_FIT_Exception_FileIO $e ) {
			fwrite( STDERR, $e->getMessage() . "\n" );
            return 2;
		} 
        catch( Testing_FIT_Exception_Parser $e ) {
            $context    = $e->getContext();
            fwrite( STDERR, $e->getMessage() . ' @ ' . implode( ', ', $context ) . "\n" );
            return 3;
        } 
        catch( Exception $e ) {
			fwrite( STDERR, 'Caught unknown exception: ' . $e->getMessage() . "\n" );
            return 127;
		}
        
        return 0;
	}

   /**
    * Process tests from file and save output
    *
    * Process all tables in input file and store result in output file. This is the API you 
    * probably want to use...
    *
    * Example:
    * <code>
    *  $fr = new Testing_FIT_Runner();
    *  $fr->run( 'infile.html', 'outfile.html' );
    * </code>
    *
    * @param string $input path to input file, or "-"  to read from STDIN
    * @param string $output path to output file, or "-"  to write to STDOUT
    * @return bool always true
    */
    public function run( $input, $output )
    {
        
        // read from STDIN
        if( $input == '-' ) {
            $isFile =   false;
            
            $input  =   '';
            while( !feof( STDIN ) ) {
                $input  .=  fread( STDIN, 4096 );
            }
            
        } else {
            $isFile =   true;
            
            // check input file
            if( !file_exists( $input ) ) {
                throw new Testing_FIT_Exception_FileIO( 'Input file does not exist!', $input );
            }
            if( !is_readable( $input ) ) {
                throw new Testing_FIT_Exception_FileIO( 'Input file is not readable', $input );
            }            
        }        
        
        if( $output != '-' ) {
            // check output file
            if( file_exists( $output ) ) {
                if( !is_writable( $output ) ) {
                    throw new Testing_FIT_Exception_FileIO( 'Output file is not writable (probably a problem of file permissions)', $output );
                }
            }
            else if( !is_writable( dirname( $output ) ) ) {
                throw new Testing_FIT_Exception_FileIO( 'Cannot create output file in given folder. (probably a problem of file permissions)', $output ); 
            }
            
        }
        
        // run and save output
        $result =   $this->process( $input, $isFile );
        if( $output != '-' ) {
            file_put_contents( $output, $result );
        } else {
            echo $result;
        }
        
        return true;
    }

   /**
    * process tables from input
    * 
    * Run tests and return HTML.
    *
    * @param string $input source of HTML
    * @param bool $isFile whether input is a file or a string
    * @return string html output 
    */
    public function process( $input, $isFile = true ) 
    {
        // use parser and table
        include_once 'Testing/FIT/Parser.php';
        include_once 'Testing/FIT/Table.php';

        if( $isFile ) {
            $input      =   file_get_contents( $input );
        }

        $parser         =   new Testing_FIT_Parser();
        $this->table    =   new Testing_FIT_Table();
        
        $parser->parse( $input );
        $this->table->doTables( $parser );

        return $parser->serialize();
    }
}
?>