| [ Index ] |
PHP Cross Reference of JPSpan 0.4 (beta) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * @package JPSpan 4 * @subpackage Server 5 * @version $Id: PostOffice.php,v 1.11 2004/11/23 13:49:56 harryf Exp $ 6 */ 7 //-------------------------------------------------------------------------------- 8 /** 9 * Define 10 */ 11 if ( !defined('JPSPAN') ) { 12 define ('JPSPAN',dirname(__FILE__).'/../'); 13 } 14 /** 15 * Include 16 */ 17 require_once JPSPAN . 'Server.php'; 18 //-------------------------------------------------------------------------------- 19 20 /** 21 * Class and method name passed in the URL with params passed 22 * as url-encoded POST data. Urls like 23 * http://localhost/server.php/Class/Method 24 * @package JPSpan 25 * @subpackage Server 26 * @public 27 */ 28 class JPSpan_Server_PostOffice extends JPSpan_Server { 29 30 /** 31 * Name of user defined handler that was called 32 * @param string 33 * @access private 34 */ 35 var $calledClass = NULL; 36 37 /** 38 * Name of method in handler 39 * @param string 40 * @access private 41 */ 42 var $calledMethod = NULL; 43 44 /** 45 * Request encoding to use (e.g. xml or php) 46 * @var string 47 * @access public 48 */ 49 var $RequestEncoding = 'xml'; 50 51 /** 52 * @access public 53 */ 54 function JPSpan_Server_PostOffice() { 55 parent::JPSpan_Server(); 56 } 57 58 /** 59 * Serve a request 60 * @param boolean send headers 61 * @return boolean FALSE if failed (invalid request - see errors) 62 * @access public 63 */ 64 function serve($sendHeaders = TRUE) { 65 require_once JPSPAN . 'Monitor.php'; 66 $M = & JPSpan_Monitor::instance(); 67 68 $this->calledClass = NULL; 69 $this->calledMethod = NULL; 70 71 if ( $this->resolveCall() ) { 72 73 $M->setRequestInfo('class',$this->calledClass); 74 $M->setRequestInfo('method',$this->calledMethod); 75 76 if ( FALSE !== ($Handler = & $this->getHandler($this->calledClass) ) ) { 77 78 $args = array(); 79 $M->setRequestInfo('args',$args); 80 81 if ( $this->getArgs($args) ) { 82 83 $M->setRequestInfo('args',$args); 84 85 $response = call_user_func_array( 86 array( 87 & $Handler, 88 $this->calledMethod 89 ), 90 $args 91 ); 92 93 } else { 94 95 $response = call_user_func( 96 array( 97 & $Handler, 98 $this->calledMethod 99 ) 100 ); 101 102 } 103 104 require_once JPSPAN . 'Serializer.php'; 105 106 $M->setResponseInfo('payload',$response); 107 $M->announceSuccess(); 108 109 $response = JPSpan_Serializer::serialize($response); 110 111 if ( $sendHeaders ) { 112 header('Content-Length: '.strlen($response)); 113 header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); 114 header('Last-Modified: ' . gmdate( "D, d M Y H:i:s" ) . 'GMT'); 115 header('Cache-Control: no-cache, must-revalidate'); 116 header('Pragma: no-cache'); 117 } 118 echo $response; 119 120 return TRUE; 121 122 } else { 123 124 trigger_error('Invalid handle for: '.$this->calledClass,E_USER_ERROR); 125 return FALSE; 126 127 } 128 129 } 130 return FALSE; 131 } 132 133 /** 134 * Resolve the call - identify the handler class and method and store 135 * locally 136 * @return boolean FALSE if failed (invalid request - see errors) 137 * @access private 138 */ 139 function resolveCall() { 140 $uriPath = explode('/',JPSpan_Server::getUriPath()); 141 142 if ( count($uriPath) != 2 ) { 143 trigger_error('Invalid call syntax',E_USER_ERROR); 144 return FALSE; 145 } 146 147 if ( preg_match('/^[a-z]+[0-9a-z_]*$/',$uriPath[0]) != 1 ) { 148 trigger_error('Invalid handler name: '.$uriPath[0],E_USER_ERROR); 149 return FALSE; 150 } 151 152 if ( preg_match('/^[a-z]+[0-9a-z_]*$/',$uriPath[1]) != 1 ) { 153 trigger_error('Invalid handler method: '.$uriPath[1],E_USER_ERROR); 154 return FALSE; 155 } 156 157 if ( !array_key_exists($uriPath[0],$this->descriptions) ) { 158 trigger_error('Unknown handler: '.$uriPath[0],E_USER_ERROR); 159 return FALSE; 160 } 161 162 if ( !in_array($uriPath[1],$this->descriptions[$uriPath[0]]->methods) ) { 163 trigger_error('Unknown handler method: '.$uriPath[1],E_USER_ERROR); 164 return FALSE; 165 } 166 167 $this->calledClass = $uriPath[0]; 168 $this->calledMethod = $uriPath[1]; 169 170 return TRUE; 171 172 } 173 174 /** 175 * Populate the args array if there are any 176 * @param array args (reference) 177 * @return boolean TRUE if request had args 178 * @access private 179 */ 180 function getArgs(& $args) { 181 require_once JPSPAN . 'RequestData.php'; 182 183 if ( $this->RequestEncoding == 'php' ) { 184 $args = JPSpan_RequestData_Post::fetch($this->RequestEncoding); 185 } else { 186 $args = JPSpan_RequestData_RawPost::fetch($this->RequestEncoding); 187 } 188 189 if ( is_array($args) ) { 190 return TRUE; 191 } 192 193 return FALSE; 194 } 195 196 /** 197 * Get the Javascript client generator 198 * @return JPSpan_Generator 199 * @access public 200 */ 201 function & getGenerator() { 202 require_once JPSPAN . 'Generator.php'; 203 $G = & new JPSpan_Generator(); 204 $G->init( 205 new JPSpan_PostOffice_Generator(), 206 $this->descriptions, 207 $this->serverUrl, 208 $this->RequestEncoding 209 ); 210 return $G; 211 } 212 } 213 214 //-------------------------------------------------------------------------------- 215 /** 216 * Generator for the JPSpan_Server_PostOffice 217 * @todo Much refactoring need to make code generation "pluggable" 218 * @see JPSpan_Server_PostOffice 219 * @package JPSpan 220 * @subpackage Server 221 * @access public 222 */ 223 class JPSpan_PostOffice_Generator { 224 225 /** 226 * @var array list of JPSpan_HandleDescription objects 227 * @access public 228 */ 229 var $descriptions; 230 231 /** 232 * @var string URL or server 233 * @access public 234 */ 235 var $serverUrl; 236 237 /** 238 * How requests should be encoded 239 * @var string request encoding 240 * @access public 241 */ 242 var $RequestEncoding; 243 244 /** 245 * Invokes code generator 246 * @param JPSpan_CodeWriter 247 * @return void 248 * @access public 249 */ 250 function generate(& $Code) { 251 252 $this->generateScriptHeader($Code); 253 foreach ( array_keys($this->descriptions) as $key ) { 254 $this->generateHandleClient($Code, $this->descriptions[$key]); 255 } 256 } 257 258 /** 259 * Generate the starting includes section of the script 260 * @param JPSpan_CodeWriter 261 * @return void 262 * @access private 263 */ 264 function generateScriptHeader(& $Code) { 265 ob_start(); 266 ?> 267 /**@ 268 * include 'remoteobject.js'; 269 <?php 270 if ( $this->RequestEncoding == 'xml' ) { 271 ?> 272 * include 'request/rawpost.js'; 273 * include 'encode/xml.js'; 274 <?php 275 } else { 276 ?> 277 * include 'request/post.js'; 278 * include 'encode/php.js'; 279 <?php 280 } 281 ?> 282 */ 283 <?php 284 $Code->append(ob_get_contents()); 285 ob_end_clean(); 286 } 287 288 /** 289 * Generate code for a single description (a single PHP class) 290 * @param JPSpan_CodeWriter 291 * @param JPSpan_HandleDescription 292 * @return void 293 * @access private 294 */ 295 function generateHandleClient(& $Code, & $Description) { 296 ob_start(); 297 ?> 298 299 function <?php echo $Description->Class; ?>() { 300 301 var oParent = new JPSpan_RemoteObject(); 302 303 if ( arguments[0] ) { 304 oParent.Async(arguments[0]); 305 } 306 307 oParent.__serverurl = '<?php 308 echo $this->serverUrl . '/' . $Description->Class; ?>'; 309 310 oParent.__remoteClass = '<?php echo $Description->Class; ?>'; 311 312 <?php 313 if ( $this->RequestEncoding == 'xml' ) { 314 ?> 315 oParent.__request = new JPSpan_Request_RawPost(new JPSpan_Encode_Xml()); 316 <?php 317 } else { 318 ?> 319 oParent.__request = new JPSpan_Request_Post(new JPSpan_Encode_PHP()); 320 <?php 321 } 322 323 foreach ( $Description->methods as $method ) { 324 ?> 325 326 // @access public 327 oParent.<?php echo $method; ?> = function() { 328 var url = this.__serverurl+'/<?php echo $method; ?>/'; 329 return this.__call(url,arguments,'<?php echo $method; ?>'); 330 }; 331 <?php 332 } 333 ?> 334 335 return oParent; 336 } 337 338 <?php 339 $Code->append(ob_get_contents()); 340 ob_end_clean(); 341 } 342 } 343 344
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Fri Nov 26 11:42:46 2004 | Cross-referenced by PHPXref 0.6 |