WikiPDB:AbstractErrorCheckClient

From WikiPDB

Jump to: navigation, search
<?
 
define( "DATA_FILE_URL", "http://wikipdb.org/wikidata/datafileforapi.php" );
 
/**
 * The AbstractErrorCheckClient class, is a helper class, to make it really easy to create plug-ins for WikiPDB. 
 * It containes most of the code necessary for a working plug-in, so that develepores only need to include
 * the code necessary for the actual error checking. 
 * 
 * @name Abstract Error Check Client
 * @version 1.0
 * @author Rafael Ördög, <a href="http://pitgroup.org">Protein Information Technology Group, Eotvos University, Hungary</a>, <a href="http://uratim.com>Uratim Inc.</a>
 * @license GNU
 * @copyright Rafael Ördög (C) 2008
 */
abstract class AbstractErrorCheckClient
{
    protected $action;
    protected $revisionId;
    protected $pdbId;
    protected $useractiontype;
    protected $pluginName;
    protected $conditions;
    protected $pdbFile;
    protected $conditionStatus;
    protected $returnUrl;
    protected $callApiDetailsCash;
    protected $callUserActionCash;
 
    /**
     * Constructor
     * @param $pluginName - An arbitary name for the plug-in. This is only used to identify the plug-in for WikiPDB end users.
     * @param $conditions - Space separated list of plug-in IDs. The plug-in wont be invoked by WikiPDB until the plug-ins referenced here have finished their job.
     */
    public function __construct( $pluginName, $conditions = "" )
    {
        $this->pdbFile = "";
        $this->callApiDetailsCash = array();
        $this->callUserActionCash = array();
 
        if ( isset($_GET['action']) )
        {
            $this->action = $_GET['action'];
        }
        else
        {
            throw new Exception( "Missing action" );
        }
 
        if ( $this->action == "help" )
        {
            $this->help();
        }
        else
        {
            if ( preg_match('/^[a-zA-Z0-9\s]+$/', $pluginName) )
            {
                $this->pluginName = $pluginName;
            }
            else
            {
                throw new Exception( "Invalid plugin name! Allowed characters are a-z, A-Z, 0-9" );
            }
 
            if ( preg_match('/^[\d\s]*$/', $conditions) )
            {
                $this->conditions = $conditions;
            }
            else
            {
                throw new Exception( "Invalid condition! Condition must be a space separated list of digits" );
            }
 
            if ( isset($_GET['pdbid']) && preg_match('/^\d\w\w\w$/', $_GET['pdbid']) )
            {
                $this->pdbId = $_GET['pdbid'];
            }
            else
            {
                if ( isset($_GET['pdbid']) )
                {
                    throw new Exception( "Invalid pdbid: " . $_GET['pdbid'] );
                }
                else
                {
                    throw new Exception( "Missing pdbid" );
                }
            }
 
            if ( isset($_GET['revisionid']) && preg_match('/^\d+$/', $_GET['revisionid']) )
            {
                $this->revisionId = $_GET['revisionid'];
            }
            else
            {
                if ( isset($_GET['revisionid']) )
                {
                    throw new Exception( "Invalid revisionid: " . $_GET['revisionid'] );
                }
                else
                {
                    throw new Exception( "Missing revisionid" );
                }
            }
 
            switch ( $this->action )
            {
                case "start":
                    $this->start();
                    break;
                case "kick":
                    $this->kick();
                    break;
                case "details":
                    $this->details();
                    break;
                case "apidetails":
                    $this->apiDetails();
                    break;
                case "useraction":
                    $this->useractiontype = ( (isset($_GET['useraction'])) ? $_GET['useraction'] : "" );
                    $this->useraction();
                    break;
		case "debug":
		    $this->debug();
		    break;
                default:
                    throw new Exception( "Invalid action" );
            }
        }
    }
 
    /**
     * This Function is invoked when WikiPDB sends a start signal to the plug-in. Returns the plug-in name, and conditions to WikiPDB.
     */
    protected function start()
    {
        $retArray = array( 'name'      => $this->pluginName,
                           'condition' => $this->conditions
                    );
        $retVal = json_encode( $retArray );
        echo $retVal;
    }
 
    /**
     * This Function is invoked when WikiPDB sends a kick signal to the plug-in. After basic check on the input values this will call the 
     * userDefinedErrorcheck abstract function, which has to be defined by the developer of the plug-in.
     */
    protected function kick()
    {
        if ( isset($_POST['returnurl']) )
        {
            $this->returnUrl = $_POST['returnurl'];
        }
        else
        {
            throw new Exception( "Missing return URL" );
        }
        if ( isset($_POST['status']) )
        {
            $this->conditionStatus = json_decode( stripslashes($_POST['status']), true );
        }
        else
        {
            throw new Exception( "Missing status" );
        }
 
        header( "Content-Length: 2" );
        ob_start();
        echo "OK";
        ob_end_flush();
        flush();
 
        $retVal = $this->userDefinedErrorcheck();
 
        if ( !isset($retVal['errors']) )
        {
            throw new Exception( "Errors variable not set" );
        }
        if ( !isset($retVal['warning']) )
        {
            throw new Exception( "Warning variable not set" );
        }
 
        $pageContents = HttpClient::quickPost( $_POST['returnurl'],
                                               array( 'errors'  => $retVal['errors'],
                                                      'warning' => $retVal['warning']
                                               )
                        );
    }
 
    /**
     * This function is for debuging the check algorithm. It is recomended, that you comment it out once you are finished with development.
     * @return Nothing
     */
    protected function debug()
    {
        if ( isset($_POST['status']) )
        {
            $this->conditionStatus = json_decode( stripslashes($_POST['status']), true );
        }
        else
        {
            $this->conditionStatus = array();
        }
 
	$retVal = $this->userDefinedErrorcheck();
 
	echo json_encode($retVal);
    }
 
 
    /**
     * This function will download the pdb file from wikipdb. 
     * Future development -> other pdb / revisionid pairs
     * @return The PDB file being checked in a single multiline string
     */
    protected function getPdbFile()
    {
        if ( $this->pdbFile == "" )
        {
            $this->pdbFile = 
				HttpClient::quickGet( DATA_FILE_URL . "?pdbid={$this->pdbId}&revisionid={$this->revisionId}" );
        }
        return $this->pdbFile;
    }
 
    /**
     *  Same as getPdbFile, but returns an array.
     * @return Array of lines in the PDB file
     */
    protected function getPdbFileArray()
    {
        return explode( "\n", $this->getPdbFile() );
    }
 
    /**
     * Invokes apiDetails action for another plugin
     * Future development -> Call request status if not already available
     *                    -> Call for other pdb / revision pairs
     * @param $pluginId - The ID of the plug-in invoked. Please include this id into the conditions list of the constructor.
     * @return The answer the invoked plug-in has sent as a string
     */
    protected function callApiDetails( $pluginId )
    {
        if ( !isset($this->callApiDetailsCash[$pluginId]) )
        {
            if ( !isset($this->conditionStatus[$pluginId]) )
            {
                if ( isset($this->conditionStatus) )
                {
                    throw new Exception( "ConditionStatus wasn't posted" );
                }
                else
                {
                    print_r( $this->conditionStatus );
                    throw new Exception( "Plug-in is not available" );
                }
            }
            if ( $this->conditionStatus[$pluginId]['status'] == "fail" )
            {
                throw new Exception( "Plug-in #$pluginId ({$this->conditionStatus[$pluginId]['name']}) failed" );
            }
            if ( $this->conditionStatus[$pluginId]['status'] != "success" )
            {
                throw new Exception( "Plug-in #$pluginId ({$this->conditionStatus[$pluginId]['name']}) not ready, please add plug-in Id to conditions!" );
            }
            $this->callApiDetailsCash[$pluginId] = 
			HttpClient::quickGet( "{$this->conditionStatus[$pluginId]['httpaddress']}?pdbid={$this->pdbId}&revisionid={$this->revisionId}&action=apidetails" );
        }
        return $this->callApiDetailsCash[$pluginId];
    }
 
    /**
     * Invokes a userAction action for another plugin
     * Future development -> Call request status if not already available
     *                    -> Call for other pdb / revision pairs
     * @param $pluginId - The ID of the plug-in invoked. Please include this id into the conditions list of the constructor.
     * @param $userAction - The name of the action that is being invoked.
     * @return The answer the invoked plug-in has sent as a string          
     */
    protected function callUserAction( $pluginId, $userAction )
    {
        if ( !isset($this->callUserActionCash[$pluginId][$userAction]) )
        {
            if ( !isset($this->conditionStatus[$pluginId]) )
            {
                if ( isset($this->conditionStatus) )
                {
                    throw new Exception( "ConditionStatus wasn't posted" );
                }
                else
                {
                    print_r( $this->conditionStatus );
                    throw new Exception( "Plug-in is not available" );
                }
            }
            if ( $this->conditionStatus[$pluginId]['status'] == "fail" )
            {
                throw new Exception( "Plug-in #$pluginId ({$this->conditionStatus[$pluginId]['name']}) failed" );
            }
            if ( $this->conditionStatus[$pluginId]['status'] != "success" )
            {
                throw new Exception( "Plug-in #$pluginId ({$this->conditionStatus[$pluginId]['name']}) not ready, please add plug-in Id to conditions!" );
            }
 
            $this->callUserActionCash[$pluginId][$userAction] = 
				HttpClient::quickGet( "{$this->conditionStatus[$pluginId]['httpaddress']}?pdbid={$this->pdbId}&revisionid={$this->revisionId}&action=useraction&useraction=$userAction" );
        }
        return $this->callUserActionCash[$pluginId][$userAction];
    }
 
    /**
     * This function is invoked when another plug in sends request for a userAction.
     */
    protected function useraction()
    {
 
    }
 
    /**
     * Invoked by kick(), This function should contain the error check algorithm. 
     */
    abstract protected function userDefinedErrorcheck();
 
    /**
     * This function should return a human readable help file in HTML format, that gives information about the plug-in for WikiPDB endusers
     */
    abstract protected function help();
 
    /**
     * This function should return human readable list of errors in HTML format. Intended for  WikiPDB endusers.
     */
    abstract protected function details();
 
    /**
     * This function should return a list of errors in JSON. Intended for other WikiPDB plug-ins.
     */
    abstract protected function apiDetails();
};
 
?>