PHP Classes

File: ExtDirectApp.php

Recommend this page to a friend!
  Classes of Joćo Bruni   Ext Direct App   ExtDirectApp.php   Download  
File: ExtDirectApp.php
Role: Class source
Content type: text/plain
Description: Required file, containing all necessary classes for ExtDirectApp
Class: Ext Direct App
Call PHP classes from Javascript using ExtJS
Author: By
Last change:
Date: 14 years ago
Size: 8,344 bytes
 

Contents

Class file image Download
<?php

/**
 * Process Ext.Direct HTTP requests
 *
 * @author jbruni
 *
 */
class ExtDirectRequest
{
   
/**
     * @var array Actions to be executed in this request
     */
   
public $actions = array();
   
   
/**
     * @var string Name of the API class (ExtDirectActions descendant)
     */
   
public $actions_class;
   
   
/**
     * @param string $actions_class Name of the API class (ExtDirectActions descendant)
     */
   
public function __construct( $actions_class )
    {
       
$this->actions_class = $actions_class;
       
        if ( isset(
$_POST['extAction'] ) )
           
$this->getFormAction();
        else
           
$this->getRequestActions();
    }
   
   
/**
     * Instantiate actions to be executed in this request using "extAction" (form)
     */
   
protected function getFormAction()
    {
       
$extParameters = $_POST;
        foreach( array(
'extAction', 'extMethod', 'extTID', 'extUpload' ) as $variable )
        {
            if ( !isset(
$extParameters[$variable] ) )
                $
$variable = '';
            else
            {
                $
$variable = $extParameters[$variable];
                unset(
$extParameters[$variable] );
            }
        }
       
$this->actions[] = new $this->actions_class( $extAction, $extMethod, $extParameters, $extTID, $extUpload );
    }
   
   
/**
     * Instantiate actions to be executed in this request (without "extAction")
     */
   
protected function getRequestActions()
    {
       
$input = file_get_contents( 'php://input' );
       
       
$request = json_decode( $input );
       
        if ( !
is_array( $request ) )
           
$request = array( $request );
       
        foreach(
$request as $rpc )
        {
            foreach( array(
'type', 'action', 'method', 'data', 'tid' ) as $variable )
                $
$variable = ( isset( $rpc->$variable ) ? $rpc->$variable : '' );
            if (
$type == 'rpc' )
               
$this->actions[] = new $this->actions_class( $action, $method, $data, $tid, false );
        }
    }
}

/**
 * Store HTTP response contents for output
 *
 * @author jbruni
 *
 */
class ExtDirectResponse
{
   
/**
     * @var array HTTP headers to be sent in the response
     */
   
public $headers = array();
   
   
/**
     * @var content HTTP body to be sent in the response
     */
   
public $content = '';
}

/**
 * Ext.Direct API controller
 *
 * @author jbruni
 *
 */
class ExtDirectController
{
   
/**
     * @var string Name of the API class (ExtDirectActions descendant)
     */
   
public $actions_class;
   
   
/**
     * @var ExtDirectRequest Object to process HTTP request
     */
   
public $request;
   
   
/**
     * @var ExtDirectResponse Object to store HTTP response
     */
   
public $response;
   
   
/**
     * @var string Filename of Javascript template file
     */
   
public $template_file = 'app.js';
   
   
/**
     * @var array Contents of the template elements
     */
   
public $template_elements = array();
   
   
/**
     * @param string $actions_class Name of the API class (ExtDirectActions descendant)
     * @param boolean $autorun If true, automatically run the controller
     */
   
public function __construct( $actions_class, $autorun = true )
    {
       
$this->actions_class = $actions_class;
       
$this->request = new ExtDirectRequest( $this->actions_class );
       
$this->response = new ExtDirectResponse();
       
        if (
$autorun )
        {
           
$this->run();
           
$this->output();
            exit();
        }
    }
   
   
/**
     * @return string Parsed Javascript template, including the API declaration of the class (Ext.Direct.Provider object actions configuration)
     */
   
public function getJavascript()
    {
       
$template = file_get_contents( $this->template_file );
       
$this->template_elements['[%actions%]'] = $this->getActionsAPI( $this->actions_class );
        return
strtr( $template, $this->template_elements );
    }
   
   
/**
     * @param string $class Name of the API class (ExtDirectActions descendant)
     * @return string API declaration of the class (Ext.Direct.Provider object "actions" configuration)
     */
   
protected function getActionsAPI( $actions_class )
    {
       
$methods = array();
       
$reflection = new ReflectionClass( $actions_class );
        foreach(
$reflection->getMethods() as $method )
            if (
$method->isPublic() && ( $method->getDeclaringClass()->name == $actions_class ) )
               
$methods[] = array( 'name' => $method->getName(), 'len' => $method->getNumberOfRequiredParameters() );
        return
json_encode( $methods );
    }
   
   
/**
     * Process the request, execute the actions, and generate the response
     */
   
public function run()
    {
        if ( empty(
$this->request->actions ) )
           
$this->response->content = $this->getJavascript();
       
        else
        {
           
$response = array();
            foreach(
$this->request->actions as $action )
               
$response[] = $action->run();
           
            if (
count( $response ) > 1 )
               
$this->response->content = utf8_encode( json_encode( $response ) );
            else
               
$this->response->content = utf8_encode( json_encode( $response[0] ) );
        }
       
       
$this->response->headers[] = 'Content-Type: text/javascript';
    }
   
   
/**
     * Output response contents
     */
   
public function output()
    {
        foreach(
$this->response->headers as $header )
           
header( $header );
       
        echo
$this->response->content;
    }
}

/**
 * Base class for Ext.Direct APIs
 *
 * @author jbruni
 *
 */
abstract class ExtDirectActions
{
   
/**
     * @var string Class name
     */
   
   
public $action;
   
   
/**
     * @var string Method name
     */
   
public $method;
   
   
/**
     * @var mixed Method parameters
     */
   
public $parameters;
   
   
/**
     * @var integer Unique identifier for the transaction
     */
   
public $transaction_id;
   
   
/**
     * @var boolean True if there is a file upload; false otherwise
     */
   
public $upload = false;
   
   
/**
     * @var boolean Set this to true to allow exception detailed information in the output
     */
   
public $debug = false;
   
   
/**
     * @param string $action Class name
     * @param string $method Method name
     * @param mixed $parameters Method parameters
     * @param integer $transaction_id Unique identifier for the transaction
     * @param boolean $upload True if there is a file upload; false otherwise
     * @param boolean $debug Set this to true to allow exception detailed information in the output
     */
   
final public function __construct( $action, $method, $parameters, $transaction_id, $upload = false, $debug = null )
    {
        foreach( array(
'action', 'method', 'parameters', 'transaction_id', 'upload', 'debug' ) as $parameter )
           
$this->$parameter = $$parameter;
    }
   
   
/**
     * @return array Result of the action execution
     */
   
public function run()
    {
       
$response = array(
           
'type' => 'rpc',
           
'tid' => $this->transaction_id,
           
'action' => get_class( $this ),
           
'method' => $this->method
       
);
       
        try
        {
           
$result = $this->callAction();
           
$response['result'] = $result;
        }
       
        catch (
Exception $e )
        {
           
$response['result'] = 'Failure';
            if (
$this->debug )
               
$response = array(
                   
'type' => 'exception',
                   
'tid' => $this->transaction_id,
                   
'message' => $e->getMessage(),
                   
'where' => $e->getTraceAsString()
                );
        }
       
       
array_walk_recursive( $response, array( $this, 'utf8_encode' ) );
       
        return
$response;
    }
   
   
/**
     * @param mixed $value If it is a string, it will be UTF8 encoded
     * @param mixed $key Not used (passed by "array_walk_recursive" function)
     * @return mixed UTF8 encoded string, or unchanged value if not a string
     */
   
protected function &utf8_encode( &$value, $key )
    {
        if (
is_string( $value ) )
           
$value = utf8_encode( $value );
        return
$value;
    }
   
   
/**
     * @return mixed Result of the action
     */
   
protected function callAction()
    {
       
$class = get_class( $this );
       
        if (
$this->action != $class )
            throw new
Exception( 'Only calls to ' . $class . ' are allowed; tried to call ' . $this->action, E_USER_ERROR );
       
        if ( !
method_exists( $class, $this->method ) )
            throw new
Exception( 'Call to undefined or not allowed ' . $class . ' method ' . $this->method, E_USER_ERROR );
       
       
$method = new ReflectionMethod( $class, $this->method );
       
$params = $method->getNumberOfRequiredParameters();
        if (
count( $this->parameters ) < $params )
            throw new
Exception( 'Call to ' . $class . ' method ' . $this->method . ' needs at least ' . $params . ' parameters', E_USER_ERROR );
       
        return
call_user_func_array( array( $this, $this->method ), $this->parameters );
    }
}

?>