瀏覽代碼

Worked (mainly) on MySQL plugin

Taddes Kroes 14 年之前
父節點
當前提交
73ca598734
共有 4 個文件被更改,包括 342 次插入50 次删除
  1. 0 1
      .gitignore
  2. 26 5
      array.php
  3. 75 38
      base.php
  4. 241 6
      sql.php

+ 0 - 1
.gitignore

@@ -1,2 +1 @@
 docs
-index.php

+ 26 - 5
array.php

@@ -1,17 +1,18 @@
 <?php
+/**
+ * pQuery extention for executing common array functions.
+ * 
+ * @package pQuery
+ */
 
 /**
  * @todo Documentation
  */
-class pQueryArray extends pQuery {
+class pQueryArray extends pQuery implements pQueryExtension {
 	function get($index) {
 		return isset($this->variable[$index]) ? $this->variable[$index] : null;
 	}
 	
-	function count() {
-		return count($this->variable);
-	}
-	
 	function is_empty() {
 		return !$this->count();
 	}
@@ -31,8 +32,28 @@ class pQueryArray extends pQuery {
 			return call_user_func_array($function, $args);
 		}
 		
+		if( in_array($method, array('count')) )
+			return $method($this->variable);
+		
+		if( in_array($method, array('shuffle')) ) {
+			$method($this->variable);
+			return $this;
+		}
+		
 		return self::error('Plugin "%s" has no method "%s".', __CLASS__, $method);
 	}
 }
 
+/**
+ * Shortcut constructor for {@link pQuerySql}.
+ * 
+ * @returns pQuerySql A new pQuerySql instance.
+ * @see pQuerySql::__construct
+ */
+function _arr($array) {
+	return pQuery::create('pQueryArray', $array);
+}
+
+pQuery::extend('pQueryArray', 'array');
+
 ?>

+ 75 - 38
base.php

@@ -5,24 +5,19 @@
  * @package pQuery
  */
 
-/**
- * Indicates whether the framework is in debug mode.
- * 
- * @var bool
- */
-defined('DEBUG') || define('DEBUG', true);
-
-/**
- * The root location of the pQuery framework folder.
- * 
- * @var string
- */
-define('PQUERY_ROOT', 'D:/xampp/htdocs/pquery/');
+include_once 'config.php';
 
 /**
  * Common utility class.
  */
 class pQuery {
+	/**
+	 * Pattern of tha alias created for an extending plugin that has defined an alias.
+	 * 
+	 * @var string
+	 */
+	const CLASS_ALIAS_PATTERN = '__%s';
+	
 	/**
 	 * The minimum php version required to use the framework.
 	 * 
@@ -52,6 +47,13 @@ class pQuery {
 	 */
 	var $variable;
 	
+	/**
+	 * Additional arguments that were passed to the constructor.
+	 * 
+	 * @var array
+	 */
+	var $arguments = array();
+	
 	/**
 	 * Extend pQuery with a plugin.
 	 * 
@@ -75,7 +77,12 @@ class pQuery {
 				$class_name, $class_name::$REQUIRED_PHP_VERSION);
 		}
 		
-		self::$plugins[$alias === null ? $class_name : $alias] = $class_name;
+		if( $alias === null ) {
+			self::$plugins[$class_name] = $class_name;
+		} else {
+			self::$plugins[$alias] = $class_name;
+			class_alias($class_name, sprintf(self::CLASS_ALIAS_PATTERN, $alias));
+		}
 	}
 	
 	/**
@@ -92,15 +99,26 @@ class pQuery {
 			call_user_func_array('printf', $args);
 			//echo debug_backtrace();
 		}
+		
+		ERROR_IS_FATAL && exit;
 	}
 	
 	/**
 	 * Constructor.
 	 * 
+	 * @param string $class_name The class to constuct an object off.
 	 * @param mixed $variable The variable to use an utility on.
 	 */
-	function __construct($variable) {
-		$this->set_variable($variable);
+	static function create() {
+		$args = func_get_args();
+		$class_name = array_shift($args);
+		$obj = $class_name === null ? new self() : new $class_name();
+		$variable = array_shift($args);
+		
+		$obj->arguments = $args;
+		$obj->set_variable($variable);
+		
+		return $obj;
 	}
 	
 	/**
@@ -110,33 +128,34 @@ class pQuery {
 	 * @param bool $force Whether not to check the variables type against the accepted types.
 	 */
 	function set_variable($variable, $force=false) {
-		if( !$force ) {
-			$type = gettype($variable);
-			$class_name = get_class($this);
-			$accepts = $class_name::$accepts;
+		$this->variable = $variable;
+		
+		if( $force )
+			return;
+		
+		$type = gettype($variable);
+		$class_name = get_class($this);
+		$accepts = $class_name::$accepts;
+		
+		if( isset($accepts[$type]) ) {
+			$convert_method = $accepts[$type];
 			
-			if( isset($accepts[$type]) ) {
-				$convert_method = $accepts[$type];
-				
-				if( !method_exists($this, $convert_method) )
-					return self::error('Plugin "%s" has no conversion method "%s".', $class_name, $convert_method);
-				
-				$result = $this->$convert_method($variable);
-				$result === null || $variable = $result;
-			} else if( !in_array($type, $accepts) ) {
-				return self::error('Variable type "%s" is not accepted by class "%s".', $type, $class_name);
-			}
+			if( !method_exists($this, $convert_method) )
+				return self::error('Plugin "%s" has no conversion method "%s".', $class_name, $convert_method);
+			
+			$result = $this->$convert_method($variable);
+			$result === null || $this->variable = $result;
+		} else if( !in_array($type, $accepts) ) {
+			return self::error('Variable type "%s" is not accepted by class "%s".', $type, $class_name);
 		}
-		
-		$this->variable = $variable;
 	}
 	
 	/**
-	 * Load the file containing the utility class for a specific variable type.
+	 * Try to load the file containing the utility class for a specific variable type.
 	 * 
-	 * @param mixed $typoe the variable type of the class to load.
+	 * @param mixed $type the variable type of the class to load.
 	 */
-	static function load_type_class($type) {
+	static function load_plugin($type) {
 		$file = PQUERY_ROOT.$type.'.php';
 		
 		if( !file_exists($file) )
@@ -146,6 +165,24 @@ class pQuery {
 		
 		return true;
 	}
+	
+	/**
+	 * Include the nescessary files for the given plugins.
+	 */
+	static function require_plugins(/* $plugin1 [ , $plugin2, ... ] */) {
+		$plugins = func_get_args();
+		
+		foreach( $plugins as $plugin ) {
+			$path = PQUERY_ROOT.$plugin.'.php';
+			
+			if( !file_exists($path) ) {
+				return self::error('Required plugin "%s" could not be located (looked in "%s").',
+					$plugin, $path);
+			}
+			
+			include_once $path;
+		}
+	}
 }
 
 /**
@@ -157,7 +194,7 @@ interface pQueryExtension {
 	 * 
 	 * @param mixed $variable The variable to use an utility on.
 	 */
-	function __construct($variable);
+	//function __construct();
 }
 
 /**
@@ -174,7 +211,7 @@ function _p($variable, $plugin=null) {
 		// Use custom class for this variable type
 		$type = gettype($variable);
 		
-		if( pQuery::load_type_class($type) )
+		if( pQuery::load_plugin($type) )
 			$class_name .= ucfirst($type);
 	} else {
 		// Use custom plugin class

+ 241 - 6
sql.php

@@ -1,13 +1,245 @@
 <?php
+/**
+ * pQuery extention for executing MySQL queries.
+ * 
+ * @package pQuery
+ */
 
 /**
  * @todo Documentation
+ * @property query Alias for {@link pQuery::variable}.
  */
 class pQuerySql extends pQuery implements pQueryExtension {
+	const VARIABLE_PATTERN = '/\[\s*%s\s*\]/';
+	
 	static $accepts = array('string' => 'parse_query', 'resource');
 	
-	function parse_query($query) {
-		$this->query = $query;
+	/**
+	 * The MySQL link identifier.
+	 * 
+	 * @var resource
+	 */
+	static $link;
+	
+	/**
+	 * The result of the current query.
+	 * 
+	 * @var resource|bool
+	 */
+	var $result;
+	
+	/**
+	 * Indicates whether the query has been executed yet.
+	 * 
+	 * @var bool
+	 */
+	var $executed;
+	
+	/**
+	 * Parse the given query string.
+	 */
+	function parse_query() {
+		$args = $this->arguments;
+		
+		if( !count($args) )
+			return;
+		
+		// Replace variable indices by names equal to their indices
+		if( !is_array($args[0]) )
+			array_unshift($args, null);
+		
+		// Replace variables by their escaped values
+		$this->set($args);
+	}
+	
+	/**
+	 * Replace a set of variables with their (optionally escaped)
+	 * values in the current query.
+	 * 
+	 * @param array $variables The variables to replace.
+	 * @param bool $escape Whether to escape the variable values.
+	 * @returns pQuerySql The current object.
+	 */
+	function replace_variables($variables, $escape) {
+		$patterns = array_map('pQuerySql::variable_pattern', array_keys($variables));
+		$escape && $variables = array_map('pQuerySql::escape', $variables);
+		$this->variable = preg_replace($patterns, $variables, $this->variable);
+		$this->executed = false;
+		
+		return $this;
+	}
+	
+	/**
+	 * Replace a set of variables with their escaped values in the current query.
+	 * 
+	 * @param array $variables The variables to replace.
+	 * @returns pQuerySql The current object.
+	 */
+	function set($variables) {
+		return $this->replace_variables($variables, true);
+	}
+	
+	/**
+	 * Replace a set of variables with their non-escaped values in the current query.
+	 * 
+	 * @param array $variables The variables to replace.
+	 * @returns pQuerySql The current object.
+	 */
+	function set_plain($variables) {
+		return $this->replace_variables($variables, false);
+	}
+	
+	/**
+	 * Transform a variable name to a regex to be used as a replacement
+	 * pattern in a query.
+	 * 
+	 * @param string $name The variable name to transform.
+	 * @returns string The variable's replacement pattern.
+	 */
+	static function variable_pattern($name) {
+		return sprintf(self::VARIABLE_PATTERN, $name);
+	}
+	
+	/**
+	 * Execute the current query.
+	 * 
+	 * @returns pQuerySql The current object.
+	 */
+	function execute() {
+		self::assert_connection();
+		
+		//debug('query:', $this->query);
+		$result = mysql_query($this->query, self::$link);
+		
+		if( !$result )
+			return self::mysql_error();
+		
+		$this->result = $result;
+		$this->executed = true;
+		
+		return $this;
+	}
+	
+	/**
+	 * Fetch a row from the current result.
+	 * 
+	 * @param string $type The format of the result row.
+	 * @returns mixed The fetched row in the requested format.
+	 */
+	function fetch($type) {
+		$this->assert_execution();
+		
+		if( !$this->result )
+			return self::error('No valid result to fetch from.');
+		
+		$func = 'mysql_fetch_'.$type;
+		
+		if( !function_exists($func) )
+			return self::error('Fetch type "%s" is not supported.', $type);
+		
+		return $func($this->result);
+	}
+	
+	/**
+	 * Fetch all rows from the current result.
+	 * 
+	 * @param string $type The format of the result rows.
+	 * @returns array The result set.
+	 */
+	function fetch_all($type) {
+		$results = array();
+		
+		while( ($row = $this->fetch($type)) !== false ) {
+			$results[] = $row;
+		}
+		
+		return $results;
+		
+		return $func($this->result);
+	}
+	
+	/**
+	 * Getter for property {@link query}.
+	 */
+	function __get($name) {
+		if( $name == 'query' )
+			return $this->variable;
+	}
+	
+	/**
+	 * Setter for property {@link query}.
+	 */
+	function __set($name, $value) {
+		if( $name == 'query' )
+			$this->variable = $value;
+	}
+	
+	/**
+	 * Assert that the current query has been executed.
+	 */
+	function assert_execution() {
+		$this->executed || $this->execute();
+	}
+	
+	/**
+	 * Assert that the MySQL connection is opened.
+	 * 
+	 * @uses mysql_connect, mysql_select_db
+	 */
+	static function assert_connection() {
+		// Return if the connection has already been opened
+		if( self::$link )
+			return;
+		
+		if( !isset(Config::$sql) )
+			return self::error('Could not connect to database: no MySQL config found.');
+		
+		// Connect to the database
+		$c = Config::$sql;
+		$link = @mysql_connect($c['host'], $c['username'], $c['password']);
+		
+		if( $link === false )
+			return self::mysql_error();
+		
+		self::$link = $link;
+		
+		// Select the correct database
+		if( !@mysql_select_db($c['dbname'], $link) )
+			return self::mysql_error();
+	}
+	
+	/**
+	 * Echo the latest MySQL error.
+	 */
+	static function mysql_error() {
+		self::error('MySQL error %d: %s.', mysql_errno(), mysql_error());
+	}
+	
+	/**
+	 * Extention of {@link pQuery::error}, returning FALSE (useful in result loops).
+	 * Also, the current query is printed in DEBUG mode.
+	 * 
+	 * @returns bool FALSE
+	 */
+	static function error() {
+		parent::error('MySQL error %d: %s.', mysql_errno(), mysql_error());
+		
+		if( DEBUG )
+			echo $this->query;
+		
+		return false;
+	}
+	
+	/**
+	 * Escape a string for safe use in a query.
+	 * 
+	 * @param string $value The string to escape.
+	 * @uses mysql_real_escape_string
+	 */
+	static function escape($value) {
+		self::assert_connection();
+		
+		return mysql_real_escape_string($value, self::$link);
 	}
 }
 
@@ -17,11 +249,14 @@ class pQuerySql extends pQuery implements pQueryExtension {
  * @returns pQuerySql A new pQuerySql instance.
  * @see pQuerySql::__construct
  */
-function _s($query) {
-	return _p($query, 'sql');
+function _sql($query /* [ , $arg1, ... ] */) {
+	$args = func_get_args();
+	$query = array_shift($args);
+	array_unshift($args, 'pQuerySql', $query);
+	
+	return call_user_func_array('pQuery::create', $args);
 }
 
-pQuerySql::extend('pQuerySql', 'sql');
-debug(pQuery::$plugins);
+pQuery::extend('pQuerySql', 'sql');
 
 ?>