Results 1 to 1 of 1

Thread: TYPO3 Implementation of ExtDirect

  1. #1
    Sencha Premium Member steffenk's Avatar
    Join Date
    Jul 2007
    Location
    Haan, Germany
    Posts
    2,676

    Default TYPO3 Implementation of ExtDirect

    Hi,

    i want to show you how we implemented ExtDirect in TYPO3. We only have 2 files (api + router), if you use it, you have to register your class in the system. Here is a description how to use it:
    http://wiki.typo3.org/index.php/ExtDirect

    And here are the core classes:

    API
    PHP Code:
    <?php
    /***************************************************************
    *  Copyright notice
    *
    *  (c) 2010 Sebastian Kurfuerst <[email protected]>
    *  All rights reserved
    *
    *  This script is part of the TYPO3 project. The TYPO3 project 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.
    *
    *  The GNU General Public License can be found at
    *  http://www.gnu.org/copyleft/gpl.html.
    *  A copy is found in the textfile GPL.txt and important notices to the license
    *  from the author is found in LICENSE.txt distributed with these scripts.
    *
    *
    *  This script 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.
    *
    *  This copyright notice MUST APPEAR in all copies of the script!
    ***************************************************************/

    /**
     * Ext Direct API Generator
     *
     * @author    Sebastian Kurfuerst <[email protected]>
     * @author    Stefan Galinski <[email protected]>
     * @package    TYPO3
     */
    class t3lib_extjs_ExtDirectApi {
        
    /**
         * @var array
         */
        
    protected $settings = array();

        
    /**
         * Constructs this object.
         */
        
    public function __construct() {
            if (isset(
    $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ExtDirect']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ExtDirect'])) {
                
    $this->settings $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ExtDirect'];
            }
        }

        
    /**
         * Parses the ExtDirect configuration array "$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ExtDirect']"
         * and feeds the given typo3ajax instance with the resulting information. The get parameter
         * "namespace" will be used to filter the configuration.
         *
         * This method makes usage of the reflection mechanism to fetch the methods inside the
         * defined classes together with their amount of parameters. This information are building
         * the API and are required by ExtDirect. The result is cached to improve the overall
         * performance.
         *
         * @param array $ajaxParams ajax parameters
         * @param TYPO3AJAX $ajaxObj typo3ajax instance
         * @return void
         */
        
    public function getAPI($ajaxParamsTYPO3AJAX $ajaxObj) {
            
    $filterNamespace t3lib_div::_GET('namespace');

            
    // look up into the cache
            
    $cacheIdentifier 'ExtDirectApi';
            
    $cacheHash md5($cacheIdentifier $filterNamespace serialize($this->settings));
            
    $cacheContent t3lib_pageSelect::getHash($cacheHash);

            
    // generate the javascript content if it wasn't found inside the cache and cache it!
            
    if (!$cacheContent) {
                
    $javascriptNamespaces $this->generateAPI($filterNamespace);
                
    t3lib_pageSelect::storeHash(
                    
    $cacheHash,
                    
    serialize($javascriptNamespaces),
                    
    $cacheIdentifier
                
    );
            } else {
                
    $javascriptNamespaces unserialize($cacheContent);
            }

            
    // return the generated javascript API configuration
            
    if (count($javascriptNamespaces)) {
                
    $setup '
                    if (typeof Ext.app.ExtDirectAPI !== "object") {
                        Ext.app.ExtDirectAPI = {};
                    }

                    if (typeof Object.extend !== "function") {
                        Object.extend = function(destination, source) {
                            for (var property in source) {
                                destination[property] = source[property];
                            }
                            return destination;
                        };
                    }
                '
    ;

                
    $ajaxObj->setContent($javascriptNamespaces);
                
    $ajaxObj->setContentFormat('javascript');
                
    $ajaxObj->setJavascriptCallbackWrap(
                    
    $setup 'Ext.app.ExtDirectAPI = Object.extend(Ext.app.ExtDirectAPI, |);'
                
    );
            }
        }

        
    /**
         * Generates the API that is configured inside the ExtDirect configuration
         * array "$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ExtDirect']".
         *
         * @param string $filerNamespace namespace that should be loaded like TYPO3.Backend
         * @return array javascript API configuration
         */
        
    protected function generateAPI($filterNamespace) {
            
    $javascriptNamespaces = array();
            if (
    is_array($this->settings)) {
                foreach (
    $this->settings as $javascriptName => $className) {
                    
    $splittedJavascriptName explode('.'$javascriptName);
                    
    $javascriptObjectName array_pop($splittedJavascriptName);
                    
    $javascriptNamespace implode('.'$splittedJavascriptName);

                    
    // only items inside the wanted namespace
                    
    if (strpos($javascriptNamespace$filterNamespace) !== 0) {
                        continue;
                    }

                    if (!isset(
    $javascriptNamespaces[$javascriptNamespace])) {
                        
    $javascriptNamespaces[$javascriptNamespace] = array(
                            
    'url' => t3lib_div::locationHeaderUrl('ajax.php?ajaxID=ExtDirect::route&namespace=') . rawurlencode($javascriptNamespace),
                            
    'type' => 'remoting',
                            
    'actions' => array(),
                            
    'namespace' => $javascriptNamespace
                        
    );
                    }

                    
    $serverObject t3lib_div::getUserObj($classNameFALSE);
                    
    $javascriptNamespaces[$javascriptNamespace]['actions'][$javascriptObjectName] = array();
                    foreach (
    get_class_methods($serverObject) as $methodName) {
                        
    $reflectionMethod = new ReflectionMethod($serverObject$methodName);
                        
    $numberOfParameters $reflectionMethod->getNumberOfParameters();
                        
    $docHeader $reflectionMethod->getDocComment();
                        
    $formHandler = (strpos($docHeader'@formHandler') !== FALSE);
                        
                        
    $javascriptNamespaces[$javascriptNamespace]['actions'][$javascriptObjectName][] = array(
                            
    'name' => $methodName,
                            
    'len' => $numberOfParameters,
                            
    'formHandler' => $formHandler
                        
    );
                    }
                }
            }

            return 
    $javascriptNamespaces;
        }
    }

    if (
    defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_extjs_extdirectapi.php'])    {
        include_once(
    $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_extjs_extdirectapi.php']);
    }

    ?>
    ROUTER

    PHP Code:
    <?php
    /***************************************************************
    *  Copyright notice
    *
    *  (c) 2010 Sebastian Kurfuerst <[email protected]>
    *  All rights reserved
    *
    *  This script is part of the TYPO3 project. The TYPO3 project 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.
    *
    *  The GNU General Public License can be found at
    *  http://www.gnu.org/copyleft/gpl.html.
    *  A copy is found in the textfile GPL.txt and important notices to the license
    *  from the author is found in LICENSE.txt distributed with these scripts.
    *
    *
    *  This script 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.
    *
    *  This copyright notice MUST APPEAR in all copies of the script!
    ***************************************************************/

    /**
     * Ext Direct Router
     *
     * @author    Sebastian Kurfuerst <[email protected]>
     * @author    Stefan Galinski <[email protected]>
     * @package    TYPO3
     */
    class t3lib_extjs_ExtDirectRouter {
        
    /**
         * Dispatches the incoming calls to methods about the ExtDirect API.
         *
         * @param aray $ajaxParams ajax parameters
         * @param TYPO3AJAX $ajaxObj typo3ajax instance
         * @return void
         */
        
    public function route($ajaxParamsTYPO3AJAX $ajaxObj) {
            try {
                
    $isForm FALSE;
                
    $isUpload FALSE;
                
    $rawPostData file_get_contents('php://input');
                
    $postParameters t3lib_div::_POST();
                
    $namespace t3lib_div::_GET('namespace');

                if (!empty(
    $postParameters['extAction'])) {
                    
    $isForm TRUE;
                    
    $isUpload $postParameters['extUpload'] === 'true';

                    
    $request->action $postParameters['extAction'];
                    
    $request->method $postParameters['extMethod'];
                    
    $request->tid $postParameters['extTID'];
                    
    $request->data = array($_POST $_FILES);
                } elseif (!empty(
    $rawPostData)) {
                    
    $request json_decode($rawPostData);
                } else {
                    throw new 
    t3lib_error_Exception('ExtDirect: Missing Parameters!');
                }

                
    $response NULL;
                if (
    is_array($request)) {
                    
    $response = array();
                    foreach (
    $request as $singleRequest) {
                        
    $response[] = $this->processRpc($singleRequest$namespace);
                    }
                } else {
                    
    $response $this->processRpc($request$namespace);
                }

                if (
    $isForm && $isUpload) {
                    
    $ajaxObj->setContentFormat('plain');
                    
    $response json_encode($response);
                    
    $response preg_replace('/&quot;/''\\&quot;'$response);

                    
    $response = array(
                        
    '<html><body><textarea>' .
                        
    $response .
                        
    '</textarea></body></html>'
                    
    );
                } else {
                    
    $ajaxObj->setContentFormat('jsonbody');
                }
            } catch (
    t3lib_error_Exception $exception) {
                
    $response = array(
                    
    'type' => 'exception',
                    
    'message' => $exception->getMessage(),
                    
    'where' => $exception->getTraceAsString()
                );
            }

            
    $ajaxObj->setContent($response);
        }


        
    /**
         * Processes an incoming extDirect call by executing the defined method. The configuration
         * array "$GLOBALS['TYPO3_CONF_VARS']['BE']['ExtDirect']" is taken to find the class/method
         * information.
         *
         * @param object $singleRequest request object from extJS
         * @param string $namespace namespace like TYPO3.Backend
         * @return mixed return value of the called method
         */
        
    protected function processRpc($singleRequest$namespace) {
            try {
                
    $endpointName $namespace '.' $singleRequest->action;

                
    // theoretically this can never happen, because of an javascript error on
                // the client side due the missing namespace/endpoint
                
    if (!isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ExtDirect'][$endpointName])) {
                    throw new 
    t3lib_error_Exception('ExtDirect: Call to undefined endpoint: ' $endpointName);
                }

                
    $response = array(
                    
    'type' => 'rpc',
                    
    'tid' => $singleRequest->tid,
                    
    'action' => $singleRequest->action,
                    
    'method' => $singleRequest->method
                
    );

                
    $endpointObject t3lib_div::getUserObj(
                    
    $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ExtDirect'][$endpointName],
                    
    FALSE
                
    );

                
    $response['result'] = call_user_func_array(
                    array(
    $endpointObject$singleRequest->method),
                    
    is_array($singleRequest->data) ? $singleRequest->data : array()
                );

            } catch (
    t3lib_error_Exception $exception) {
                throw 
    $exception;
            }

            return 
    $response;
        }
    }

    if (
    defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_extjs_extdirectrouter.php'])    {
        include_once(
    $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_extjs_extdirectrouter.php']);
    }

    ?>
    For Forms you simply use @formHandler in the phpDoc of the function. All works fine, even file uploads (which seems not working proper in the other php implementations)
    Last edited by [email protected]; 16 Mar 2010 at 8:46 AM. Reason: replaced PHP tags with CODE tags
    vg Steffen
    --------------------------------------
    Release Manager of TYPO3 4.5

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •