PHP Classes
Icontem

File: ACE.php


  Search   All class groups All class groups   Latest entries Latest entries   Top 10 charts Top 10 charts   Newsletter Newsletter   Blog Blog   Forums Forums   Help FAQ Help FAQ  
  Login   Register  
Recommend this page to a friend! ReTweet ReTweet Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Andrea Giammarchi  >  ACE  >  ACE.php  
File: ACE.php
Role: Class source
Content type: text/plain
Description: ACE for the Server
Class: ACE
Generate Javascript to call PHP objects using AJAX
 

Contents

Class file image Download
<?php
/**_______________________________________
 *
 *    ACE :: Asynchronous Client Engine
 * ---------------------------------------
 * 
 *    ################################
 *    #   #                          #
 *    #  ###                         #
 *    #                              #
 *    #              #               #
 *    #             ###              #
 *    #           #######            #
 *    #         ###########          #
 *    #       ###############        #
 *    #     ###################      #
 *    #    #########    #########    #
 *    #     ######   #   ######      #
 *    #             ###              #
 *    #           #######            #
 *    #                              #
 *    #                              #
 *    #                         ###  #
 *    #                          #   #
 *    ################################
 *
 * ---------------------------------------
 * @author              Andrea Giammarchi
 * @site                www.devpro.it
 * @version             1.0b
 * ---------------------------------------
 * 
 * Copyright (c) 2006 Andrea Giammarchi - www.devpro.it
 *
 * Permission is hereby granted, free of charge,
 * to any person obtaining a copy of this software and associated
 * documentation files (the "Software"),
 * to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * _______________________________________
 */



/**
 * CONFIGURATION :: PLEASE READ COMMENTS
 */

// GAME CONFIGURATION
$HAND_RULES = array(

	'DEBUG'	=> true,	// [true/false] creates a report for each class interaction
				// (requires a folder called "debug" with write permissions inside ACE.php place folder)
                                
	'UTF8'	=> false,	// [true/false] set ACE as an UTF8 compatible system
        
	'SPEED'	=> true,	// [true/false] increase server class inclusions, requires a dedicated name for classes
				// Example: class MyObject{} should be saved in a file called MyObject.class.php
                                // then suffix .class.php for each class file is required
                                
	'GZ'	=> false	// [true/false] try to use gz_compression to send responce to the client
				// NOTE: if enabled the progression value (0 to 100) will not be perfect
);



/**
 * ACE SYSTEM :: PLEASE DON'T MODIFY ANYTHING
 */

class ACE { // THE "CARD"
	
	/**
	 * ACE Class,
         * 	drived manager to parse and produce AJAX - PHP interaction
         *
         * @version	1.0
	 */
	
	var	$utf8 = false,		// is UTF8 enabled or not
		$continue = true,	// has any error
		$speed = false,		// uses direct require
		$gz = false,		// uses gz compression
		$dodebug = false,	// creates a debug file
		$debug = array(),	// debug informations
		$types = array(		// valid variable types
			's'=>'string', 'N'=>'null', 'O'=>'Class', 'b'=>'boolean', 'i'=>'integer', 'd'=>'float', 'a'=>'array', 'u'=>'undefined'
		);
	
	/**
	 * public constructor,
         * 	assigns properties to internal variables
         * 
         * new ACE(&config:array)
         *
         * @param	array		ACE configuration
	 */
	function ACE(&$settings) {
		$this->utf8 = &$settings['UTF8'];
		$this->speed = &$settings['SPEED'];
		$this->dodebug = &$settings['DEBUG'];
		$this->gz = !$this->dodebug && $settings['GZ'];
		if($this->dodebug) {
			@error_reporting(!defined('E_STRICT') ? 2047 : 2048);
			@set_error_handler(array(&$this, '__errorHandler'));
		}
	}
	
	/**
	 * public method,
         * 	includes external class file, parses input variables and if there aren't errors call the method with
         *      sent arguments.
         * 
         * self->callClassMethod(&className:string, &method:string):string
         *
         * @param	string		the name of the class to initializate
         * @param	string		the name of the method to use
         * @return	string		serialized value of method result or empty string if something is wrong
	 */
	function callClassMethod(&$className, &$method) {
		$i = 0;
		$istring = '_0';
		$hasinfo = false;
		$tmpclass = null;
		$args = $settings = $vars = $methodInfo = array();
		if($this->getClass($className)) {
			$tmpclass = new $className;
			$vars = get_object_vars($tmpclass);
			$settings = $this->getMethods($vars);
			if(in_array($method, $settings)) {
				$settings = $this->getMethodInformations($tmpclass, $method, $vars['methodTable']);
				if($settings['required'] === 0 || isset($_POST['_'.($settings['required'] - 1)])) {
					if(get_magic_quotes_gpc())
						$_POST = array_map(array(&$this, 'removePostMagicQuotes'), $_POST);
					$hasinfo = isset($settings['info']);
					while(isset($_POST[$istring]) && $this->goodRequestVariable($settings, $i, $_POST[$istring], $hasinfo)) {
						if($this->dodebug)
							array_push($methodInfo, '$args['.$i.'] = '.$_POST[$istring]);
						array_push($args, $this->unserialize($_POST[$istring]));
						$istring = '_'.(++$i);
					}
					if($this->continue) {
						$settings = array();
						$i = count($args);
						while($i)
							array_push($settings, '$args['.(--$i).']');
						$method .= '('.implode(',', array_reverse($settings)).')';
						eval('$istring=serialize(@$tmpclass->'.$method.');');
						if($this->dodebug)
							$method .= '<br />'.implode('<br />', $methodInfo);
					}
					elseif($this->dodebug)
						array_push($this->debug, 'ACE has killed itsself, bye bye.');
				}
				elseif($this->dodebug) {
					while(isset($_POST['_'.$i]))
						++$i;
					array_push($this->debug, $method.' method requires at least '.$settings['required'].' params and not '.$i);
				}
			}
			elseif($this->dodebug)
				array_push($this->debug, 'Choosed method is not availbale: '.$method);
		}
		elseif($this->dodebug)
			array_push($this->debug, 'Choosed Class or method is not valid: '.$className.'-&gt;'.$method);
		return $this->continue ? $istring : '';
	}
	
	/**
	 * public method,
         * 	verify class inclusion and parse methodTable informations.
         * 
         * self->exportClass(&className:string):array
         *
         * @param	string		the name of the class to export
         * @return	array		a list of every exported method (based on methodTable)
	 */
	function exportClass(&$className) {
		$tmpclass = null;
		$result = $settings = array();
		if($this->getClass($className)) {
			$tmpclass = new $className;
			$settings = get_object_vars($tmpclass);
			$settings = $this->getMethods($settings);
			for($a = 0, $b = count($settings); $a < $b; $a++)
				array_push($result, $this->utf8 ? utf8_encode($settings[$a]) : $settings[$a]);
		}
		elseif($this->dodebug)
			array_push($this->debug, 'Class '.$className.' is not valid');
		return $result;
	}
	
	/**
	 * public method,
         * 	try to include class file
         * 
         * self->getClass(&className:string):bool
         *
         * @param	string		the name of the class to include
         * @return	bool		true if class exists, false otherwise
	 */
	function getClass(&$className) {
		$classExists = false;
		if($this->speed) {
			@require $className.'.class.php';
			$classExists = class_exists($className);
		}
		else {
			$included = array();
			for($a = 0, $current = glob('ACE.php'), $files = glob('*.php'), $b = count($files); $a < $b; $a++) {
				if(!is_dir($files[$a]) && $files[$a] !== $current && !in_array($files[$a], $included)) {
					@require $files[$a];
					$classExists = class_exists($className);
					if($classExists)
						$a = $b;
					else
						$included = get_included_files();
				}
			}
		}
		return $classExists;
	}
	
	/**
	 * public method,
         * 	verify methodTable informations
         * 
         * self->getMethodInformations(&tmpclass:Object, &method:string, &vars:array):array
         *
         * @param	Object		an instance of the class
         * @param	string		the name of the method to use
         * @param	array		a list of each class variable (get_object_vars)
         * @return	array		a list of every required parameter and its type for choosed method
	 */
	function getMethodInformations(&$tmpclass, &$method, &$vars) {
		$i = 0;
		$result = array();
		if(
			isset($vars[$method]['arguments']) &&
			is_array($vars[$method]['arguments'])
		) {
			$result = array('info'=>array(), 'required'=>0);
			foreach($vars[$method]['arguments'] as $value) {
				array_push($result['info'], array(
					'type'=>(isset($value['type']) ? $this->parseType($value['type']) : 'u'),
					'required'=>(isset($value['required']) ? $value['required'] : false)
				));
				if($result['info'][$i]['required'])
					++$result['required'];
				++$i;
			}
		}
		return $result;
	}
	
	/**
	 * public method,
         * 	verify methodTable variable, if exists, gets every usable method
         * 
         * self->getMethods(&vars:array):array
         *
         * @param	array		a list of each class variable (get_object_vars)
         * @return	array		a list of every usable method defined in methodTable
	 */
	function getMethods(&$vars) {
		$result = array();
		if(isset($vars['methodTable']) && is_array($vars['methodTable'])) {
			foreach($vars['methodTable'] as $key => $value) {
				if(is_array($value) && (!isset($value['access']) || $value['access'] === 'remote'))
					array_push($result, $key);
			}
		}
		return $result;
	}
	
	/**
	 * public method,
         * 	verify if recieved variable is compatible with methodTable informations
         * 
         * self->goodRequestVariable(&settings:array, &i:int, &post:string, &hasinfo:bool):bool
         *
         * @param	array		a list of each methodtable valid information
         * @param	int		the index to use for informations
         * @param	string		recieved post variable
         * @param	bool		methodTable has informations
         * @return	bool		a boolean value that, if false, will kill a while loop and ACE execution
	 */
	function goodRequestVariable(&$settings, &$i, &$post, &$hasinfo) {
		if($this->continue)
			$this->continue = strlen($post) > 0;
		if($this->continue && $hasinfo && isset($settings['info'][$i])) {
			if($post{0} !== $settings['info'][$i]['type'] && $settings['info'][$i]['type'] !== 'u') {
				if($this->dodebug)
					array_push($this->debug, 'Variable #'.($i + 1).' of type '.$this->types[$settings['info'][$i]['type']].' is not defined or is not correct: '.$post);
				$this->continue = false;
			}
		}
		return $this->continue;
	}
	
	/**
	 * public method,
         * 	internal rapresentation of valid variable type
         * 
         * self->parseType(&type:string):string
         *
         * @param	string		a string defined on methodTable class array
         * @return	string		a single char that rappresents defined string type
	 */
	function parseType(&$type) {
		$result = 'u';
		switch(strtolower($type)) {
			case 'string':
				$result = 's';
				break;
			case 'int':
			case 'integer':
				$result = 'i';
				break;
			case 'null':
				$result = 'N';
			case 'class':
			case 'object':
				$result = 'O';
				break;
			case 'bool':
			case 'boolean':
				$result = 'b';
				break;
			case 'array':
				$result = 'a';
				break;
			case 'float':
			case 'double':
				$result = 'd';
				break;
		}
		return $result;
	}
	
	/**
	 * public method,
         * 	used to remove magic_quotes of $_POST array
         * 
         * self->removePostMagicQuotes(&post:mixed):mixed
         *
         * @param	mixed		array or a string
         * @return	string		stripslashed string or array to stripslash
	 */
	function removePostMagicQuotes(&$post) {
		return is_array($post) ? array_map(array(&$this, 'removePostMagicQuotes'), $post) : stripslashes($post);
	}
	
	/**
	 * public method,
         * 	verify that unserializzation works correctly and returns unserialized value.
         * 
         * self->unserialize(&post:string):mixed
         *
         * @param	string		variable serialized
         * @return	mixed		unserialized var
	 */
	function unserialize(&$post) {
		$result = $this->utf8 ? @unserialize($post) : @unserialize(utf8_decode($post));
		if($result === false && utf8_encode(serialize($result)) !== $post) {
			if($this->dodebug)
				array_push($this->debug, 'Unserialize Exception [utf8: '.($this->utf8 ? 'true' : 'false').'] with this var: '.$post);
			$this->continue = false;
		}
		return $result;
	}
	
	/**
	 * public method,
         * 	verify that unserializzation works correctly and returns unserialized value.
         * 
         * self->writeOutput(&output:string, htmloutput:bool):void
         *
         * @param	string		output to print
         * @param	bool		create html or javascript output output
	 */
	function writeOutput(&$output, $htmloutput) {
		if($this->gz)
			@ob_start('ob_gzhandler');
		if($htmloutput) {
			if($this->utf8)
				header('Content-type: text/html; charset=UTF-8');
			else
				header('Content-type: text/html; charset=ISO-8859-1');
			header('Content-Length: '.strlen($output));
			header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
			header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
			header('Cache-Control: no-store, no-cache, must-revalidate');
			header('Cache-Control: post-check=0, pre-check=0', false);
			header('Pragma: no-cache');
		}
		else {
			header('Content-type: text/javascript');
			header('Content-Length: '.strlen($output));
		}
		echo $output;
		if($this->gz)
			@ob_end_flush();
	}
	
	/**
	 * "private" method,
         * 	used to add errors to debugger
         * 
         * self->__errorHandler(errno:int, errstr:string, errfile:string, errline:int):void
         *
	 * @param	int		error number
         * @param	string		error message
         * @param	string		file that has trigged the error
         * @param	int		line of file
         */
	function __errorHandler($errno, $errstr, $errfile, $errline) {
		$errortype = array(
			1 	=> 'ERROR',
			2 	=> 'WARNING',
			4 	=> 'PARSE',
			8 	=> 'NOTICE',
			16	=> 'CORE_ERROR',
			32	=> 'CORE_WARNING',
			64	=> 'COMPILE_ERROR',
			128	=> 'COMPILE_WARNING',
			256	=> 'USER_ERROR',
			512	=> 'USER_WARNING',
			1024	=> 'USER_NOTICE',
			2047	=> 'ALL',
			2048	=> 'STRICT',
			4096	=> 'FUTURE'
		);
		array_push($this->debug, "[{$errno}] PHP {$errortype[$errno]} in line {$errline} of file {$errfile}<br />&nbsp; &nbsp; &nbsp; &nbsp; {$errstr}");
	}
}

class PAIR { // THE "HAND"
	
	/**
	 * PAIR Class,
         * 	ACE driver, makes ACE safe and manages debug output.
         *
         * @version	1.0
	 */


	/**
	 * public constructor,
         * 	REQUEST parser, ACE manager and DEBUG creator
         * 
         * new PAIR(&config:array)
         *
         * @param	array		ACE SYSTEM configuration
	 */
	function PAIR(&$settings) {
		
		$ace = &new ACE($settings);
		$call = '';
		$debugfile = '';
		$dodebug = false;
		$error = null;
		$file = null;
		$javascript = '';
		$output = '';
		$path = '';
		$report = array();
		$validClass = false;
		$methodExsists = isset($_GET['method']);
		if(isset($_GET['class']))
			$validClass = $this->verifyClass($_GET['class'], $methodExsists);
		
		if($ace->dodebug) {
			$path = $validClass ? 'debug/'.$_GET['class'].'.html' : 'debug/class.html';
			$file = @fopen($path, 'w');
			if($file) {
				$dodebug = true;
				$report = $this->getCommonErrors();
			}
		}
		if($validClass) {			
			if($dodebug)
				ob_start();
			if($methodExsists && $this->verifyMethod($_GET['class'], $_GET['method'])) {
				$output = $ace->callClassMethod($_GET['class'], $_GET['method']);
				if($output !== '')
					$ace->writeOutput($output, true);
				elseif($dodebug)
					array_push($ace->debug, $report['somethingwrong']);
			}
			else {
				if($dodebug)
					$debugfile = 'this.debug="'.substr($_SERVER['PHP_SELF'], 0, strpos(strtolower($_SERVER['PHP_SELF']), 'ace.php')).$path.'";';
				$call = $this->getJSCode($ace->utf8);
				for($class = explode('|', $_GET['class']), $a = 0, $b = count($class); $a < $b; $a++) {
					if($this->verifyClass($class[$a], $methodExsists)) {
						$output .= 'function '.$class[$a].'(){'.$debugfile;
						for($method = $ace->exportClass($class[$a]), $c = 0, $d = count($method); $c < $d; $c++) {
							$output .= 'this.'.$method[$c].'={call:function(){__ACE__(this,"'.$class[$a].'","'.$method[$c].'",arguments)}}';
							if(($c + 1) < $d)
								$output .= ',';
						}
						$output .= '};';
					}
					elseif($dodebug)
						array_push($ace->debug, $report['selfcall']);
				}
				$javascript = @file_get_contents('ACE.js');
				if($javascript) {
					$output = "{$javascript}\n{$call}\n{$output}";
					$ace->writeOutput($output, false);
				}
				elseif($dodebug)
					array_push($ace->debug, $report['missingfile']);
			}
		}
		elseif($dodebug)
			array_push($ace->debug, $report['selfcall']);
		if($dodebug) {
			$report = array();
			array_push($report, '<html><head><meta http-equiv="content-Type" content="text/html; charset='.($ace->utf8 ? 'UTF-8' : 'ISO-8859-1').'" /></head><body>');
			array_push($report,
				'<strong>ACE</strong> :: &quot;HAND&quot; INFORMATIONS :: '.gmdate('Y/m/d H:i:s').'<hr /><pre>',
				'<strong>Class:</strong> '.$_GET['class'].'<br /> <br />'
			);
			if(isset($_GET['method']))
				array_push($report, '<strong>Method:</strong> '.$_GET['method'].'<br /> <br />');
			if(count($ace->debug) === 0)
				array_push($report, '<strong>Any Error</strong>');
			else
				array_push($report, '<strong>Errors: </strong><br />'.implode('<br />', $ace->debug));
			array_push($report, '<br /> <br /><strong>Output:</strong><br />'.ob_get_contents().'</pre></body></html>');
			fwrite($file, implode("\r\n", $report));
			fclose($file);
			ob_end_flush();
		}
	}
	
	/**
	 * public method,
         * 	creates an associative array with common used method for debug
         * 
         * self->getCommonErrors(void):array
         *
         * @return	array		associative array with debug informations
	 */
	function getCommonErrors() {
		
		# POKER is "a joke" then this HAND "is a joke" too :-)
		return array(
			
			# means: ACE has recieved a $_GET['ACE'] parameter and cannot include itsself
			'selfcall'	=> 'Is this a bluff ? You just have an ACE in your hand and ACE wins the hand.',
			
			# means: file ACE.js not found and should be in the same ACE.php file directory
			'missingfile'	=> 'This game is for two players but ACE.js player is not present.',
			
			# means: ACE SYSTEM hasn't work correctly, something was wrong
			'somethingwrong'=> 'Any winner for this hand, let\'s start another one ?'
		);
	}
	
	/**
	 * public method,
         * 	generates javascript code
         * 
         * self->getJSCode(&utf8:bool):string
         *
         * @param	boolean		ACE uses utf8 or not
         * @return	string		runtime cross-browser javascript function rappresentation.
	 */
	function getJSCode(&$utf8) {
		$utf8string = $utf8 ? 'true' : 'false';
		return (
'function __ACE__(self,className,methodName,args){
function onProgress(){var p=ace.getProgress();if(self.progress)self.progress(p);if(p===100){clearInterval(i);ace.onLoadComplete()}};
var i=0,ace=new ACE('.$utf8string.');
ace.onError=function(s){if(self.error)self.error("Error #".concat(s))};
ace.onLoad=function(r){if(self.result)self.result(r)};
ace.sendAndLoad("'.$_SERVER['PHP_SELF'].'".concat("?class=",encodeURIComponent(className),"&method=",encodeURIComponent(methodName)),args);
i=setInterval(onProgress,10);};'
		);
	}

	/**
	 * public method,
         * 	check if required class is different from ACE then is safe for this file
         * 
         * self->verifyClass(&className:string):bool
         *
         * @param	string		the name of required class
         * @return	bool		verify passed or not
	 */
	function verifyClass(&$className, &$methodExsists) {
		return (preg_match('/^[\w]+$/', $className) && strtoupper($className) !== 'ACE') || (!$methodExsists && preg_match('/^[\w|]+$/', $className));
	}
	
	/**
	 * public method,
         * 	check if required method is different from constructor and if has correct chars
         * 
         * self->verifyMethod(&className:string, &method:string):bool
         *
         * @param	string		the name of required class
         * @param	string		the name of required method for required class
         * @return	bool		verify passed or not
	 */
	function verifyMethod(&$className, &$method) {
		return preg_match('/^[\w]+$/', $method) && strtoupper($method) !== strtoupper($className);
	}
}

// THE "GAME"
	/** LET'S START THIS GAME */
		new PAIR($HAND_RULES);
	/** YOU WIN ? ... THEN PLAY ANOTHER HAND ! */
?>

 
  Advertise on this site Advertise on this site   Site map Site map   Statistics Statistics   Site tips Site tips   Privacy policy Privacy policy   Contact Contact  

For more information send a message to :
info at phpclasses dot org.
Copyright (c) Icontem 1999-2009 PHP Classes - PHP Class Scripts
  PHP Book Reviews - Reviews of books and other products