diff options
author | Volker Thiel <riker09@gmx.de> | 2013-03-07 08:43:41 +0100 |
---|---|---|
committer | Volker Thiel <riker09@gmx.de> | 2013-03-07 08:43:41 +0100 |
commit | 763a79a04e9ee5efbc24c0c335e77a86cacb02be (patch) | |
tree | 0efb570d95c55ab34e5089a2497c56bc5abd05f6 /modules | |
parent | ee3133db1bcbab537a03db6ad498e6de689dc04a (diff) | |
parent | 2e8b8467e22f984b42a25b1d90c1a3a19ea4a99d (diff) | |
download | PHPixie-763a79a04e9ee5efbc24c0c335e77a86cacb02be.zip PHPixie-763a79a04e9ee5efbc24c0c335e77a86cacb02be.tar.gz PHPixie-763a79a04e9ee5efbc24c0c335e77a86cacb02be.tar.bz2 |
Merge branch 'master' into guidelines
Diffstat (limited to 'modules')
-rw-r--r-- | modules/database/classes/database/result.php | 84 | ||||
-rw-r--r-- | modules/database/classes/db.php | 13 | ||||
-rw-r--r-- | modules/database/classes/driver/mysql/db.php | 133 | ||||
-rw-r--r-- | modules/database/classes/driver/mysql/result.php | 45 | ||||
-rw-r--r-- | modules/database/classes/driver/pdo/db.php | 137 | ||||
-rw-r--r-- | modules/database/classes/driver/pdo/query.php | 448 | ||||
-rw-r--r-- | modules/database/classes/driver/pdo/result.php | 45 | ||||
-rw-r--r-- | modules/orm/classes/orm.php | 962 | ||||
-rw-r--r-- | modules/orm/classes/orm/result.php | 233 |
9 files changed, 1191 insertions, 909 deletions
diff --git a/modules/database/classes/database/result.php b/modules/database/classes/database/result.php index 5873457..1c6b9fe 100644 --- a/modules/database/classes/database/result.php +++ b/modules/database/classes/database/result.php @@ -5,7 +5,8 @@ * provides iterator support, so it can be used inside loops like 'foreach' * @package Database */ -abstract class Result_Database implements Iterator { +abstract class Result_Database implements Iterator +{ /** * Current row number @@ -19,7 +20,7 @@ abstract class Result_Database implements Iterator { * @var mixed * @access protected */ - protected $_result; + protected $_result; /** * Current row @@ -27,22 +28,23 @@ abstract class Result_Database implements Iterator { * @access protected */ protected $_row; - - /** + + /** * If at least one row has been fetched * @var object * @access protected */ - protected $_fetched = false; - + protected $_fetched = false; + /** * Returns current row * * @return object Current row in result set * @access public */ - public function current() { - $this->check_fetched(); + public function current() + { + $this->check_fetched(); return $this->_row; } @@ -52,8 +54,9 @@ abstract class Result_Database implements Iterator { * @return integer Row number * @access public */ - public function key() { - $this->check_fetched(); + public function key() + { + $this->check_fetched(); return $this->_position; } @@ -63,9 +66,10 @@ abstract class Result_Database implements Iterator { * @return bool True if row exists * @access public */ - public function valid() { - $this->check_fetched(); - return $this->_row!=null; + public function valid() + { + $this->check_fetched(); + return $this->_row != null; } /** @@ -74,36 +78,44 @@ abstract class Result_Database implements Iterator { * @return array Array of rows * @access public */ - public function as_array() { - $arr = array(); - foreach($this as $row) - $arr[] = $row; - return $arr; - } - - /** + public function as_array() + { + $arr = array(); + foreach ($this as $row) + { + $arr[] = $row; + } + return $arr; + } + + /** * Checks if the rows from the result set have - * been fetched at least once. If not fetches first row. + * been fetched at least once. If not fetches first row. * * @access public */ - protected function check_fetched() { - if (!$this->_fetched) { - $this->_fetched=true; - $this->next(); - } - } - - /** + protected function check_fetched() + { + if (!$this->_fetched) + { + $this->_fetched = true; + $this->next(); + } + } + + /** * Gets a column from the current row in the set * - * @param string $column Column name + * @param string $column Column name * @return mixed Column value * @access public */ - public function get($column) { - if ($this->valid() && isset($this->_row->$column)) - return $this->_row->$column; - } - + public function get($column) + { + if ($this->valid() && isset($this->_row->$column)) + { + return $this->_row->$column; + } + } + }
\ No newline at end of file diff --git a/modules/database/classes/db.php b/modules/database/classes/db.php index 42e8534..4979450 100644 --- a/modules/database/classes/db.php +++ b/modules/database/classes/db.php @@ -8,6 +8,7 @@ */ abstract class DB { + /** * An associative array of connections to databases * @var array @@ -66,11 +67,11 @@ abstract class DB * @return Result_Database Current drivers implementation of Result_Database * @access public */ - public function named_query($query, $params=array()) + public function named_query($query, $params = array()) { $bind = array(); - preg_match_all('#:(\w+)#is', $query, $matches,PREG_SET_ORDER); - foreach($matches as $match) + preg_match_all('#:(\w+)#is', $query, $matches, PREG_SET_ORDER); + foreach ($matches as $match) { if (isset($params[$match[1]])) { @@ -78,7 +79,7 @@ abstract class DB $bind[] = $params[$match[1]]; } } - return $this->execute($query,$bind); + return $this->execute($query, $bind); } /** @@ -105,7 +106,7 @@ abstract class DB * @access public * @static */ - public static function query($type,$config = 'default') + public static function query($type, $config = 'default') { return DB::instance($config)->build_query($type); } @@ -133,7 +134,7 @@ abstract class DB * @access public * @static */ - public static function instance($config='default') + public static function instance($config = 'default') { if (!isset(DB::$_instances[$config])) { diff --git a/modules/database/classes/driver/mysql/db.php b/modules/database/classes/driver/mysql/db.php index 0b2e03f..88df9b8 100644 --- a/modules/database/classes/driver/mysql/db.php +++ b/modules/database/classes/driver/mysql/db.php @@ -4,23 +4,24 @@ * Mysqli Database Implementation
* @package Database
*/
-class DB_Mysql_Driver extends DB{
+class DB_Mysql_Driver extends DB
+{
/**
* Mysqli database connection object
* @var mysqli
* @access public
- * @link http://php.net/manual/en/class.mysqli.php
+ * @link http://php.net/manual/en/class.mysqli.php
*/
- public $conn;
-
- /**
+ public $conn;
+
+ /**
* Type of the database, mysql.
* @var string
* @access public
*/
- public $db_type='mysql';
-
+ public $db_type = 'mysql';
+
/**
* Initializes database connection
*
@@ -28,47 +29,51 @@ class DB_Mysql_Driver extends DB{ * @return void
* @access public
*/
- public function __construct($config) {
- $this->conn = mysqli_connect(
- Config::get("database.{$config}.host",'localhost'),
- Config::get("database.{$config}.user",''),
- Config::get("database.{$config}.password",''),
- Config::get("database.{$config}.db")
- );
- $this->conn->set_charset("utf8");
- }
-
- /**
+ public function __construct($config)
+ {
+ $this->conn = mysqli_connect(
+ Config::get("database.{$config}.host", 'localhost'), Config::get("database.{$config}.user", ''), Config::get("database.{$config}.password", ''), Config::get("database.{$config}.db")
+ );
+ $this->conn->set_charset("utf8");
+ }
+
+ /**
* Gets column names for the specified table
*
- * @param string $table Name of the table to get columns from
+ * @param string $table Name of the table to get columns from
* @return array Array of column names
- * @throw Exception if table doesn't exist
+ * @throw Exception if table doesn't exist
* @access public
*/
- public function list_columns($table) {
- $columns=array();
- $table_desc = $this->execute("DESCRIBE `$table`");
- Debug::log($table_desc);
- if (!$table_desc->valid())
- throw new Exception("Table '{$table}' doesn't exist");
- foreach($table_desc as $column)
- $columns[] = $column->Field;
-
- return $columns;
- }
-
+ public function list_columns($table)
+ {
+ $columns = array();
+ $table_desc = $this->execute("DESCRIBE `$table`");
+ Debug::log($table_desc);
+ if (!$table_desc->valid())
+ {
+ throw new Exception("Table '{$table}' doesn't exist");
+ }
+ foreach ($table_desc as $column)
+ {
+ $columns[] = $column->Field;
+ }
+
+ return $columns;
+ }
+
/**
* Builds a new Query implementation
*
* @param string $type Query type. Available types: select,update,insert,delete,count
* @return Query_Mysql_Driver Returns a Mysqli implementation of a Query.
* @access public
- * @see Query_Database
+ * @see Query_Database
*/
- public function build_query($type) {
- return new Query_Mysql_Driver($this,$type);
- }
+ public function build_query($type)
+ {
+ return new Query_Mysql_Driver($this, $type);
+ }
/**
* Gets the id of the last inserted row.
@@ -76,9 +81,10 @@ class DB_Mysql_Driver extends DB{ * @return mixed Row id
* @access public
*/
- public function get_insert_id() {
- return $this->conn->insert_id;
- }
+ public function get_insert_id()
+ {
+ return $this->conn->insert_id;
+ }
/**
* Executes a prepared statement query
@@ -88,28 +94,33 @@ class DB_Mysql_Driver extends DB{ * @return Result_Mysql_Driver Mysqli implementation of a database result
* @access public
* @throws Exception If the query resulted in an error
- * @see Database_Result
+ * @see Database_Result
*/
- public function execute($query, $params = array()) {
- $cursor = $this->conn->prepare($query);
- if (!$cursor)
- throw new Exception("Database error: {$this->conn->error} \n in query:\n{$query}");
- $types = '';
- $bind = array();
- $refs = array();
- if(!empty($params)){
- foreach($params as $key=>$param) {
- $refs[$key]=is_array($param)?$param[0]:$param;
- $bind[]=&$refs[$key];
- $types.=is_array($param)?$param[1]:'s';
- }
- array_unshift($bind, $types);
-
- call_user_func_array(array($cursor, 'bind_param'), $bind);
- }
- $cursor->execute();
- $res = $cursor->get_result();
- return new Result_Mysql_Driver($res);
+ public function execute($query, $params = array())
+ {
+ $cursor = $this->conn->prepare($query);
+ if (!$cursor)
+ {
+ throw new Exception("Database error: {$this->conn->error} \n in query:\n{$query}");
+ }
+ $types = '';
+ $bind = array();
+ $refs = array();
+ if (!empty($params))
+ {
+ foreach ($params as $key => $param)
+ {
+ $refs[$key] = is_array($param) ? $param[0] : $param;
+ $bind[] = &$refs[$key];
+ $types .= is_array($param) ? $param[1] : 's';
+ }
+ array_unshift($bind, $types);
+
+ call_user_func_array(array($cursor, 'bind_param'), $bind);
+ }
+ $cursor->execute();
+ $res = $cursor->get_result();
+ return new Result_Mysql_Driver($res);
+ }
- }
}
\ No newline at end of file diff --git a/modules/database/classes/driver/mysql/result.php b/modules/database/classes/driver/mysql/result.php index a2b2a90..e9de4a5 100644 --- a/modules/database/classes/driver/mysql/result.php +++ b/modules/database/classes/driver/mysql/result.php @@ -4,7 +4,8 @@ * Database result implementation for Mysqli * @package Database */ -class Result_Mysql_Driver extends Result_Database { +class Result_Mysql_Driver extends Result_Database +{ /** * Initializes new result object @@ -12,11 +13,12 @@ class Result_Mysql_Driver extends Result_Database { * @param mysqli_result $result Mysqli Result * @return void * @access public - * @link http://php.net/manual/en/class.mysqli-result.php + * @link http://php.net/manual/en/class.mysqli-result.php */ - public function __construct($result) { - $this->_result = $result; - } + public function __construct($result) + { + $this->_result = $result; + } /** * Throws exception if rewind is attempted. @@ -25,25 +27,32 @@ class Result_Mysql_Driver extends Result_Database { * @access public * @throws Exception If rewind is attempted */ - public function rewind() { - if($this->_position>0) - throw new Exception('Mysqli result cannot be rewound for unbuffered queries.'); + public function rewind() + { + if ($this->_position > 0) + { + throw new Exception('Mysqli result cannot be rewound for unbuffered queries.'); + } } - + /** * Iterates to the next row in the result set * * @return void * @access public */ - public function next() { - $this->check_fetched(); - $this->_row = $this->_result->fetch_object(); - if ($this->_row) { - $this->_position++; - }else { - $this->_result->free(); - } + public function next() + { + $this->check_fetched(); + $this->_row = $this->_result->fetch_object(); + if ($this->_row) + { + $this->_position++; + } + else + { + $this->_result->free(); + } } - + }
\ No newline at end of file diff --git a/modules/database/classes/driver/pdo/db.php b/modules/database/classes/driver/pdo/db.php index 69a7457..5b81d66 100644 --- a/modules/database/classes/driver/pdo/db.php +++ b/modules/database/classes/driver/pdo/db.php @@ -4,23 +4,24 @@ * PDO Database implementation. * @package Database */ -class DB_PDO_Driver extends DB{ +class DB_PDO_Driver extends DB +{ /** * Connection object * @var PDO * @access public - * @link http://php.net/manual/en/class.pdo.php + * @link http://php.net/manual/en/class.pdo.php */ - public $conn; - - /** + public $conn; + + /** * Type of the database, e.g. mysql, pgsql etc. * @var string * @access public */ - public $db_type; - + public $db_type; + /** * Initializes database connection * @@ -28,17 +29,18 @@ class DB_PDO_Driver extends DB{ * @return void * @access public */ - public function __construct($config) { - $this->conn = new PDO( - Config::get("database.{$config}.connection"), - Config::get("database.{$config}.user",''), - Config::get("database.{$config}.password",'') - ); - $this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - $this->db_type = strtolower(str_replace('PDO_', '', $this->conn->getAttribute(PDO::ATTR_DRIVER_NAME))); - if($this->db_type!='sqlite') - $this->conn->exec("SET NAMES utf8"); - } + public function __construct($config) + { + $this->conn = new PDO( + Config::get("database.{$config}.connection"), Config::get("database.{$config}.user", ''), Config::get("database.{$config}.password", '') + ); + $this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $this->db_type = strtolower(str_replace('PDO_', '', $this->conn->getAttribute(PDO::ATTR_DRIVER_NAME))); + if ($this->db_type != 'sqlite') + { + $this->conn->exec("SET NAMES utf8"); + } + } /** * Builds a new Query implementation @@ -46,11 +48,12 @@ class DB_PDO_Driver extends DB{ * @param string $type Query type. Available types: select,update,insert,delete,count * @return Query_PDO_Driver Returns a PDO implementation of a Query. * @access public - * @see Query_Database + * @see Query_Database */ - public function build_query($type) { - return new Query_PDO_Driver($this,$type); - } + public function build_query($type) + { + return new Query_PDO_Driver($this, $type); + } /** * Gets the id of the last inserted row. @@ -58,39 +61,52 @@ class DB_PDO_Driver extends DB{ * @return mixed Row id * @access public */ - public function get_insert_id() { - if ($this->db_type == 'pgsql') - return $this->execute('SELECT lastval() as id')->current()->id; - return $this->conn->lastInsertId(); - } - - /** + public function get_insert_id() + { + if ($this->db_type == 'pgsql') + { + return $this->execute('SELECT lastval() as id')->current()->id; + } + return $this->conn->lastInsertId(); + } + + /** * Gets column names for the specified table * - * @param string $table Name of the table to get columns from + * @param string $table Name of the table to get columns from * @return array Array of column names * @access public */ - public function list_columns($table) { - $columns=array(); - if ($this->db_type == 'mysql') { - $table_desc = $this->execute("DESCRIBE `$table`"); - foreach($table_desc as $column) - $columns[]=$column->Field; - } - if ($this->db_type == 'pgsql') { - $table_desc = $this->execute("select column_name from information_schema.columns where table_name = '{$table}' and table_catalog=current_database();"); - foreach($table_desc as $column) - $columns[]=$column->column_name; - } - if ($this->db_type == 'sqlite') { - $table_desc = $this->execute("PRAGMA table_info('$table')"); - foreach($table_desc as $column) - $columns[]=$column->name; - } - return $columns; - } - + public function list_columns($table) + { + $columns = array(); + if ($this->db_type == 'mysql') + { + $table_desc = $this->execute("DESCRIBE `$table`"); + foreach ($table_desc as $column) + { + $columns[] = $column->Field; + } + } + if ($this->db_type == 'pgsql') + { + $table_desc = $this->execute("select column_name from information_schema.columns where table_name = '{$table}' and table_catalog=current_database();"); + foreach ($table_desc as $column) + { + $columns[] = $column->column_name; + } + } + if ($this->db_type == 'sqlite') + { + $table_desc = $this->execute("PRAGMA table_info('$table')"); + foreach ($table_desc as $column) + { + $columns[] = $column->name; + } + } + return $columns; + } + /** * Executes a prepared statement query * @@ -99,14 +115,17 @@ class DB_PDO_Driver extends DB{ * @return Result_PDO_Driver PDO implementation of a database result * @access public * @throws Exception If the query resulted in an error - * @see Database_Result + * @see Database_Result */ - public function execute($query, $params = array()) { - $cursor = $this->conn->prepare($query); - if (!$cursor->execute($params)) { - $error = $cursor->errorInfo(); - throw new Exception("Database error:\n".$error[2]." \n in query:\n{$query}"); - } - return new Result_PDO_Driver($cursor); - } + public function execute($query, $params = array()) + { + $cursor = $this->conn->prepare($query); + if (!$cursor->execute($params)) + { + $error = $cursor->errorInfo(); + throw new Exception("Database error:\n".$error[2]." \n in query:\n{$query}"); + } + return new Result_PDO_Driver($cursor); + } + }
\ No newline at end of file diff --git a/modules/database/classes/driver/pdo/query.php b/modules/database/classes/driver/pdo/query.php index f23e28b..d37e459 100644 --- a/modules/database/classes/driver/pdo/query.php +++ b/modules/database/classes/driver/pdo/query.php @@ -4,22 +4,23 @@ * PDO implementation of the database Query * @package Database */ -class Query_PDO_Driver extends Query_Database { - - /** +class Query_PDO_Driver extends Query_Database +{ + + /** * Type of the database, e.g. mysql, pgsql etc. * @var string * @access public */ - protected $_db_type; - - /** + protected $_db_type; + + /** * Character to use for quoting fields * @var string * @access public */ - protected $_quote; - + protected $_quote; + /** * Creates a new query object, checks which driver we are using and set the character used for quoting * @@ -27,188 +28,247 @@ class Query_PDO_Driver extends Query_Database { * @param string $type Query type. Available types: select, update, insert, delete, count * @return void * @access public - * @see Query_Database::__construct() + * @see Query_Database::__construct() */ - public function __construct($db, $type) { - parent::__construct($db, $type); - $this->_db_type = $this->_db->db_type; - $this->_quote=$this->_db_type=='mysql'?'`':'"'; - } - + public function __construct($db, $type) + { + parent::__construct($db, $type); + $this->_db_type = $this->_db->db_type; + $this->_quote = $this->_db_type == 'mysql' ? '`' : '"'; + } + /** * Puts quotes around a string * * @param string $str String to be enclosed in quotes * @return string String surrounded with quotes * @access protected - */ - protected function quote($str) { - return $this->_quote.$str.$this->_quote; - } - + */ + protected function quote($str) + { + return $this->_quote.$str.$this->_quote; + } + /** * If a string is passed escapes a field by enclosing it in specified quotes. - * If you pass an Expression_Database object the value will be inserted into the query unescaped + * If you pass an Expression_Database object the value will be inserted into the query unescaped * * @param mixed $field Field to be escaped or an Expression_Database object - * if the field must not be escaped + * if the field must not be escaped * @return string Escaped field representation * @access public - * @see Expression_Database + * @see Expression_Database */ - public function escape_field($field) { - if (is_object($field) && get_class($field) == 'Expression_Database') - return $field->value; - $field = explode('.', $field); - if (count($field) == 1) - array_unshift($field,$this->last_alias()); - $str = $this->quote($field[0]).'.'; - if (trim($field[1]) == '*') - return $str.'*'; - return $str.$this->quote($field[1]); - } - + public function escape_field($field) + { + if (is_object($field) && get_class($field) == 'Expression_Database') + { + return $field->value; + } + $field = explode('.', $field); + if (count($field) == 1) + { + array_unshift($field, $this->last_alias()); + } + $str = $this->quote($field[0]).'.'; + if (trim($field[1]) == '*') + { + return $str.'*'; + } + return $str.$this->quote($field[1]); + } + /** * Replaces the value with ? and appends it to the parameters array - * If you pass an Expression_Database object the value will be inserted into the query unescaped + * If you pass an Expression_Database object the value will be inserted into the query unescaped * @param mixed $val Value to be escaped or an Expression_Database object - * if the value must not be escaped + * if the value must not be escaped * @param array &$params Reference to parameters array * @return string Escaped value representation * @access public */ - public function escape_value($val,&$params) { - if (is_object($val) && get_class($val) == 'Expression_Database') - return $val->value; - $params[] = $val; - return '?'; - } - + public function escape_value($val, &$params) + { + if (is_object($val) && get_class($val) == 'Expression_Database') + { + return $val->value; + } + $params[] = $val; + return '?'; + } + /** * Builds a query and fills the $params array with parameter values * * @return array An array with a prepared query string and an array of parameters * @access public */ - public function query() { - - $query = ''; - $params = array(); - if ($this->_type == 'insert') { - $query.= "INSERT INTO {$this->quote($this->_table)} "; - if (empty($this->_data) && $this->_db_type == 'pgsql'){ - $query.= "DEFAULT VALUES "; - }else{ - $columns = ''; - $values = ''; - $first = true; - foreach($this->_data as $key => $val) { - if (!$first) { - $values.= ', '; - $columns.= ', '; - }else { - $first=false; - } - $columns.= $this->quote($key); - $values.=$this->escape_value($val,$params); - } - $query.= "({$columns}) VALUES({$values})"; - } - }else{ - if ($this->_type == 'select'){ - $query.= "SELECT "; - if($this->_fields==null){ - $query.= "* "; - }else{ - $first = true; - foreach($this->_fields as $f) { - if (!$first) { - $query.=", "; - }else { - $first = false; - } - if(is_array($f)){ - $query.= "{$this->escape_field($f[0])} AS {$f[1]} "; - }else { - $query.= "{$this->escape_field($f)} "; - } - } - } - $query.= "FROM {$this->quote($this->_table)} "; - } - if ($this->_type == 'count') { - $query.= "SELECT COUNT(*) as {$this->quote('count')} FROM {$this->quote($this->_table)} "; - } - if ($this->_type == 'delete') { - if($this->_db_type!='sqlite'){ - $query.= "DELETE {$this->last_alias()}.* FROM {$this->quote($this->_table)} "; - }else { - if (!empty($this->_joins)) - throw new Exception("SQLite doesn't support deleting a table with JOIN in the query"); - $query.= "DELETE FROM {$this->quote($this->_table)} "; - } - } - if($this->_type=='update'){ - $query.= "UPDATE {$this->quote($this->_table)} SET "; - $first = true; - foreach($this->_data as $key=>$val){ - if (!$first) { - $query.=", "; - }else { - $first=false; - } - $query.= "{$this->quote($key)} = {$this->escape_value($val,$params)}"; - } - $query.= " "; - } - - foreach($this->_joins as $join) { - $table = $join[0]; - if (is_array($table)){ - $table = "{$this->quote($table[0])} as {$this->quote($table[1])}"; - }else { - $table="{$this->quote($table)}"; - } - $query.= strtoupper($join[1])." JOIN {$table} ON {$this->get_condition_query($join[2],$params,true,true)} "; - } + public function query() + { + + $query = ''; + $params = array(); + if ($this->_type == 'insert') + { + $query.= "INSERT INTO {$this->quote($this->_table)} "; + if (empty($this->_data) && $this->_db_type == 'pgsql') + { + $query.= "DEFAULT VALUES "; + } + else + { + $columns = ''; + $values = ''; + $first = true; + foreach ($this->_data as $key => $val) + { + if (!$first) + { + $values .= ', '; + $columns .= ', '; + } + else + { + $first = false; + } + $columns .= $this->quote($key); + $values .= $this->escape_value($val, $params); + } + $query .= "({$columns}) VALUES({$values})"; + } + } + else + { + if ($this->_type == 'select') + { + $query .= "SELECT "; + if ($this->_fields == null) + { + $query .= "* "; + } + else + { + $first = true; + foreach ($this->_fields as $f) + { + if (!$first) + { + $query .= ", "; + } + else + { + $first = false; + } + if (is_array($f)) + { + $query .= "{$this->escape_field($f[0])} AS {$f[1]} "; + } + else + { + $query .= "{$this->escape_field($f)} "; + } + } + } + $query .= "FROM {$this->quote($this->_table)} "; + } + if ($this->_type == 'count') + { + $query .= "SELECT COUNT(*) as {$this->quote('count')} FROM {$this->quote($this->_table)} "; + } + if ($this->_type == 'delete') + { + if ($this->_db_type != 'sqlite') + { + $query .= "DELETE {$this->last_alias()}.* FROM {$this->quote($this->_table)} "; + } + else + { + if (!empty($this->_joins)) + { + throw new Exception("SQLite doesn't support deleting a table with JOIN in the query"); + } + $query .= "DELETE FROM {$this->quote($this->_table)} "; + } + } + if ($this->_type == 'update') + { + $query .= "UPDATE {$this->quote($this->_table)} SET "; + $first = true; + foreach ($this->_data as $key => $val) + { + if (!$first) + { + $query .= ", "; + } + else + { + $first = false; + } + $query .= "{$this->quote($key)} = {$this->escape_value($val, $params)}"; + } + $query .= " "; + } + + foreach ($this->_joins as $join) + { + $table = $join[0]; + if (is_array($table)) + { + $table = "{$this->quote($table[0])} as {$this->quote($table[1])}"; + } + else + { + $table = "{$this->quote($table)}"; + } + $query .= strtoupper($join[1])." JOIN {$table} ON {$this->get_condition_query($join[2], $params, true, true)} "; + } - if (!empty($this->_conditions)) { - $query.="WHERE {$this->get_condition_query($this->_conditions,$params,true)} "; - } - if (($this->_type == 'select' || $this->_type == 'count') && $this->_group_by!=null) { - $query.="GROUP BY {$this->escape_field($this->_group_by)} "; - } - if (($this->_type == 'select' || $this->_type == 'count') && !empty($this->_having)) { - $query.="HAVING {$this->get_condition_query($this->_having,$params,true)} "; - } - - if ($this->_type == 'select' && !empty($this->_orderby)) { - $query.="ORDER BY "; - $first = true; - foreach($this->_orderby as $order) { - if (!$first) { - $query.=','; - }else { - $first=false; - } - $query.= $this->escape_field($order[0])." "; - if (isset($order[1])) { - $dir = strtoupper($order[1]); - $query.=$dir." "; - } - } - } - if($this->_type != 'count'){ - if ($this->_limit != null) - $query.= "LIMIT {$this->_limit} "; - if ($this->_offset != null) - $query.= "OFFSET {$this->_offset} "; - } - - } - - return array($query,$params); - } + if (!empty($this->_conditions)) + { + $query .= "WHERE {$this->get_condition_query($this->_conditions, $params, true)} "; + } + if (($this->_type == 'select' || $this->_type == 'count') && $this->_group_by != null) + { + $query .= "GROUP BY {$this->escape_field($this->_group_by)} "; + } + if (($this->_type == 'select' || $this->_type == 'count') && !empty($this->_having)) + { + $query .= "HAVING {$this->get_condition_query($this->_having, $params, true)} "; + } + + if ($this->_type == 'select' && !empty($this->_orderby)) + { + $query .= "ORDER BY "; + $first = true; + foreach ($this->_orderby as $order) + { + if (!$first) + { + $query .= ','; + } + else + { + $first = false; + } + $query .= $this->escape_field($order[0])." "; + if (isset($order[1])) + { + $dir = strtoupper($order[1]); + $query .= $dir." "; + } + } + } + if ($this->_type != 'count') + { + if ($this->_limit != null) + $query .= "LIMIT {$this->_limit} "; + if ($this->_offset != null) + $query .= "OFFSET {$this->_offset} "; + } + } + + return array($query, $params); + } /** * Recursively parses conditions array into a query string @@ -216,41 +276,47 @@ class Query_PDO_Driver extends Query_Database { * @param array $p Element of the cobditions array * @param array &$params Reference to parameters array * @param boolean $skip_first_operator Flag to skip the first logical operator in a query - * to prevent AND or OR to be at the beginning of the query + * to prevent AND or OR to be at the beginning of the query * @param boolean $value_is_field Flag if the the value in the logical operations should - * be treated as a field. E.g. for joins where the fields are - * compared between themselves and not with actual values + * be treated as a field. E.g. for joins where the fields are + * compared between themselves and not with actual values * @return string String representation of the conditions * @access public * @throws Exception If condition cannot be parsed */ - public function get_condition_query($p,&$params,$skip_first_operator,$value_is_field=false) { - if (isset($p['field'])) { - if ($value_is_field){ - $param = $this->escape_field($p['value']); - }else { - $param = $this->escape_value($p['value'],$params); - } - return $this->escape_field($p['field']).' '.$p['operator'].' '.$param; - } - if (isset($p['logic'])) { - return ($skip_first_operator?'':strtoupper($p['logic']).' ') - .$this->get_condition_query($p['conditions'],$params,false,$value_is_field); - } - - $conds = ''; - $skip=$skip_first_operator||(count($p) > 1); - foreach($p as $q) { - $conds.=$this->get_condition_query($q,$params,$skip,$value_is_field).' '; - $skip=false; - } - if (count($p) > 1 && !$skip_first_operator) - return "( ".$conds.")"; - return $conds; - - throw new Exception("Cannot parse condition:\n".var_export($p,true)); - } + public function get_condition_query($p, &$params, $skip_first_operator, $value_is_field = false) + { + if (isset($p['field'])) + { + if ($value_is_field) + { + $param = $this->escape_field($p['value']); + } + else + { + $param = $this->escape_value($p['value'], $params); + } + return $this->escape_field($p['field']).' '.$p['operator'].' '.$param; + } + if (isset($p['logic'])) + { + return ($skip_first_operator ? '' : strtoupper($p['logic']).' ').$this->get_condition_query($p['conditions'], $params, false, $value_is_field); + } + $conds = ''; + $skip = $skip_first_operator || (count($p) > 1); + foreach ($p as $q) + { + $conds .= $this->get_condition_query($q, $params, $skip, $value_is_field).' '; + $skip = false; + } + if (count($p) > 1 && !$skip_first_operator) + { + return "( ".$conds.")"; + } + return $conds; + throw new Exception("Cannot parse condition:\n".var_export($p, true)); + } }
\ No newline at end of file diff --git a/modules/database/classes/driver/pdo/result.php b/modules/database/classes/driver/pdo/result.php index 3c96b4c..d64c479 100644 --- a/modules/database/classes/driver/pdo/result.php +++ b/modules/database/classes/driver/pdo/result.php @@ -4,7 +4,8 @@ * Database result implementation for PDO * @package Database */ -class Result_PDO_Driver extends Result_Database { +class Result_PDO_Driver extends Result_Database +{ /** * Initializes new result object @@ -12,11 +13,12 @@ class Result_PDO_Driver extends Result_Database { * @param PDOStatement $stmt PDO Statement * @return void * @access public - * @link http://php.net/manual/en/class.pdostatement.php + * @link http://php.net/manual/en/class.pdostatement.php */ - public function __construct($stmt) { - $this->_result = $stmt; - } + public function __construct($stmt) + { + $this->_result = $stmt; + } /** * Throws exception if rewind is attempted. @@ -25,25 +27,32 @@ class Result_PDO_Driver extends Result_Database { * @access public * @throws Exception If rewind is attempted */ - public function rewind() { - if($this->_position>0) - throw new Exception('PDO statement cannot be rewound for unbuffered queries'); + public function rewind() + { + if ($this->_position > 0) + { + throw new Exception('PDO statement cannot be rewound for unbuffered queries'); + } } - + /** * Iterates to the next row in the result set * * @return void * @access public */ - public function next() { - $this->check_fetched(); - $this->_row = $this->_result->fetchObject(); - if ($this->_row) { - $this->_position++; - }else { - $this->_result->closeCursor(); - } + public function next() + { + $this->check_fetched(); + $this->_row = $this->_result->fetchObject(); + if ($this->_row) + { + $this->_position++; + } + else + { + $this->_result->closeCursor(); + } } - + }
\ No newline at end of file diff --git a/modules/orm/classes/orm.php b/modules/orm/classes/orm.php index 4083cbc..96bfd1e 100644 --- a/modules/orm/classes/orm.php +++ b/modules/orm/classes/orm.php @@ -19,256 +19,290 @@ * @see Query_Database::where() * @package ORM */ -class ORM { +class ORM +{ /** * Specifies which table the model will use, can be overridden * @var string * @access public */ - public $table = null; + public $table = null; /** * Specifies which connection the model will use, can be overridden - * but a model can have relationships only with models utilizing the same connection + * but a model can have relationships only with models utilizing the same connection * @var string * @access public */ - public $connection = 'default'; + public $connection = 'default'; /** * Specifies which column is treated as PRIMARY KEY * @var string * @access public */ - public $id_field='id'; + public $id_field = 'id'; /** * You can define 'Belongs to' relationships buy changing this array * @var array * @access protected */ - protected $belongs_to=array(); + protected $belongs_to = array(); /** * You can define 'Has one' relationships buy changing this array * @var array * @access protected */ - protected $has_one = array(); + protected $has_one = array(); /** * You can define 'Has many' relationships buy changing this array * @var array * @access protected */ - protected $has_many = array(); + protected $has_many = array(); - /** + /** * Associated query builder * @var Query_Database * @access public */ - public $query; + public $query; /** * The name of the model * @var string * @access public */ - public $model_name; + public $model_name; /** * Cached properties * @var array * @access public */ - public $cached = array(); - + public $cached = array(); + /** * An instance of the database connection * @var DB * @access protected */ - protected $db; + protected $db; /** * Current row returned by the database * @var array * @access protected */ - protected $_row = array(); - + protected $_row = array(); + /** * A flag whether the row was loaded from the database * @var boolean * @access protected */ - protected $_loaded = false; + protected $_loaded = false; - - /** + /** * Relationships to be preloaded * @var array * @access protected */ - protected $_with = array(); - - /** + protected $_with = array(); + + /** * Cached column names for tables * @var array * @access protected */ - protected static $_column_cache = array(); - - + protected static $_column_cache = array(); + /** * Constructs the model. To use ORM it is enough to - * just create a model like this: - * <code> - * class Fairy_Model extends ORM { } - * </code> + * just create a model like this: + * <code> + * class Fairy_Model extends ORM { } + * </code> * By default it will assume that the name of your table - * is the plural form of the models' name, the PRIMARY KEY is id, - * and will use the 'default' connection. This behaviour is easy to be - * changed by overriding $table, $id and $db properties. - * + * is the plural form of the models' name, the PRIMARY KEY is id, + * and will use the 'default' connection. This behaviour is easy to be + * changed by overriding $table, $id and $db properties. + * * @return void * @access public - * @ see $table - * @ see $id - * @ see $db - */ - public function __construct() { - $this->query = DB::instance($this->connection)->build_query('select'); - $this->model_name = strtolower(get_class($this)); - if (substr($this->model_name, -6) == '_model') - $this->model_name=substr($this->model_name,0,-6); - if ($this->table == null) - $this->table = ORM::plural($this->model_name); - $this->query->table($this->table); - - foreach(array('belongs_to', 'has_one', 'has_many') as $rels) { - $normalized=array(); - foreach($this->$rels as $key => $rel) { - if (!is_array($rel)) { - $key = $rel; - $rel=array(); - } - $normalized[$key]=$rel; - if (!isset($rel['model'])) { - $rel['model']=$normalized[$key]['model']=$rels=='has_many'?ORM::singular($key):$key; - } - - $normalized[$key]['type']=$rels; - if (!isset($rel['key'])) - $normalized[$key]['key'] = $rels != 'belongs_to'?($this->model_name.'_id'):$rel['model'].'_id'; - - if ($rels == 'has_many' && isset($rel['through'])) - if (!isset($rel['foreign_key'])) - $normalized[$key]['foreign_key'] = $rel['model'].'_id'; - - $normalized[$key]['name']=$key; - } - $this->$rels=$normalized; - - } - - } - + * @ see $table + * @ see $id + * @ see $db + */ + public function __construct() + { + $this->query = DB::instance($this->connection)->build_query('select'); + $this->model_name = strtolower(get_class($this)); + if (substr($this->model_name, -6) == '_model') + { + $this->model_name = substr($this->model_name, 0, -6); + } + if ($this->table == null) + { + $this->table = ORM::plural($this->model_name); + } + $this->query->table($this->table); + + foreach (array('belongs_to', 'has_one', 'has_many') as $rels) + { + $normalized = array(); + foreach ($this->$rels as $key => $rel) + { + if (!is_array($rel)) + { + $key = $rel; + $rel = array(); + } + $normalized[$key] = $rel; + if (!isset($rel['model'])) + { + $rel['model'] = $normalized[$key]['model'] = $rels == 'has_many' ? ORM::singular($key) : $key; + } + + $normalized[$key]['type'] = $rels; + if (!isset($rel['key'])) + { + $normalized[$key]['key'] = $rels != 'belongs_to' ? ($this->model_name.'_id') : $rel['model'].'_id'; + } + + if ($rels == 'has_many' && isset($rel['through'])) + { + if (!isset($rel['foreign_key'])) + { + $normalized[$key]['foreign_key'] = $rel['model'].'_id'; + } + } + + $normalized[$key]['name'] = $key; + } + $this->$rels = $normalized; + } + } + /** * Magic method for call Query_Database methods * * @param string $method Method to call * @param array $arguments Arguments passed to the method * @return mixed Returns self if parameters were passed. If no parameters where passed returns - * current value for the associated parameter - * @throws Exception If method doesn't exist + * current value for the associated parameter + * @throws Exception If method doesn't exist * @access public */ - public function __call($method, $arguments) { - if (!in_array($method, array('limit', 'offset', 'order_by', 'where'))) - throw new Exception("Method '{$method}' doesn't exist on .".get_class($this)); - $res = call_user_func_array(array($this->query, $method), $arguments); - if(is_subclass_of($res,'Query_Database')) - return $this; - return $res; - } + public function __call($method, $arguments) + { + if (!in_array($method, array('limit', 'offset', 'order_by', 'where'))) + { + throw new Exception("Method '{$method}' doesn't exist on .".get_class($this)); + } + $res = call_user_func_array(array($this->query, $method), $arguments); + if (is_subclass_of($res, 'Query_Database')) + { + return $this; + } + return $res; + } /** * Finds all rows that meet set criteria. * * @return Result_ORM Returns Result_ORM that you can use in a 'foreach' loop. - * @throw Exception If the relationship specified using with() does not exist or is not of the belongs_to or has_one type + * @throw Exception If the relationship specified using with() does not exist or is not of the belongs_to or has_one type * @access public */ - public function find_all() { - $paths = array(); - if(!empty($this->_with)){ - $fields = array(); - $this_alias=$this->query->last_alias(); - foreach($this->columns() as $column) - $fields[]=array("{$this_alias}.{$column}","{$this_alias}__{$column}"); - foreach($this->_with as $target) { - $model = $this; - $model_alias=$this_alias; - $rels = explode('.', $target); - foreach($rels as $key => $rel_name) { - $path = implode('.', array_slice($rels, 0, $key + 1)); - if (isset($paths[$path])) { - $model = $paths[$path]['model']; - $model_alias=$paths[$path]['alias']; - continue; - } - $alias=$this->query->add_alias(); - $model_rels = array_merge($model->has_one, $model->has_many,$model->belongs_to); - $rel = Misc::arr($model_rels, $rel_name, false); - - if (!$rel) - throw new Exception("Model '{$model->model_name}' doesn't have a '{$rel_name}' relation defined"); - if ($rel['type'] == 'has_many') - throw new Exception("Relationship '{$rel_name}' is of has_many type and cannot be preloaded view with()"); - $rel_model = ORM::factory($rel['model']); - - if ($rel['type'] == 'belongs_to') { - $this->query->join(array($rel_model->table, $alias), array( - $model_alias.'.'.$rel['key'], - $alias.'.'.$rel_model->id_field, - ),'left'); - }else { - $this->query->join(array($rel_model->table, $alias), array( - $model_alias.'.'.$model->id_field, - $alias.'.'.$rel['key'], - ), 'left'); - } - - foreach($rel_model->columns() as $column) - $fields[]=array("{$alias}.{$column}","{$alias}__{$column}"); - $model = $rel_model; - $model_alias = $alias; - $paths[$path] = array('alias' => $alias, 'model' => $model); - } - } - - call_user_func_array(array($this->query, 'fields'), $fields); - } - - return new Result_ORM(get_class($this), $res=$this->query->execute(),$paths); - } + public function find_all() + { + $paths = array(); + if (!empty($this->_with)) + { + $fields = array(); + $this_alias = $this->query->last_alias(); + foreach ($this->columns() as $column) + { + $fields[] = array("{$this_alias}.{$column}", "{$this_alias}__{$column}"); + } + foreach ($this->_with as $target) + { + $model = $this; + $model_alias = $this_alias; + $rels = explode('.', $target); + foreach ($rels as $key => $rel_name) + { + $path = implode('.', array_slice($rels, 0, $key + 1)); + if (isset($paths[$path])) + { + $model = $paths[$path]['model']; + $model_alias = $paths[$path]['alias']; + continue; + } + $alias = $this->query->add_alias(); + $model_rels = array_merge($model->has_one, $model->has_many, $model->belongs_to); + $rel = Misc::arr($model_rels, $rel_name, false); + + if (!$rel) + { + throw new Exception("Model '{$model->model_name}' doesn't have a '{$rel_name}' relation defined"); + } + if ($rel['type'] == 'has_many') + { + throw new Exception("Relationship '{$rel_name}' is of has_many type and cannot be preloaded view with()"); + } + $rel_model = ORM::factory($rel['model']); + + if ($rel['type'] == 'belongs_to') + { + $this->query->join(array($rel_model->table, $alias), array( + $model_alias.'.'.$rel['key'], + $alias.'.'.$rel_model->id_field, + ), 'left'); + } + else + { + $this->query->join(array($rel_model->table, $alias), array( + $model_alias.'.'.$model->id_field, + $alias.'.'.$rel['key'], + ), 'left'); + } + + foreach ($rel_model->columns() as $column) + { + $fields[] = array("{$alias}.{$column}", "{$alias}__{$column}"); + } + $model = $rel_model; + $model_alias = $alias; + $paths[$path] = array('alias' => $alias, 'model' => $model); + } + } + + call_user_func_array(array($this->query, 'fields'), $fields); + } + + return new Result_ORM(get_class($this), $res = $this->query->execute(), $paths); + } /** * Searches for the first row that meets set criteria. If no rows match it still returns an ORM object - * but with its loaded() flag being False. calling save() on such an object will insert a new row. + * but with its loaded() flag being False. calling save() on such an object will insert a new row. * * @return ORM Found item or new object of the current model but with loaded() flag being False * @access public */ - public function find() { - $set_limit=$this->limit(); - $res = $this->limit(1)->find_all()->current(); - $this->limit($set_limit); - return $res; - } + public function find() + { + $set_limit = $this->limit(); + $res = $this->limit(1)->find_all()->current(); + $this->limit($set_limit); + return $res; + } /** * Counts all rows that meet set criteria. Ignores limit and offset. @@ -276,12 +310,12 @@ class ORM { * @return int Number of rows * @access public */ - public function count_all() { - $query = clone $this->query; - $query->type('count'); - return $query->execute(); - - } + public function count_all() + { + $query = clone $this->query; + $query->type('count'); + return $query->execute(); + } /** * Checks if the item is considered to be loaded from the database @@ -289,9 +323,10 @@ class ORM { * @return boolean Returns True if the item was loaded * @access public */ - public function loaded() { - return $this->_loaded; - } + public function loaded() + { + return $this->_loaded; + } /** * Returns the row associated with current ORM item as an associative array @@ -299,120 +334,143 @@ class ORM { * @return array Associative array representing the row * @access public */ - public function as_array() { - return $this->_row; - } + public function as_array() + { + return $this->_row; + } /** * Returns a clone of query builder that is being used to set conditions. - * It is useful for example if you let ORM manage building a complex query using it's relationship - * system, then you get the clone of that query and alter it to your liking, - * so there is no need to writing relationship joins yourself. + * It is useful for example if you let ORM manage building a complex query using it's relationship + * system, then you get the clone of that query and alter it to your liking, + * so there is no need to writing relationship joins yourself. * * @return Query_Database A clone of the current query builder * @access public */ - public function query() { - return clone $this->query; - } + public function query() + { + return clone $this->query; + } /** * You can override this method to return additional properties that you would like to use - * in your model. One advantage for using this instead of just overriding __get() is that - * in this way the properties also get cached. + * in your model. One advantage for using this instead of just overriding __get() is that + * in this way the properties also get cached. * * @param string $property The name of the property to get * @return void * @access public */ - public function get($property) { - - } + public function get($property) + { + + } /** * Magic method that allows accessing row columns as properties and also facilitates - * access to relationships and custom properties defined in get() method. + * access to relationships and custom properties defined in get() method. * If a relationship is being accessed, it will return an ORM model of the related table - * and automatically alter its query so that all your previously set conditions will remain - + * and automatically alter its query so that all your previously set conditions will remain + * @param string $column Name of the column, property or relationship to get * @return mixed * @access public * @throws Exception If neither property nor a relationship with such name is found */ - public function __get($column) { - if (array_key_exists($column,$this->_row)) - return $this->_row[$column]; - if (array_key_exists($column,$this->cached)) - return $this->cached[$column]; - if (($val = $this->get($column))!==null) { - $this->cached[$column] = $val; - return $val; - } - $relations = array_merge($this->has_one, $this->has_many, $this->belongs_to); - if ($target = Misc::arr($relations, $column, false)) { - $model = ORM::factory($target['model']); - $model->query = clone $this->query; - if ($this->loaded()) - $model->query->where($this->id_field,$this->_row[$this->id_field]); - if ($target['type']=='has_many'&&isset($target['through'])) { - $last_alias = $model->query->last_alias(); - $through_alias=$model->query->add_alias(); - $new_alias = $model->query->add_alias(); - $model->query->join(array($target['through'], $through_alias), array( - $last_alias.'.'.$this->id_field, - $through_alias.'.'.$target['key'], - ),'inner'); - $model->query->join(array($model->table, $new_alias), array( - $through_alias.'.'.$target['foreign_key'], - $new_alias.'.'.$model->id_field, - ),'inner'); - }else{ - $last_alias = $model->query->last_alias(); - $new_alias = $model->query->add_alias(); - if ($target['type'] == 'belongs_to') { - $model->query->join(array($model->table, $new_alias), array( - $last_alias.'.'.$target['key'], - $new_alias.'.'.$model->id_field, - ),'inner'); - }else { - $model->query->join(array($model->table, $new_alias), array( - $last_alias.'.'.$this->id_field, - $new_alias.'.'.$target['key'], - ), 'inner'); - } - } - $model->query->fields("$new_alias.*"); - if ($target['type'] != 'has_many' && $this->loaded() ) { - $model = $model->find(); - $this->cached[$column]=$model; - } - return $model; - } - - throw new Exception("Property {$column} not found on {$this->model_name} model."); - } + public function __get($column) + { + if (array_key_exists($column, $this->_row)) + { + return $this->_row[$column]; + } + if (array_key_exists($column, $this->cached)) + { + return $this->cached[$column]; + } + if (($val = $this->get($column)) !== null) + { + $this->cached[$column] = $val; + return $val; + } + $relations = array_merge($this->has_one, $this->has_many, $this->belongs_to); + if ($target = Misc::arr($relations, $column, false)) + { + $model = ORM::factory($target['model']); + $model->query = clone $this->query; + if ($this->loaded()) + { + $model->query->where($this->id_field, $this->_row[$this->id_field]); + } + if ($target['type'] == 'has_many' && isset($target['through'])) + { + $last_alias = $model->query->last_alias(); + $through_alias = $model->query->add_alias(); + $new_alias = $model->query->add_alias(); + $model->query->join(array($target['through'], $through_alias), array( + $last_alias.'.'.$this->id_field, + $through_alias.'.'.$target['key'], + ), 'inner'); + $model->query->join(array($model->table, $new_alias), array( + $through_alias.'.'.$target['foreign_key'], + $new_alias.'.'.$model->id_field, + ), 'inner'); + } + else + { + $last_alias = $model->query->last_alias(); + $new_alias = $model->query->add_alias(); + if ($target['type'] == 'belongs_to') + { + $model->query->join(array($model->table, $new_alias), array( + $last_alias.'.'.$target['key'], + $new_alias.'.'.$model->id_field, + ), 'inner'); + } + else + { + $model->query->join(array($model->table, $new_alias), array( + $last_alias.'.'.$this->id_field, + $new_alias.'.'.$target['key'], + ), 'inner'); + } + } + $model->query->fields("$new_alias.*"); + if ($target['type'] != 'has_many' && $this->loaded()) + { + $model = $model->find(); + $this->cached[$column] = $model; + } + return $model; + } + + throw new Exception("Property {$column} not found on {$this->model_name} model."); + } /** * Magic method to update record values when set as properties or to add an ORM item to - * a relation. By assigning an ORM object to a relationship a relationship is created between the - * current item and the passed one Using properties this way is a shortcut to the add() method. + * a relation. By assigning an ORM object to a relationship a relationship is created between the + * current item and the passed one Using properties this way is a shortcut to the add() method. * * @param string $column Column or relationship name * @param mixed $val Column value or an ORM item to be added to a relation * @return void * @access public - * @see add() - */ - public function __set($column, $val) { - $relations = array_merge($this->has_one, $this->has_many, $this->belongs_to); - if (array_key_exists($column,$relations)){ - $this->add($column, $val); - }else{ - $this->_row[$column] = $val; - } - $this->cached=array(); - } + * @see add() + */ + public function __set($column, $val) + { + $relations = array_merge($this->has_one, $this->has_many, $this->belongs_to); + if (array_key_exists($column, $relations)) + { + $this->add($column, $val); + } + else + { + $this->_row[$column] = $val; + } + $this->cached = array(); + } /** * Create a relationship between current item and an other one @@ -425,56 +483,78 @@ class ORM { * @throws Exception Exception If current item is not in the database yet (isn't considered loaded()) * @throws Exception Exception If passed item is not in the database yet (isn't considered loaded()) */ - public function add($relation, $model) { - - $rels = array_merge($this->has_one, $this->has_many,$this->belongs_to); - $rel = Misc::arr($rels, $relation, false); - if (!$rel) - throw new Exception("Model doesn't have a '{$relation}' relation defined"); - - if ($rel['type'] == 'belongs_to') { - - if (!$model->loaded()) - throw new Exception("Model must be loaded before added to a belongs_to relationship. Probably you haven't saved it."); - - $key=$rel['key']; - $this->$key = $model->_row[$this->id_field]; - if ($this->loaded()) - $this->save(); - }elseif (isset($rel['through'])) { - - if (!$this->loaded()) - throw new Exception("Model must be loaded before you try adding 'through' relationships to it. Probably you haven't saved it."); - if (!$model->loaded()) - throw new Exception("Model must be loaded before added to a 'through' relationship. Probably you haven't saved it."); - - $exists = DB::instance($this->connection)->build_query('count') - ->table($rel['through']) - ->where(array( - array($rel['key'],$this->_row[$this->id_field]), - array($rel['foreign_key'],$model->_row[$model->id_field]) - )) - ->execute(); - if(!$exists) - DB::instance($this->connection)->build_query('insert') - ->table($rel['through']) - ->data(array( - $rel['key'] => $this->_row[$this->id_field], - $rel['foreign_key'] =>$model->_row[$model->id_field] - )) - ->execute(); - }else { - - if (!$this->loaded()) - throw new Exception("Model must be loaded before you try adding 'has_many' relationships to it. Probably you haven't saved it."); - - $key=$rel['key']; - $model->$key = $this->_row[$this->id_field]; - if($model->loaded()) - $model->save(); - } - $this->cached=array(); - } + public function add($relation, $model) + { + + $rels = array_merge($this->has_one, $this->has_many, $this->belongs_to); + $rel = Misc::arr($rels, $relation, false); + if (!$rel) + { + throw new Exception("Model doesn't have a '{$relation}' relation defined"); + } + + if ($rel['type'] == 'belongs_to') + { + + if (!$model->loaded()) + { + throw new Exception("Model must be loaded before added to a belongs_to relationship. Probably you haven't saved it."); + } + + $key = $rel['key']; + $this->$key = $model->_row[$this->id_field]; + if ($this->loaded()) + { + $this->save(); + } + } + elseif (isset($rel['through'])) + { + + if (!$this->loaded()) + { + throw new Exception("Model must be loaded before you try adding 'through' relationships to it. Probably you haven't saved it."); + } + if (!$model->loaded()) + { + throw new Exception("Model must be loaded before added to a 'through' relationship. Probably you haven't saved it."); + } + + $exists = DB::instance($this->connection)->build_query('count') + ->table($rel['through']) + ->where(array( + array($rel['key'], $this->_row[$this->id_field]), + array($rel['foreign_key'], $model->_row[$model->id_field]) + )) + ->execute(); + if (!$exists) + { + DB::instance($this->connection)->build_query('insert') + ->table($rel['through']) + ->data(array( + $rel['key'] => $this->_row[$this->id_field], + $rel['foreign_key'] => $model->_row[$model->id_field] + )) + ->execute(); + } + } + else + { + + if (!$this->loaded()) + { + throw new Exception("Model must be loaded before you try adding 'has_many' relationships to it. Probably you haven't saved it."); + } + + $key = $rel['key']; + $model->$key = $this->_row[$this->id_field]; + if ($model->loaded()) + { + $model->save(); + } + } + $this->cached = array(); + } /** * Removes a relationship between current item and the passed one @@ -487,64 +567,81 @@ class ORM { * @throws Exception Exception If current item is not in the database yet (isn't considered loaded()) * @throws Exception Exception If passed item is not in the database yet (isn't considered loaded()) */ - public function remove($relation, $model=null) { - - if (!$this->loaded()) - throw new Exception("Model must be loaded before you try removing relationships from it."); - - $rels = array_merge($this->has_one, $this->has_many,$this->belongs_to); - $rel = Misc::arr($rels, $relation, false); - if (!$rel) - throw new Exception("Model doesn't have a '{$relation}' relation defined"); - - if ($rel['type']!='belongs_to'&&(!$model||!$model->loaded())) - throw new Exception("Model must be loaded before being removed from a has_one or has_many relationship."); - if ($rel['type']=='belongs_to') { - $key=$rel['key']; - $this->$key = null; - $this->save(); - }elseif (isset($rel['through'])) { - DB::instance($this->connection)->build_query('delete') - ->table($rel['through']) - ->where(array( - array($rel['key'],$this->_row[$this->id_field]), - array($rel['foreign_key'],$model->_row[$model->id_field]) - )) - ->execute(); - }else { - $key=$rel['key']; - $model->$key = null; - $model->save(); - } - $this->cached=array(); - } - - /** + public function remove($relation, $model = null) + { + + if (!$this->loaded()) + { + throw new Exception("Model must be loaded before you try removing relationships from it."); + } + + $rels = array_merge($this->has_one, $this->has_many, $this->belongs_to); + $rel = Misc::arr($rels, $relation, false); + if (!$rel) + { + throw new Exception("Model doesn't have a '{$relation}' relation defined"); + } + + if ($rel['type'] != 'belongs_to' && (!$model || !$model->loaded())) + { + throw new Exception("Model must be loaded before being removed from a has_one or has_many relationship."); + } + if ($rel['type'] == 'belongs_to') + { + $key = $rel['key']; + $this->$key = null; + $this->save(); + } + elseif (isset($rel['through'])) + { + DB::instance($this->connection)->build_query('delete') + ->table($rel['through']) + ->where(array( + array($rel['key'], $this->_row[$this->id_field]), + array($rel['foreign_key'], $model->_row[$model->id_field]) + )) + ->execute(); + } + else + { + $key = $rel['key']; + $model->$key = null; + $model->save(); + } + $this->cached = array(); + } + + /** * Gets name column names of the table associated with the model. * * @return array Array of column names * @access public */ - public function columns() { - if (!isset(ORM::$_column_cache[$this->table])) - ORM::$_column_cache[$this->table] = DB::instance($this->connection)->list_columns($this->table); - return ORM::$_column_cache[$this->table]; - } - - /** + public function columns() + { + if (!isset(ORM::$_column_cache[$this->table])) + { + ORM::$_column_cache[$this->table] = DB::instance($this->connection)->list_columns($this->table); + } + return ORM::$_column_cache[$this->table]; + } + + /** * Defines which relationships should be preloaded. You can only preload - * belongs_to and has_one relationships. You can use the dot notation to - * preload deep relationsips, e.g. 'tree.protector' will preload the tree - * that a fairy lives in and also preload the protector of that tree. + * belongs_to and has_one relationships. You can use the dot notation to + * preload deep relationsips, e.g. 'tree.protector' will preload the tree + * that a fairy lives in and also preload the protector of that tree. * - * @param string $relationsip,... List of relationships to preload + * @param string $relationsip,... List of relationships to preload * @return ORM Returns itself * @access public */ - public function with() { - $this->_with = func_get_args(); - return $this; - } + public function with() + { + $this->_with = func_get_args(); + return $this; + } + /** * Deletes current item from the database * @@ -552,78 +649,91 @@ class ORM { * @access public * @throws Exception If the item is not in the database, e.g. is not loaded() */ - public function delete() { - if (!$this->loaded()) - throw new Exception("Cannot delete an item that wasn't selected from database"); - DB::instance($this->connection)->build_query('delete') - ->table($this->table) - ->where($this->id_field, $this->_row[$this->id_field]) - ->execute(); - $this->cached=array(); - } + public function delete() + { + if (!$this->loaded()) + { + throw new Exception("Cannot delete an item that wasn't selected from database"); + } + DB::instance($this->connection)->build_query('delete') + ->table($this->table) + ->where($this->id_field, $this->_row[$this->id_field]) + ->execute(); + $this->cached = array(); + } /** * Deletes all items that meet set conditions. Use in the same way - * as you would a find_all() method. + * as you would a find_all() method. * * @return ORM Returns self * @access public */ - public function delete_all() { - $query = clone $this->query; - $query->type('delete'); - $query->execute(); - return $this; - } + public function delete_all() + { + $query = clone $this->query; + $query->type('delete'); + $query->execute(); + return $this; + } /** * Saves the item back to the database. If item is loaded() it will result - * in an update, otherwise a new row will be inserted + * in an update, otherwise a new row will be inserted * * @return ORM Returns self * @access public */ - public function save() { - if ($this->loaded()) { - $query = DB::instance($this->connection)->build_query('update') - ->table($this->table) - ->where($this->id_field,$this->_row[$this->id_field]); - }else { - $query = DB::instance($this->connection)->build_query('insert') - ->table($this->table); - } - $query->data($this->_row); - $query->execute(); - - if ($this->loaded()) { - $id=$this->_row[$this->id_field]; - }else { - $id=DB::instance($this->connection)->get_insert_id(); - } - $row =(array) DB::instance($this->connection)->build_query('select') - ->table($this->table) - ->where($this->id_field, $id)->execute()->current(); - $this->values($row,true); - return $this; - } - - + public function save() + { + if ($this->loaded()) + { + $query = DB::instance($this->connection)->build_query('update') + ->table($this->table) + ->where($this->id_field, $this->_row[$this->id_field]); + } + else + { + $query = DB::instance($this->connection)->build_query('insert') + ->table($this->table); + } + $query->data($this->_row); + $query->execute(); + + if ($this->loaded()) + { + $id = $this->_row[$this->id_field]; + } + else + { + $id = DB::instance($this->connection)->get_insert_id(); + } + $row = (array) DB::instance($this->connection)->build_query('select') + ->table($this->table) + ->where($this->id_field, $id)->execute()->current(); + $this->values($row, true); + return $this; + } + /** * Batch updates item columns using an associative array * * @param array $row Associative array of key => value pairs * @param boolean $set_loaded Flag to consider the ORM item loaded. Useful if you selected - * the row from the database and want to wrap it in ORM + * the row from the database and want to wrap it in ORM * @return ORM Returns self * @access public */ - public function values($row, $set_loaded = false) { - $this->_row = array_merge($this->_row, $row); - if ($set_loaded) - $this->_loaded = true; - $this->cached=array(); - return $this; - } + public function values($row, $set_loaded = false) + { + $this->_row = array_merge($this->_row, $row); + if ($set_loaded) + { + $this->_loaded = true; + } + $this->cached = array(); + return $this; + } /** * Initializes ORM model by name, and optionally fetches an item by id @@ -634,15 +744,17 @@ class ORM { * @access public * @static */ - public static function factory($name,$id=null){ - $model = $name.'_Model'; - $model=new $model; - if ($id != null){ - $model=$model->where($model->id_field, $id)->find(); - $model->values(array($model->id_field => $id)); - } - return $model; - } + public static function factory($name, $id = null) + { + $model = $name.'_Model'; + $model = new $model; + if ($id != null) + { + $model = $model->where($model->id_field, $id)->find(); + $model->values(array($model->id_field => $id)); + } + return $model; + } /** * Gets plural form of a noun @@ -652,19 +764,23 @@ class ORM { * @access private * @static */ - private static function plural($str){ - $regexes=array( - '/^(.*?[sxz])$/i' => '\\1es', - '/^(.*?[^aeioudgkprt]h)$/i' => '\\1es', - '/^(.*?[^aeiou])y$/i'=>'\\1ies', - ); - foreach($regexes as $key=>$val){ - $str = preg_replace($key, $val, $str,-1, $count); - if ($count) - return $str; - } - return $str.'s'; - } + private static function plural($str) + { + $regexes = array( + '/^(.*?[sxz])$/i' => '\\1es', + '/^(.*?[^aeioudgkprt]h)$/i' => '\\1es', + '/^(.*?[^aeiou])y$/i' => '\\1ies', + ); + foreach ($regexes as $key => $val) + { + $str = preg_replace($key, $val, $str, -1, $count); + if ($count) + { + return $str; + } + } + return $str.'s'; + } /** * Gets singular form of a noun @@ -674,19 +790,23 @@ class ORM { * @access private * @static */ - private static function singular($str){ - $regexes=array( - '/^(.*?us)$/i' => '\\1', - '/^(.*?[sxz])es$/i' => '\\1', - '/^(.*?[^aeioudgkprt]h)es$/i' => '\\1', - '/^(.*?[^aeiou])ies$/i' => '\\1y', - '/^(.*?)s$/'=>'\\1' - ); - foreach($regexes as $key=>$val){ - $str = preg_replace($key, $val, $str,-1, $count); - if ($count) - return $str; - } - return $str; - } + private static function singular($str) + { + $regexes = array( + '/^(.*?us)$/i' => '\\1', + '/^(.*?[sxz])es$/i' => '\\1', + '/^(.*?[^aeioudgkprt]h)es$/i' => '\\1', + '/^(.*?[^aeiou])ies$/i' => '\\1y', + '/^(.*?)s$/' => '\\1', + ); + foreach ($regexes as $key => $val) + { + $str = preg_replace($key, $val, $str, -1, $count); + if ($count) + { + return $str; + } + } + return $str; + } }
\ No newline at end of file diff --git a/modules/orm/classes/orm/result.php b/modules/orm/classes/orm/result.php index 71f8159..47757cf 100644 --- a/modules/orm/classes/orm/result.php +++ b/modules/orm/classes/orm/result.php @@ -9,50 +9,54 @@ * @see Database_Result * @package ORM */ -class Result_ORM implements Iterator { +class Result_ORM implements Iterator +{ /** * Name of the model that the rows belong to * @var string * @access private */ - private $_model; + private $_model; /** * Database result * @var Result_Database * @access private */ - private $_dbresult; + private $_dbresult; - /** + /** * Rules for preloaded relationships * @var array * @access private */ - private $_with = array(); - + private $_with = array(); + /** * Initialized an Result_ORM with which model to use and which result to - * iterate over + * iterate over * * @param string $model Model name * @param Result_Database $dbresult Database result - * @param array $with Array of rules for preloaded relationships + * @param array $with Array of rules for preloaded relationships * @return void * @access public */ - public function __construct($model,$dbresult,$with=array()){ - $this->_model=$model; - $this->_dbresult = $dbresult; - foreach($with as $path => $rel) - $this->_with[] = array( - 'path' => explode('.',$path), - 'path_count' => count(explode('.',$path)), - 'model' => $rel['model'], - 'columns' => $rel['model']->columns() - ); - } + public function __construct($model, $dbresult, $with = array()) + { + $this->_model = $model; + $this->_dbresult = $dbresult; + foreach ($with as $path => $rel) + { + $this->_with[] = array( + 'path' => explode('.', $path), + 'path_count' => count(explode('.', $path)), + 'model' => $rel['model'], + 'columns' => $rel['model']->columns(), + ); + } + } /** * Rewinds database cursor to the first row @@ -60,8 +64,9 @@ class Result_ORM implements Iterator { * @return void * @access public */ - function rewind() { - $this->_dbresult->rewind(); + function rewind() + { + $this->_dbresult->rewind(); } /** @@ -70,39 +75,53 @@ class Result_ORM implements Iterator { * @return ORM Model of the current row of the result set * @access public */ - function current() { + function current() + { $model = new $this->_model; - - if (!$this->_dbresult->valid()) - return $model; - - if(empty($this->_with)) - return $model->values((array)$this->_dbresult->current(), true); - - $data = (array)$this->_dbresult->current(); - - $model_data=array(); - foreach($model->columns() as $column) - $model_data[$column] = array_shift($data); - $model->values($model_data, true); - - foreach($this->_with as $rel) { - $rel_data = array(); - foreach($rel['columns'] as $column) - $rel_data[$column] = array_shift($data); - $rel['model']->values($rel_data, true); - - $owner = $model; - foreach($rel['path'] as $key => $child) { - if ($key == $rel['path_count'] - 1) { - $owner->cached[$child]=$rel['model']; - }else { - $owner=$owner->cached[$child]; - } - } - } - - return $model; + + if (!$this->_dbresult->valid()) + { + return $model; + } + + if (empty($this->_with)) + { + return $model->values((array) $this->_dbresult->current(), true); + } + + $data = (array) $this->_dbresult->current(); + + $model_data = array(); + foreach ($model->columns() as $column) + { + $model_data[$column] = array_shift($data); + } + $model->values($model_data, true); + + foreach ($this->_with as $rel) + { + $rel_data = array(); + foreach ($rel['columns'] as $column) + { + $rel_data[$column] = array_shift($data); + } + $rel['model']->values($rel_data, true); + + $owner = $model; + foreach ($rel['path'] as $key => $child) + { + if ($key == $rel['path_count'] - 1) + { + $owner->cached[$child] = $rel['model']; + } + else + { + $owner = $owner->cached[$child]; + } + } + } + + return $model; } /** @@ -111,7 +130,8 @@ class Result_ORM implements Iterator { * @return int Row number * @access public */ - function key() { + function key() + { return $this->_dbresult->key(); } @@ -121,7 +141,8 @@ class Result_ORM implements Iterator { * @return void * @access public */ - function next() { + function next() + { $this->_dbresult->next(); } @@ -131,57 +152,71 @@ class Result_ORM implements Iterator { * @return bool returns false if we reach the end of the result set. * @access public */ - function valid() { - return $this->_dbresult->valid(); + function valid() + { + return $this->_dbresult->valid(); } /** * Returns an array of all rows as ORM objects if $rows is False, - * or just an array of result rows with each row being a standard object, - * this can be useful for functions like json_encode. + * or just an array of result rows with each row being a standard object, + * this can be useful for functions like json_encode. * * @param boolean $rows Whether to return just rows and not ORM objects * @return array Array of ORM objects or standard objects representing rows * @access public */ - public function as_array($rows = false) { - if (!$rows) { - $arr = array(); - foreach($this as $row) - $arr[] = $row; - return $arr; - } - - if (empty($this->_with)) - return $this->_dbresult->as_array(); - - $arr = array(); - $model=new $this->_model; - foreach($this->_dbresult as $data) { - $row = new stdClass; - $data=(array)$data; - foreach($model->columns() as $column) - $row->$column = array_shift($data); - - foreach($this->_with as $rel) { - $rel_data = new StdClass; - foreach($rel['columns'] as $column) - $rel_data->$column = array_shift($data); - - $owner = &$row; - foreach($rel['path'] as $key => $child) { - if ($key == $rel['path_count'] - 1) { - $owner->$child=$rel_data; - }else { - $owner=&$owner->$child; - } - } - } - $arr[]=$row; - } - - return $arr; - - } - + public function as_array($rows = false) + { + if (!$rows) + { + $arr = array(); + foreach ($this as $row) + $arr[] = $row; + return $arr; + } + + if (empty($this->_with)) + { + return $this->_dbresult->as_array(); + } + + $arr = array(); + $model = new $this->_model; + foreach ($this->_dbresult as $data) + { + $row = new stdClass; + $data = (array) $data; + foreach ($model->columns() as $column) + { + $row->$column = array_shift($data); + } + + foreach ($this->_with as $rel) + { + $rel_data = new StdClass; + foreach ($rel['columns'] as $column) + { + $rel_data->$column = array_shift($data); + } + + $owner = &$row; + foreach ($rel['path'] as $key => $child) + { + if ($key == $rel['path_count'] - 1) + { + $owner->$child = $rel_data; + } + else + { + $owner = &$owner->$child; + } + } + } + $arr[] = $row; + } + + return $arr; + } + }
\ No newline at end of file |