This commit is contained in:
parent
dac05178ca
commit
571cb46726
76
classes/Access.class.php
Normal file
76
classes/Access.class.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* class Doctrine_Access
|
||||
* Doctrine_Record and Doctrine_Collection classes extend this base class
|
||||
* the purpose of DAOStrategy is to provice array access and property overload interface for these classes
|
||||
*/
|
||||
abstract class Doctrine_Access implements ArrayAccess {
|
||||
/**
|
||||
* setArray
|
||||
* @param array $array an array of key => value pairs
|
||||
*/
|
||||
public function setArray(array $array) {
|
||||
foreach($array as $k=>$v):
|
||||
$this->set($k,$v);
|
||||
endforeach;
|
||||
}
|
||||
/**
|
||||
* __set -- an alias of set()
|
||||
* @see set, offsetSet
|
||||
* @param $name
|
||||
* @param $value
|
||||
*/
|
||||
public function __set($name,$value) {
|
||||
$this->set($name,$value);
|
||||
}
|
||||
/**
|
||||
* __get -- an alias of get()
|
||||
* @see get, offsetGet
|
||||
* @param mixed $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name) {
|
||||
return $this->get($name);
|
||||
}
|
||||
/**
|
||||
* @return boolean -- whether or not the data has a field $offset
|
||||
*/
|
||||
public function offsetExists($offset) {
|
||||
return (bool) isset($this->data[$offset]);
|
||||
}
|
||||
/**
|
||||
* offsetGet -- an alias of get()
|
||||
* @see get, __get
|
||||
* @param mixed $offset
|
||||
* @return mixed
|
||||
*/
|
||||
public function offsetGet($offset) {
|
||||
return $this->get($offset);
|
||||
}
|
||||
/**
|
||||
* sets $offset to $value
|
||||
* @see set, __set
|
||||
* @param mixed $offset
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
public function offsetSet($offset, $value) {
|
||||
if( ! isset($offset)) {
|
||||
$this->add($value);
|
||||
} else
|
||||
$this->set($offset,$value);
|
||||
}
|
||||
/**
|
||||
* unset a given offset
|
||||
* @see set, offsetSet, __set
|
||||
* @param mixed $offset
|
||||
*/
|
||||
public function offsetUnset($offset) {
|
||||
if($this instanceof Doctrine_Collection) {
|
||||
return $this->remove($offset);
|
||||
} else {
|
||||
$this->set($offset,null);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
33
classes/Association.class.php
Normal file
33
classes/Association.class.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
require_once("Relation.class.php");
|
||||
/**
|
||||
* Doctrine_Association this class takes care of association mapping
|
||||
* (= many-to-many relationships, where the relationship is handled through an additional relational table
|
||||
* which holds 2 foreign keys)
|
||||
*/
|
||||
class Doctrine_Association extends Doctrine_Relation {
|
||||
/**
|
||||
* @var Doctrine_Table $associationTable
|
||||
*/
|
||||
private $associationTable;
|
||||
/**
|
||||
* the constructor
|
||||
* @param Doctrine_Table $table foreign factory object
|
||||
* @param Doctrine_Table $associationTable factory which handles the association
|
||||
* @param string $local local field name
|
||||
* @param string $foreign foreign field name
|
||||
* @param integer $type type of relation
|
||||
* @see Doctrine_Table constants
|
||||
*/
|
||||
public function __construct(Doctrine_Table $table, Doctrine_Table $associationTable, $local, $foreign, $type) {
|
||||
parent::__construct($table, $local, $foreign, $type);
|
||||
$this->associationTable = $associationTable;
|
||||
}
|
||||
/**
|
||||
* @return Doctrine_Table
|
||||
*/
|
||||
public function getAssociationFactory() {
|
||||
return $this->associationTable;
|
||||
}
|
||||
}
|
||||
?>
|
74
classes/BatchIterator.class.php
Normal file
74
classes/BatchIterator.class.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/**
|
||||
* Doctrine_BatchIterator
|
||||
* iterates through Doctrine_Collection_Batch
|
||||
*/
|
||||
class Doctrine_BatchIterator implements Iterator {
|
||||
/**
|
||||
* @var Doctrine_Collection_Batch $collection
|
||||
*/
|
||||
private $collection;
|
||||
/**
|
||||
* @var array $keys
|
||||
*/
|
||||
private $keys;
|
||||
/**
|
||||
* @var mixed $key
|
||||
*/
|
||||
private $key;
|
||||
/**
|
||||
* @var integer $index
|
||||
*/
|
||||
private $index;
|
||||
/**
|
||||
* @var integer $count
|
||||
*/
|
||||
private $count;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
* @var Doctrine_Collection_Batch $collection
|
||||
*/
|
||||
public function __construct(Doctrine_Collection_Batch $collection) {
|
||||
$this->collection = $collection;
|
||||
$this->keys = $this->collection->getKeys();
|
||||
$this->count = $this->collection->count();
|
||||
}
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function rewind() {
|
||||
$this->index = 0;
|
||||
$i = $this->index;
|
||||
if(isset($this->keys[$i]))
|
||||
$this->key = $this->keys[$i];
|
||||
}
|
||||
/**
|
||||
* @return boolean whether or not the iteration will continue
|
||||
*/
|
||||
public function valid() {
|
||||
return $this->index < $this->count;
|
||||
}
|
||||
/**
|
||||
* @return integer the current key
|
||||
*/
|
||||
public function key() {
|
||||
return $this->key;
|
||||
}
|
||||
/**
|
||||
* @return Doctrine_Record the current DAO
|
||||
*/
|
||||
public function current() {
|
||||
return $this->collection->get($this->key);
|
||||
}
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function next() {
|
||||
$this->index++;
|
||||
$i = $this->index;
|
||||
if(isset($this->keys[$i]))
|
||||
$this->key = $this->keys[$i];
|
||||
}
|
||||
}
|
||||
?>
|
57
classes/Cache.class.php
Normal file
57
classes/Cache.class.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
interface iDoctrine_Cache {
|
||||
public function store(Doctrine_Record $record);
|
||||
public function clean();
|
||||
public function delete($id);
|
||||
public function fetch($id);
|
||||
public function exists($id);
|
||||
}
|
||||
class Doctrine_Cache implements iDoctrine_Cache {
|
||||
/**
|
||||
* implemented by child classes
|
||||
* @param Doctrine_Record $record
|
||||
* @return boolean
|
||||
*/
|
||||
public function store(Doctrine_Record $record) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* implemented by child classes
|
||||
* @return boolean
|
||||
*/
|
||||
public function clean() {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* implemented by child classes
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete($id) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* implemented by child classes
|
||||
* @throws InvalidKeyException
|
||||
* @return Doctrine_Record found Data Access Object
|
||||
*/
|
||||
public function fetch($id) {
|
||||
throw new InvalidKeyException();
|
||||
}
|
||||
/**
|
||||
* implemented by child classes
|
||||
* @param integer $id
|
||||
* @return boolean
|
||||
*/
|
||||
public function exists($id) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* implemented by child classes
|
||||
* @return integer
|
||||
*/
|
||||
public function deleteAll() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
261
classes/Cache/File.class.php
Normal file
261
classes/Cache/File.class.php
Normal file
@ -0,0 +1,261 @@
|
||||
<?php
|
||||
require_once(Doctrine::getPath().DIRECTORY_SEPARATOR."Cache.class.php");
|
||||
/**
|
||||
* Doctrine_CacheFile
|
||||
* @author Konsta Vesterinen
|
||||
* @package Doctrine ORM
|
||||
* @url www.phpdoctrine.com
|
||||
* @license LGPL
|
||||
* @version 1.0 alpha
|
||||
*/
|
||||
class Doctrine_Cache_File extends Doctrine_Cache implements Countable {
|
||||
const STATS_FILE = "stats.cache";
|
||||
/**
|
||||
* @var string $path path for the cache files
|
||||
*/
|
||||
private $path;
|
||||
|
||||
/**
|
||||
* @var array $fetched an array of fetched primary keys
|
||||
*/
|
||||
private $fetched = array();
|
||||
/**
|
||||
* @var Doctrine_Table $objTable
|
||||
*/
|
||||
private $objTable;
|
||||
/**
|
||||
* constructor
|
||||
* @param Doctrine_Table $objTable
|
||||
*/
|
||||
public function __construct(Doctrine_Table $objTable) {
|
||||
$this->objTable = $objTable;
|
||||
|
||||
$name = $this->getTable()->getTableName();
|
||||
|
||||
$manager = Doctrine_Manager::getInstance();
|
||||
|
||||
$dir = $manager->getAttribute(Doctrine::ATTR_CACHE_DIR);
|
||||
|
||||
if( ! is_dir($dir))
|
||||
mkdir($dir, 0777);
|
||||
|
||||
if( ! is_dir($dir.DIRECTORY_SEPARATOR.$name))
|
||||
mkdir($dir.DIRECTORY_SEPARATOR.$name, 0777);
|
||||
|
||||
$this->path = $dir.DIRECTORY_SEPARATOR.$name.DIRECTORY_SEPARATOR;
|
||||
|
||||
/**
|
||||
* create stats file
|
||||
*/
|
||||
if( ! file_exists($this->path.self::STATS_FILE))
|
||||
touch($this->path.self::STATS_FILE);
|
||||
|
||||
|
||||
}
|
||||
/**
|
||||
* @return Doctrine_Table
|
||||
*/
|
||||
public function getTable() {
|
||||
return $this->objTable;
|
||||
}
|
||||
/**
|
||||
* @return integer number of cache files
|
||||
*/
|
||||
public function count() {
|
||||
$c = -1;
|
||||
foreach(glob($this->path."*.cache") as $file) {
|
||||
$c++;
|
||||
}
|
||||
return $c;
|
||||
}
|
||||
/**
|
||||
* getStats
|
||||
* @return array an array of fetch statistics, keys as primary keys
|
||||
* and values as fetch times
|
||||
*/
|
||||
public function getStats() {
|
||||
$f = file_get_contents($this->path.self::STATS_FILE);
|
||||
// every cache file starts with a ":"
|
||||
$f = substr(trim($f),1);
|
||||
$e = explode(":",$f);
|
||||
return array_count_values($e);
|
||||
}
|
||||
/**
|
||||
* store store a Doctrine_Record into file cache
|
||||
* @param Doctrine_Record $record data access object to be stored
|
||||
* @return boolean whether or not storing was successful
|
||||
*/
|
||||
public function store(Doctrine_Record $record) {
|
||||
if($record->getState() != Doctrine_Record::STATE_CLEAN)
|
||||
return false;
|
||||
|
||||
|
||||
$file = $this->path.$record->getID().".cache";
|
||||
|
||||
if(file_exists($file))
|
||||
return false;
|
||||
|
||||
$clone = clone $record;
|
||||
$id = $clone->getID();
|
||||
|
||||
$fp = fopen($file,"w+");
|
||||
fwrite($fp,serialize($clone));
|
||||
fclose($fp);
|
||||
|
||||
|
||||
|
||||
$this->fetched[] = $id;
|
||||
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* clean
|
||||
* @return void
|
||||
*/
|
||||
public function clean() {
|
||||
$stats = $this->getStats();
|
||||
|
||||
arsort($stats);
|
||||
$size = $this->objTable->getAttribute(Doctrine::ATTR_CACHE_SIZE);
|
||||
|
||||
$count = count($stats);
|
||||
$i = 1;
|
||||
|
||||
$preserve = array();
|
||||
foreach($stats as $id => $count) {
|
||||
if($i > $size)
|
||||
break;
|
||||
|
||||
$preserve[$id] = true;
|
||||
$i++;
|
||||
}
|
||||
|
||||
foreach(glob($this->path."*.cache") as $file) {
|
||||
$e = explode(".",basename($file));
|
||||
$c = count($e);
|
||||
$id = $e[($c - 2)];
|
||||
|
||||
if( ! isset($preserve[$id]))
|
||||
@unlink($this->path.$id.".cache");
|
||||
}
|
||||
|
||||
$fp = fopen($this->path.self::STATS_FILE,"w+");
|
||||
fwrite($fp,"");
|
||||
fclose($fp);
|
||||
}
|
||||
/**
|
||||
* @param integer $id primary key of the DAO
|
||||
* @return string filename and path
|
||||
*/
|
||||
public function getFileName($id) {
|
||||
return $this->path.$id.".cache";
|
||||
}
|
||||
/**
|
||||
* @return array an array of fetched primary keys
|
||||
*/
|
||||
public function getFetched() {
|
||||
return $this->fetched;
|
||||
}
|
||||
/**
|
||||
* fetch fetch a Doctrine_Record from the file cache
|
||||
* @param integer $id
|
||||
*/
|
||||
public function fetch($id) {
|
||||
$name = $this->getTable()->getComponentName();
|
||||
$file = $this->path.$id.".cache";
|
||||
|
||||
if( ! file_exists($file))
|
||||
throw new InvalidKeyException();
|
||||
|
||||
$data = file_get_contents($file);
|
||||
|
||||
$record = unserialize($data);
|
||||
|
||||
if( ! ($record instanceof Doctrine_Record)) {
|
||||
// broken file, delete silently
|
||||
$this->delete($id);
|
||||
throw new InvalidKeyException();
|
||||
}
|
||||
|
||||
$this->fetched[] = $id;
|
||||
|
||||
return $record;
|
||||
}
|
||||
/**
|
||||
* exists check the existence of a cache file
|
||||
* @param integer $id primary key of the cached DAO
|
||||
* @return boolean whether or not a cache file exists
|
||||
*/
|
||||
public function exists($id) {
|
||||
$name = $this->getTable()->getComponentName();
|
||||
$file = $this->path.$id.".cache";
|
||||
return file_exists($file);
|
||||
}
|
||||
/**
|
||||
* deleteAll
|
||||
* @return void
|
||||
*/
|
||||
public function deleteAll() {
|
||||
foreach(glob($this->path."*.cache") as $file) {
|
||||
@unlink($file);
|
||||
}
|
||||
$fp = fopen($this->path.self::STATS_FILE,"w+");
|
||||
fwrite($fp,"");
|
||||
fclose($fp);
|
||||
}
|
||||
/**
|
||||
* delete delete a cache file
|
||||
* @param integer $id primary key of the cached DAO
|
||||
*/
|
||||
public function delete($id) {
|
||||
$file = $this->path.$id.".cache";
|
||||
|
||||
if( ! file_exists($file))
|
||||
return false;
|
||||
|
||||
@unlink($file);
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* deleteMultiple delete multiple cache files
|
||||
* @param array $ids an array containing cache file ids
|
||||
* @return integer the number of files deleted
|
||||
*/
|
||||
public function deleteMultiple(array $ids) {
|
||||
$deleted = 0;
|
||||
foreach($ids as $id) {
|
||||
if($this->delete($id)) $deleted++;
|
||||
}
|
||||
return $deleted;
|
||||
}
|
||||
/**
|
||||
* destructor
|
||||
* the purpose of this destructor is to save all the fetched
|
||||
* primary keys into the cache stats
|
||||
*/
|
||||
public function __destruct() {
|
||||
if( ! empty($this->fetched)) {
|
||||
$fp = fopen($this->path.self::STATS_FILE,"a");
|
||||
fwrite($fp,":".implode(":",$this->fetched));
|
||||
fclose($fp);
|
||||
}
|
||||
/**
|
||||
*
|
||||
* cache auto-cleaning algorithm
|
||||
* $ttl is the number of page loads between each cache cleaning
|
||||
* the default is 100 page loads
|
||||
*
|
||||
* this means that the average number of page loads between
|
||||
* each cache clean is 100 page loads (= 100 constructed Doctrine_Managers)
|
||||
*
|
||||
*/
|
||||
$ttl = $this->objTable->getAttribute(Doctrine::ATTR_CACHE_TTL);
|
||||
$l1 = (mt_rand(1,$ttl) / $ttl);
|
||||
$l2 = (1 - 1/$ttl);
|
||||
|
||||
if($l1 > $l2)
|
||||
$this->clean();
|
||||
|
||||
}
|
||||
}
|
||||
?>
|
289
classes/Collection.class.php
Normal file
289
classes/Collection.class.php
Normal file
@ -0,0 +1,289 @@
|
||||
<?php
|
||||
/**
|
||||
* class Doctrine_Collection a collection of data access objects
|
||||
*
|
||||
* @author Konsta Vesterinen
|
||||
* @package Doctrine ORM
|
||||
* @url www.phpdoctrine.com
|
||||
* @license LGPL
|
||||
* @version 1.0 alpha
|
||||
*/
|
||||
class Doctrine_Collection extends Doctrine_Access implements Countable, IteratorAggregate {
|
||||
/**
|
||||
* @var array $data an array containing the data access objects of this collection
|
||||
*/
|
||||
protected $data = array();
|
||||
/**
|
||||
* @var Doctrine_Table $table each collection has only records of specified table
|
||||
*/
|
||||
protected $table;
|
||||
/**
|
||||
* @var Doctrine_Record $reference collection can belong to a record
|
||||
*/
|
||||
protected $reference;
|
||||
/**
|
||||
* @var string $reference_field the reference field of the collection
|
||||
*/
|
||||
protected $reference_field;
|
||||
/**
|
||||
* @var Doctrine_Relation
|
||||
*/
|
||||
protected $relation;
|
||||
/**
|
||||
* @var boolean $expanded whether or not this collection has been expanded
|
||||
*/
|
||||
protected $expanded = false;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
*/
|
||||
public function __construct(Doctrine_Table $table) {
|
||||
$this->table = $table;
|
||||
}
|
||||
/**
|
||||
* @return object Doctrine_Table
|
||||
*/
|
||||
public function getTable() {
|
||||
return $this->table;
|
||||
}
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function addData(array $data) {
|
||||
$this->data[] = $data;
|
||||
}
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLast() {
|
||||
return end($this->data);
|
||||
}
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setReference(Doctrine_Record $record,Doctrine_Relation $relation) {
|
||||
$this->reference = $record;
|
||||
$this->relation = $relation;
|
||||
|
||||
if($relation instanceof Doctrine_ForeignKey ||
|
||||
$relation instanceof Doctrine_LocalKey) {
|
||||
$this->reference_field = $relation->getForeign();
|
||||
|
||||
$value = $record->get($relation->getLocal());
|
||||
|
||||
foreach($this as $record) {
|
||||
if($value !== null) {
|
||||
$record->set($this->reference_field, $value);
|
||||
} else {
|
||||
$record->set($this->reference_field, $this->reference);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getReference() {
|
||||
return $this->reference;
|
||||
}
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function expand($i = null) {
|
||||
if( ! isset($this->reference))
|
||||
return false;
|
||||
|
||||
$id = $this->reference->getID();
|
||||
|
||||
if(empty($id))
|
||||
return false;
|
||||
|
||||
foreach($this->data as $v) {
|
||||
switch(gettype($v)):
|
||||
case "array":
|
||||
$ids[] = $v['id'];
|
||||
break;
|
||||
case "object":
|
||||
$id = $v->getID();
|
||||
if( ! empty($id))
|
||||
$ids[] = $id;
|
||||
break;
|
||||
endswitch;
|
||||
}
|
||||
|
||||
if($this instanceof Doctrine_Collection_Immediate) {
|
||||
$fields = implode(", ",$this->table->getColumnNames());
|
||||
} else {
|
||||
$fields = implode(", ",$this->table->getPrimaryKeys());
|
||||
}
|
||||
|
||||
if($this->relation instanceof Doctrine_ForeignKey) {
|
||||
$str = "";
|
||||
$params = array($this->reference->getID());
|
||||
|
||||
if( ! empty($ids)) {
|
||||
$str = " && id NOT IN (".substr(str_repeat("?, ",count($ids)),0,-2).")";
|
||||
$params = array_merge($params,$ids);
|
||||
}
|
||||
$str = " WHERE ".$this->reference_field." = ?".$str;
|
||||
$query = "SELECT ".$fields." FROM ".$this->table->getTableName().$str;
|
||||
$coll = $this->table->execute($query,$params);
|
||||
|
||||
} elseif($this->relation instanceof Doctrine_Association) {
|
||||
|
||||
$asf = $fk->getAssociationFactory();
|
||||
$query = "SELECT ".$foreign." FROM ".$asf->getTableName()." WHERE ".$local."=".$this->getID();
|
||||
|
||||
$table = $fk->getTable();
|
||||
$graph = new Doctrine_DQL_Parser($table->getSession());
|
||||
|
||||
$q = "FROM ".$table->getComponentName()." WHERE ".$table->getComponentName().".id IN ($query)";
|
||||
}
|
||||
|
||||
foreach($coll as $record) {
|
||||
if(isset($this->reference_field))
|
||||
$record->rawSet($this->reference_field, $this->reference);
|
||||
|
||||
$this->reference->addReference($record);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function remove($key) {
|
||||
if( ! isset($this->data[$key]))
|
||||
throw new InvalidKeyException();
|
||||
|
||||
$removed = $this->data[$key];
|
||||
|
||||
unset($this->data[$key]);
|
||||
return $removed;
|
||||
}
|
||||
/**
|
||||
* @param mixed $key
|
||||
* @return boolean
|
||||
*/
|
||||
public function contains($key) {
|
||||
return isset($this->data[$key]);
|
||||
}
|
||||
/**
|
||||
* @param mixed $key
|
||||
* @return object Doctrine_Record return a specified dao
|
||||
*/
|
||||
public function get($key) {
|
||||
if( ! isset($this->data[$key])) {
|
||||
$this->expand();
|
||||
|
||||
if( ! isset($this->data[$key]))
|
||||
$this->data[$key] = $this->table->create();
|
||||
|
||||
if(isset($this->reference_field)) {
|
||||
$value = $this->reference->get($this->relation->getLocal());
|
||||
|
||||
if($value !== null) {
|
||||
$this->data[$key]->set($this->reference_field, $value);
|
||||
} else {
|
||||
$this->data[$key]->set($this->reference_field, $this->reference);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->data[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array an array containing all primary keys
|
||||
*/
|
||||
public function getPrimaryKeys() {
|
||||
$list = array();
|
||||
foreach($this->data[$key] as $record):
|
||||
$list[] = $record->getID();
|
||||
endforeach;
|
||||
return $list;
|
||||
}
|
||||
/**
|
||||
* returns all keys
|
||||
* @return array
|
||||
*/
|
||||
public function getKeys() {
|
||||
return array_keys($this->data);
|
||||
}
|
||||
/**
|
||||
* count
|
||||
* this class implements interface countable
|
||||
* @return integer number of data access objects in this collection
|
||||
*/
|
||||
public function count() {
|
||||
return count($this->data);
|
||||
}
|
||||
/**
|
||||
* set
|
||||
* @param integer $key
|
||||
* @param Doctrine_Record $record
|
||||
* @return void
|
||||
*/
|
||||
public function set($key,Doctrine_Record $record) {
|
||||
if(isset($this->reference_field))
|
||||
$record->set($this->reference_field,$this->reference);
|
||||
|
||||
$this->data[$key] = $record;
|
||||
}
|
||||
/**
|
||||
* add
|
||||
* adds a dao instance to this collection
|
||||
* @param Doctrine_Record $record data access object to be added
|
||||
* @param string $key optional key for the DAO
|
||||
* @return boolean
|
||||
*/
|
||||
public function add(Doctrine_Record $record,$key = null) {
|
||||
if(isset($this->reference_field))
|
||||
$record->rawSet($this->reference_field,$this->reference);
|
||||
|
||||
if(isset($key)) {
|
||||
|
||||
if(isset($this->data[$key]))
|
||||
return false;
|
||||
|
||||
$this->data[$key] = $record;
|
||||
}
|
||||
|
||||
$this->data[] = $record;
|
||||
return true;
|
||||
|
||||
}
|
||||
/**
|
||||
* save
|
||||
* saves all data access objects
|
||||
*/
|
||||
public function save() {
|
||||
$this->table->getSession()->saveCollection($this);
|
||||
}
|
||||
/**
|
||||
* single shot delete
|
||||
* deletes all dao instances from this collection
|
||||
* uses only one database query to perform this operation
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete() {
|
||||
$ids = $this->table->getSession()->deleteCollection($this);
|
||||
$this->data = array();
|
||||
}
|
||||
/**
|
||||
* getIterator
|
||||
* @return object ArrayIterator
|
||||
*/
|
||||
public function getIterator() {
|
||||
$data = $this->data;
|
||||
return new ArrayIterator($data);
|
||||
}
|
||||
/**
|
||||
* returns a string representation of this object
|
||||
*/
|
||||
public function __toString() {
|
||||
return Doctrine_Lib::getCollectionAsString($this);
|
||||
}
|
||||
}
|
||||
?>
|
182
classes/Collection/Batch.class.php
Normal file
182
classes/Collection/Batch.class.php
Normal file
@ -0,0 +1,182 @@
|
||||
<?php
|
||||
require_once(Doctrine::getPath().DIRECTORY_SEPARATOR."Collection.class.php");
|
||||
/**
|
||||
* Doctrine_Collection_Batch a collection of data access objects,
|
||||
* with batch load strategy
|
||||
*
|
||||
*
|
||||
* @author Konsta Vesterinen
|
||||
* @package Doctrine ORM
|
||||
* @url www.phpdoctrine.com
|
||||
* @license LGPL
|
||||
* @version 1.0 alpha
|
||||
*/
|
||||
class Doctrine_Collection_Batch extends Doctrine_Collection {
|
||||
/**
|
||||
* @var integer $batchSize batch size
|
||||
*/
|
||||
private $batchSize;
|
||||
/**
|
||||
* @var array $loaded an array containing the loaded batches, keys representing the batch indexes
|
||||
*/
|
||||
private $loaded = array();
|
||||
|
||||
public function __construct(Doctrine_DQL_Parser $graph,$key) {
|
||||
parent::__construct($graph->getTable($key));
|
||||
$this->data = $graph->getData($key);
|
||||
if( ! is_array($this->data))
|
||||
$this->data = array();
|
||||
|
||||
$this->batchSize = $this->getTable()->getAttribute(Doctrine::ATTR_BATCH_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $batchSize batch size
|
||||
*/
|
||||
public function setBatchSize($batchSize) {
|
||||
$batchSize = (int) $batchSize;
|
||||
if($batchSize <= 0)
|
||||
return false;
|
||||
|
||||
$this->batchSize = $batchSize;
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @return integer
|
||||
*/
|
||||
public function getBatchSize() {
|
||||
return $this->batchSize;
|
||||
}
|
||||
/**
|
||||
* load load a specified element, by loading the batch the element is part of
|
||||
* @param Doctrine_Record $record data access object
|
||||
* @return boolean whether or not the load operation was successful
|
||||
*/
|
||||
public function load(Doctrine_Record $record) {
|
||||
if(empty($this->data))
|
||||
return false;
|
||||
|
||||
$id = $record->getID();
|
||||
foreach($this->data as $key => $v) {
|
||||
if(is_object($v)) {
|
||||
if($v->getID() == $id)
|
||||
break;
|
||||
|
||||
} elseif(is_array($v["id"])) {
|
||||
if($v["id"] == $id)
|
||||
break;
|
||||
}
|
||||
}
|
||||
$x = floor($key / $this->batchSize);
|
||||
|
||||
if( ! isset($this->loaded[$x])) {
|
||||
|
||||
$e = $x * $this->batchSize;
|
||||
$e2 = ($x + 1)* $this->batchSize;
|
||||
|
||||
$a = array();
|
||||
$proxies = array();
|
||||
|
||||
for($i = $e; $i < $e2 && $i < $this->count(); $i++):
|
||||
if(is_object($this->data[$i]))
|
||||
$id = $this->data[$i]->getID();
|
||||
elseif(is_array($this->data[$i]))
|
||||
$id = $this->data[$i]["id"];
|
||||
|
||||
$load = false;
|
||||
|
||||
// check the cache
|
||||
// no need of fetching the same data twice
|
||||
try {
|
||||
$record = $this->table->getCache()->fetch($id);
|
||||
} catch(InvalidKeyException $ex) {
|
||||
$load = true;
|
||||
}
|
||||
|
||||
if($load)
|
||||
$a[] = $id;
|
||||
endfor;
|
||||
|
||||
$c = count($a);
|
||||
|
||||
$query = $this->table->getQuery()." WHERE ";
|
||||
$query .= ($c > 1)?"id IN (":"id = ";
|
||||
$query .= substr(str_repeat("?, ",count($a)),0,-2);
|
||||
$query .= ($c > 1)?")":"";
|
||||
|
||||
$stmt = $this->table->getSession()->execute($query,$a);
|
||||
|
||||
while($row = $stmt->fetch(PDO::FETCH_ASSOC)):
|
||||
$this->table->setData($row);
|
||||
|
||||
if(is_object($this->data[$e])) {
|
||||
$this->data[$e]->factoryRefresh($this->table);
|
||||
} else {
|
||||
$this->data[$e] = $this->table->getRecord();
|
||||
}
|
||||
|
||||
$e++;
|
||||
endwhile;
|
||||
$this->loaded[$x] = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* get
|
||||
* @param mixed $key the key of the data access object
|
||||
* @return object Doctrine_Record data access object
|
||||
*/
|
||||
public function get($key) {
|
||||
if(isset($this->data[$key])) {
|
||||
switch(gettype($this->data[$key])):
|
||||
case "array":
|
||||
try {
|
||||
|
||||
// try to fetch the Doctrine_Record from cache
|
||||
if( ! isset($this->data[$key]["id"]))
|
||||
throw new InvalidKeyException();
|
||||
|
||||
$record = $this->table->getCache()->fetch($this->data[$key]["id"]);
|
||||
|
||||
} catch(InvalidKeyException $e) {
|
||||
|
||||
// Doctrine_Record didn't exist in cache
|
||||
$this->table->setData($this->data[$key]);
|
||||
$proxy = $this->table->getProxy();
|
||||
$record = $proxy;
|
||||
}
|
||||
|
||||
$record->addCollection($this);
|
||||
break;
|
||||
case "object":
|
||||
$record = $this->data[$key];
|
||||
break;
|
||||
endswitch;
|
||||
} else {
|
||||
|
||||
$this->expand();
|
||||
|
||||
if(isset($this->data[$key])) {
|
||||
$record = $this->data[$key];
|
||||
} else {
|
||||
$record = $this->table->create();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(isset($this->reference_field))
|
||||
$record->set($this->reference_field,$this->reference);
|
||||
|
||||
$this->data[$key] = $record;
|
||||
return $this->data[$key];
|
||||
}
|
||||
/**
|
||||
* @return Doctrine_BatchIterator
|
||||
*/
|
||||
public function getIterator() {
|
||||
return new Doctrine_BatchIterator($this);
|
||||
}
|
||||
}
|
||||
?>
|
28
classes/Collection/Immediate.class.php
Normal file
28
classes/Collection/Immediate.class.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
require_once(Doctrine::getPath().DIRECTORY_SEPARATOR."Collection.class.php");
|
||||
/**
|
||||
* @author Konsta Vesterinen
|
||||
* @package Doctrine ORM
|
||||
* @url www.phpdoctrine.com
|
||||
* @license LGPL
|
||||
* @version 1.0 alpha
|
||||
*/
|
||||
class Doctrine_Collection_Immediate extends Doctrine_Collection {
|
||||
/**
|
||||
* @param Doctrine_DQL_Parser $graph
|
||||
* @param integer $key
|
||||
*/
|
||||
public function __construct(Doctrine_DQL_Parser $graph,$key) {
|
||||
parent::__construct($graph->getTable($key));
|
||||
|
||||
$name = $this->table->getComponentName();
|
||||
$data = $graph->getData($name);
|
||||
if(is_array($data)) {
|
||||
foreach($data as $k=>$v):
|
||||
$this->table->setData($v);
|
||||
$this->add($this->table->getRecord());
|
||||
endforeach;
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
18
classes/Collection/Lazy.class.php
Normal file
18
classes/Collection/Lazy.class.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
require_once(Doctrine::getPath().DIRECTORY_SEPARATOR."Collection.class.php");
|
||||
/**
|
||||
* a collection of Doctrine_Record objects with lazy load strategy
|
||||
* (batch load strategy with batch size 1)
|
||||
*/
|
||||
class Doctrine_Collection_Lazy extends Doctrine_Collection_Batch {
|
||||
/**
|
||||
* constructor
|
||||
* @param Doctrine_DQL_Parser $graph
|
||||
* @param string $key
|
||||
*/
|
||||
public function __construct(Doctrine_DQL_Parser $graph,$key) {
|
||||
parent::setBatchSize(1);
|
||||
parent::__construct($graph,$key);
|
||||
}
|
||||
}
|
||||
?>
|
150
classes/Configurable.class.php
Normal file
150
classes/Configurable.class.php
Normal file
@ -0,0 +1,150 @@
|
||||
<?php
|
||||
/**
|
||||
* Doctrine_Configurable
|
||||
* the base for Doctrine_Table, Doctrine_Manager and Doctrine_Session
|
||||
*
|
||||
*
|
||||
* @author Konsta Vesterinen
|
||||
* @package Doctrine ORM
|
||||
* @url www.phpdoctrine.com
|
||||
* @license LGPL
|
||||
* @version 1.0 beta2
|
||||
*
|
||||
*/
|
||||
abstract class Doctrine_Configurable {
|
||||
|
||||
/**
|
||||
* @var array $attributes an array of containing all attributes
|
||||
*/
|
||||
private $attributes = array();
|
||||
/**
|
||||
* @var $parent the parents of this component
|
||||
*/
|
||||
private $parent;
|
||||
/**
|
||||
* @throws Exception if the value is invalid
|
||||
* @param integer $attribute
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
final public function setAttribute($attribute,$value) {
|
||||
switch($attribute):
|
||||
case Doctrine::ATTR_BATCH_SIZE:
|
||||
if($value < 0)
|
||||
throw new Doctrine_Exception("Batch size should be greater than or equal to zero");
|
||||
break;
|
||||
case Doctrine::ATTR_CACHE_DIR:
|
||||
if(substr(trim($value),0,6) == "%ROOT%") {
|
||||
$dir = dirname(__FILE__);
|
||||
$value = $dir.substr($value,6);
|
||||
}
|
||||
|
||||
if(! is_dir($value) && ! file_exists($value))
|
||||
mkdir($value,0777);
|
||||
break;
|
||||
case Doctrine::ATTR_CACHE_TTL:
|
||||
if($value < 1)
|
||||
throw new Doctrine_Exception("Cache TimeToLive should be greater than or equal to 1");
|
||||
break;
|
||||
case Doctrine::ATTR_CACHE_SIZE:
|
||||
if($value < 1)
|
||||
throw new Doctrine_Exception("Cache size should be greater than or equal to 1");
|
||||
break;
|
||||
case Doctrine::ATTR_CACHE_SLAM:
|
||||
if($value < 0 || $value > 1)
|
||||
throw new Doctrine_Exception("Cache slam defense should be a floating point number between 0 and 1");
|
||||
break;
|
||||
case Doctrine::ATTR_FETCHMODE:
|
||||
if($value < 0)
|
||||
throw new Doctrine_Exception("Unknown fetchmode. Fetchmode should be an integer between 0 and 2. See Doctrine::FETCH_* constants.");
|
||||
break;
|
||||
case Doctrine::ATTR_LISTENER:
|
||||
$this->setEventListener($value);
|
||||
break;
|
||||
case Doctrine::ATTR_PK_COLUMNS:
|
||||
if( ! is_array($value))
|
||||
throw new Doctrine_Exception("The value of Doctrine::ATTR_PK_COLUMNS attribute must be an array");
|
||||
break;
|
||||
case Doctrine::ATTR_PK_TYPE:
|
||||
if($value != Doctrine::INCREMENT_KEY && $value != Doctrine::UNIQUE_KEY)
|
||||
throw new Doctrine_Exception("The value of Doctrine::ATTR_PK_TYPE attribute must be either Doctrine::INCREMENT_KEY or Doctrine::UNIQUE_KEY");
|
||||
|
||||
break;
|
||||
case Doctrine::ATTR_LOCKMODE:
|
||||
if($this instanceof Doctrine_Session) {
|
||||
if($this->getState() != Doctrine_Session::STATE_OPEN)
|
||||
throw new Doctrine_Exception("Couldn't set lockmode. There are transactions open.");
|
||||
|
||||
} elseif($this instanceof Doctrine_Manager) {
|
||||
foreach($this as $session) {
|
||||
if($session->getState() != Doctrine_Session::STATE_OPEN)
|
||||
throw new Doctrine_Exception("Couldn't set lockmode. There are transactions open.");
|
||||
}
|
||||
} else {
|
||||
throw new Doctrine_Exception("Lockmode attribute can only be set at the global or session level.");
|
||||
}
|
||||
break;
|
||||
case Doctrine::ATTR_CREATE_TABLES:
|
||||
$value = (bool) $value;
|
||||
break;
|
||||
case Doctrine::ATTR_VLD:
|
||||
|
||||
break;
|
||||
case Doctrine::ATTR_CACHE:
|
||||
if($value != Doctrine::CACHE_FILE && $value != Doctrine::CACHE_NONE)
|
||||
throw new Doctrine_Exception("Unknown cache container. See Doctrine::CACHE_* constants for availible containers.");
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unknown attribute.");
|
||||
endswitch;
|
||||
|
||||
$this->attributes[$attribute] = $value;
|
||||
|
||||
}
|
||||
/**
|
||||
* @param Doctrine_EventListener $listener
|
||||
* @return void
|
||||
*/
|
||||
final public function setEventListener(Doctrine_EventListener $listener) {
|
||||
$i = Doctrine::ATTR_LISTENER;
|
||||
$this->attributes[$i] = $listener;
|
||||
}
|
||||
/**
|
||||
* @return mixed the value of the attribute
|
||||
*/
|
||||
final public function getAttribute($attribute) {
|
||||
$attribute = (int) $attribute;
|
||||
|
||||
if($attribute < 1 || $attribute > 14)
|
||||
throw new InvalidKeyException();
|
||||
|
||||
if( ! isset($this->attributes[$attribute])) {
|
||||
if(isset($this->parent))
|
||||
return $this->parent->getAttribute($attribute);
|
||||
|
||||
return null;
|
||||
}
|
||||
return $this->attributes[$attribute];
|
||||
}
|
||||
/**
|
||||
* getAttributes
|
||||
* @return array
|
||||
*/
|
||||
final public function getAttributes() {
|
||||
return $this->attributes;
|
||||
}
|
||||
/**
|
||||
* @param Doctrine_Configurable $component
|
||||
* @return void
|
||||
*/
|
||||
final public function setParent(Doctrine_Configurable $component) {
|
||||
$this->parent = $component;
|
||||
}
|
||||
/**
|
||||
* getParent
|
||||
*/
|
||||
final public function getParent() {
|
||||
return $this->parent;
|
||||
}
|
||||
}
|
||||
?>
|
64
classes/ConfigurableComponent.class.php
Normal file
64
classes/ConfigurableComponent.class.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
abstract class Doctrine_Component {
|
||||
/**
|
||||
* setTableName
|
||||
* @param string $name table name
|
||||
* @return void
|
||||
*/
|
||||
final public function setTableName($name) {
|
||||
$this->getComponent()->setTableName($name);
|
||||
}
|
||||
/**
|
||||
* setInheritanceMap
|
||||
* @param array $inheritanceMap
|
||||
* @return void
|
||||
*/
|
||||
final public function setInheritanceMap(array $inheritanceMap) {
|
||||
$this->getComponent()->setInheritanceMap($inheritanceMap);
|
||||
}
|
||||
/**
|
||||
* setAttribute
|
||||
* @param integer $attribute
|
||||
* @param mixed $value
|
||||
* @see Doctrine::ATTR_* constants
|
||||
* @return void
|
||||
*/
|
||||
final public function setAttribute($attribute,$value) {
|
||||
$this->getComponent()->setAttribute($attribute,$value);
|
||||
}
|
||||
/**
|
||||
* @param string $objTableName
|
||||
* @param string $fkField
|
||||
* @return void
|
||||
*/
|
||||
final public function ownsOne($componentName,$foreignKey) {
|
||||
$this->getComponent()->bind($componentName,$foreignKey,Doctrine_Table::ONE_COMPOSITE);
|
||||
}
|
||||
/**
|
||||
* @param string $objTableName
|
||||
* @param string $fkField
|
||||
* @return void
|
||||
*/
|
||||
final public function ownsMany($componentName,$foreignKey) {
|
||||
$this->getComponent()->bind($componentName,$foreignKey,Doctrine_Table::MANY_COMPOSITE);
|
||||
}
|
||||
/**
|
||||
* @param string $objTableName
|
||||
* @param string $fkField
|
||||
* @return void
|
||||
*/
|
||||
final public function hasOne($componentName,$foreignKey) {
|
||||
$this->getComponent()->bind($componentName,$foreignKey,Doctrine_Table::ONE_AGGREGATE);
|
||||
}
|
||||
/**
|
||||
* @param string $objTableName
|
||||
* @param string $fkField
|
||||
* @return void
|
||||
*/
|
||||
final public function hasMany($componentName,$foreignKey) {
|
||||
$this->getComponent()->bind($componentName,$foreignKey,Doctrine_Table::MANY_AGGREGATE);
|
||||
}
|
||||
|
||||
abstract public function getComponent();
|
||||
}
|
||||
?>
|
121
classes/DB.class.php
Normal file
121
classes/DB.class.php
Normal file
@ -0,0 +1,121 @@
|
||||
<?php
|
||||
class Doctrine_DB extends PDO implements Countable, IteratorAggregate {
|
||||
/**
|
||||
* default DSN
|
||||
*/
|
||||
const DSN = "mysql://zYne:dc34@localhost/test";
|
||||
/**
|
||||
* executed queries
|
||||
*/
|
||||
private $queries = array();
|
||||
/**
|
||||
* execution times of the executed queries
|
||||
*/
|
||||
private $exectimes = array();
|
||||
|
||||
/**
|
||||
* constructor
|
||||
* @param string $dsn
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
*/
|
||||
public function __construct($dsn,$username,$password) {
|
||||
parent::__construct($dsn,$username,$password);
|
||||
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array("Doctrine_DBStatement",array($this)));
|
||||
}
|
||||
/**
|
||||
* @param string $dsn PEAR::DB like DSN
|
||||
* format: schema://user:password@address/dbname
|
||||
*/
|
||||
public static function getConnection($dsn = null) {
|
||||
static $instance;
|
||||
if( ! isset($instance)) {
|
||||
if( ! isset($dsn)) {
|
||||
$a = parse_url(self::DSN);
|
||||
} else {
|
||||
$a = parse_url($dsn);
|
||||
}
|
||||
$e = array();
|
||||
$e[0] = $a["scheme"].":host=".$a["host"].";dbname=".substr($a["path"],1);
|
||||
$e[1] = $a["user"];
|
||||
$e[2] = $a["pass"];
|
||||
|
||||
$instance = new Doctrine_DB($e[0],$e[1],$e[2]);
|
||||
}
|
||||
return $instance;
|
||||
}
|
||||
/**
|
||||
* @param string $query query to be executed
|
||||
*/
|
||||
public function query($query) {
|
||||
$this->queries[] = $query;
|
||||
$time = microtime();
|
||||
|
||||
$stmt = parent::query($query);
|
||||
$this->exectimes[] = (microtime() - $time);
|
||||
return $stmt;
|
||||
}
|
||||
/**
|
||||
* @param string $query query to be prepared
|
||||
*/
|
||||
public function prepare($query) {
|
||||
$this->queries[] = $query;
|
||||
return parent::prepare($query);
|
||||
}
|
||||
/**
|
||||
* @param string $time exectime of the last executed query
|
||||
* @return void
|
||||
*/
|
||||
public function addExecTime($time) {
|
||||
$this->exectimes[] = $time;
|
||||
}
|
||||
|
||||
public function getExecTimes() {
|
||||
return $this->exectimes;
|
||||
}
|
||||
/**
|
||||
* @return array an array of executed queries
|
||||
*/
|
||||
public function getQueries() {
|
||||
return $this->queries;
|
||||
}
|
||||
/**
|
||||
* @return ArrayIterator
|
||||
*/
|
||||
public function getIterator() {
|
||||
return new ArrayIterator($this->queries);
|
||||
}
|
||||
/**
|
||||
* returns the number of executed queries
|
||||
* @return integer
|
||||
*/
|
||||
public function count() {
|
||||
return count($this->queries);
|
||||
}
|
||||
|
||||
}
|
||||
class Doctrine_DBStatement extends PDOStatement {
|
||||
/**
|
||||
* @param Doctrine_DB $dbh Doctrine Database Handler
|
||||
*/
|
||||
private $dbh;
|
||||
/**
|
||||
* @param Doctrine_DB $dbh
|
||||
*/
|
||||
private function __construct(Doctrine_DB $dbh) {
|
||||
$this->dbh = $dbh;
|
||||
}
|
||||
/**
|
||||
* @param array $params
|
||||
*/
|
||||
public function execute($params) {
|
||||
$time = microtime();
|
||||
$result = parent::execute($params);
|
||||
|
||||
$exectime = (microtime() - $time);
|
||||
$this->dbh->addExecTime($exectime);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
?>
|
779
classes/DQL/Parser.class.php
Normal file
779
classes/DQL/Parser.class.php
Normal file
@ -0,0 +1,779 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Doctrine_DQL_Parser
|
||||
* this is the base class for generating complex data graphs
|
||||
* (multiple collections, multiple factories, multiple data access objects)
|
||||
* with only one query
|
||||
*
|
||||
*
|
||||
* @author Konsta Vesterinen
|
||||
* @package Doctrine ORM
|
||||
* @url www.phpdoctrine.com
|
||||
* @license LGPL
|
||||
* @version 1.0 alpha
|
||||
*/
|
||||
class Doctrine_DQL_Parser {
|
||||
/**
|
||||
* @var array $fetchmodes an array containing all fetchmodes
|
||||
*/
|
||||
private $fetchModes = array();
|
||||
/**
|
||||
* @var array $fields an array containing all the selected fields
|
||||
*/
|
||||
private $fields = array();
|
||||
/**
|
||||
* @var array $tablenames an array containing all the tables used in the query
|
||||
*/
|
||||
private $tablenames = array();
|
||||
/**
|
||||
* @var array $from query FROM parts
|
||||
*/
|
||||
private $from = array();
|
||||
/**
|
||||
* @var array $join query JOIN parts
|
||||
*/
|
||||
private $join = array();
|
||||
/**
|
||||
* @var string $where
|
||||
*/
|
||||
private $where = array();
|
||||
/**
|
||||
* @var array $orderby query ORDER BY parts
|
||||
*/
|
||||
private $orderby = array();
|
||||
/**
|
||||
* @var integer $limit query limit
|
||||
*/
|
||||
private $limit;
|
||||
/**
|
||||
* @var integer $offset query offset
|
||||
*/
|
||||
private $offset;
|
||||
|
||||
private $joined = array();
|
||||
/**
|
||||
* @var array $data fetched data
|
||||
*/
|
||||
private $data = array();
|
||||
/**
|
||||
* @var Doctrine_Session $session Doctrine_Session object
|
||||
*/
|
||||
private $session;
|
||||
|
||||
private $inheritanceApplied = false;
|
||||
|
||||
private $aggregate = false;
|
||||
|
||||
private $paths = array();
|
||||
|
||||
private $connectors = array();
|
||||
/**
|
||||
* @param Doctrine_Session $session
|
||||
*/
|
||||
public function __construct(Doctrine_Session $session) {
|
||||
$this->session = $session;
|
||||
}
|
||||
/**
|
||||
* clear
|
||||
* resets all the variables
|
||||
*/
|
||||
private function clear() {
|
||||
$this->fetchModes = array();
|
||||
$this->fields = array();
|
||||
$this->tnames = array();
|
||||
|
||||
$this->from = array();
|
||||
$this->join = array();
|
||||
$this->where = array();
|
||||
$this->orderby = array();
|
||||
$this->inheritanceApplied = false;
|
||||
$this->aggregate = false;
|
||||
$this->data = array();
|
||||
$this->connectors = array();
|
||||
}
|
||||
/**
|
||||
* loadFields -- this method loads fields for a given factory and
|
||||
* constructs a little bit of sql for every field
|
||||
*
|
||||
* fields of the factories become: [tablename].[fieldname] as [tablename]__[fieldname]
|
||||
*
|
||||
* @access private
|
||||
* @param object Doctrine_Table $table a Doctrine_Table object
|
||||
* @param integer $fetchmode fetchmode the table is using eg. Doctrine::FETCH_LAZY
|
||||
* @return void
|
||||
*/
|
||||
private function loadFields(Doctrine_Table $table,$fetchmode) {
|
||||
switch($fetchmode):
|
||||
case Doctrine::FETCH_IMMEDIATE:
|
||||
$names = $table->getColumnNames();
|
||||
break;
|
||||
case Doctrine::FETCH_LAZY:
|
||||
case Doctrine::FETCH_BATCH:
|
||||
$names = $table->getPrimaryKeys();
|
||||
break;
|
||||
default:
|
||||
throw new InvalidFetchModeException();
|
||||
endswitch;
|
||||
$cname = $table->getComponentName();
|
||||
$this->fetchModes[$cname] = $fetchmode;
|
||||
$tablename = $table->getTableName();
|
||||
|
||||
$count = count($this->tnames);
|
||||
foreach($names as $name) {
|
||||
if($count == 0) {
|
||||
$this->fields[] = $tablename.".".$name;
|
||||
} else {
|
||||
$this->fields[] = $tablename.".".$name." AS ".$cname."__".$name;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @return string the built sql query
|
||||
*/
|
||||
final public function getQuery() {
|
||||
if(empty($this->fields) || empty($this->from))
|
||||
return false;
|
||||
|
||||
// build the basic query
|
||||
$q = "SELECT ".implode(", ",$this->fields).
|
||||
" FROM ";
|
||||
foreach($this->from as $tname => $bool) {
|
||||
$str = $tname;
|
||||
if(isset($this->join[$tname]))
|
||||
$str .= " ".$this->join[$tname];
|
||||
|
||||
$a[] = $str;
|
||||
}
|
||||
$q .= implode(", ",$a);
|
||||
$this->applyInheritance();
|
||||
if( ! empty($this->where))
|
||||
$q .= " WHERE ".implode(" && ",$this->where);
|
||||
|
||||
if( ! empty($this->orderby))
|
||||
$q .= " ORDER BY ".implode(", ",$this->orderby);
|
||||
|
||||
return $q;
|
||||
}
|
||||
/**
|
||||
* sql delete for mysql
|
||||
*/
|
||||
final public function buildDelete() {
|
||||
if(empty($this->fields) || empty($this->from))
|
||||
return false;
|
||||
|
||||
$a = array_merge(array_keys($this->from),$this->joined);
|
||||
$q = "DELETE ".implode(", ",$a)." FROM ";
|
||||
$a = array();
|
||||
|
||||
foreach($this->from as $tname => $bool) {
|
||||
$str = $tname;
|
||||
if(isset($this->join[$tname]))
|
||||
$str .= " ".$this->join[$tname];
|
||||
|
||||
$a[] = $str;
|
||||
}
|
||||
|
||||
$q .= implode(", ",$a);
|
||||
$this->applyInheritance();
|
||||
if( ! empty($this->where))
|
||||
$q .= " WHERE ".implode(" && ",$this->where);
|
||||
|
||||
if( ! empty($this->orderby))
|
||||
$q .= " ORDER BY ".implode(", ",$this->orderby);
|
||||
|
||||
if( ! empty($this->limit) && ! empty($this->offset))
|
||||
$q = $this->session->modifyLimitQuery($q,$this->limit,$this->offset);
|
||||
|
||||
return $q;
|
||||
}
|
||||
/**
|
||||
* applyInheritance
|
||||
* applies column aggregation inheritance to DQL query
|
||||
* @return boolean
|
||||
*/
|
||||
final public function applyInheritance() {
|
||||
if($this->inheritanceApplied)
|
||||
return false;
|
||||
|
||||
// get the inheritance maps
|
||||
$array = array();
|
||||
|
||||
foreach($this->tnames as $objTable):
|
||||
$tname = $objTable->getTableName();
|
||||
$array[$tname][] = $objTable->getInheritanceMap();
|
||||
endforeach;
|
||||
|
||||
// apply inheritance maps
|
||||
$str = "";
|
||||
$c = array();
|
||||
|
||||
foreach($array as $tname => $maps) {
|
||||
$a = array();
|
||||
foreach($maps as $map) {
|
||||
$b = array();
|
||||
foreach($map as $field=>$value) {
|
||||
$b[] = $tname.".$field = $value";
|
||||
}
|
||||
if( ! empty($b)) $a[] = implode(" && ",$b);
|
||||
}
|
||||
if( ! empty($a)) $c[] = implode(" || ",$a);
|
||||
}
|
||||
|
||||
$str .= implode(" || ",$c);
|
||||
|
||||
$this->addWhere($str);
|
||||
$this->inheritanceApplied = true;
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @param string $where
|
||||
* @return boolean
|
||||
*/
|
||||
final public function addWhere($where) {
|
||||
if(empty($where))
|
||||
return false;
|
||||
|
||||
$this->where[] = "(".$where.")";
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @param string $from from part of the query
|
||||
*/
|
||||
final public function addFrom($from) {
|
||||
$this->from[] = $from;
|
||||
}
|
||||
/**
|
||||
* getData
|
||||
* @param $key the factory name
|
||||
* @return array the data row for the specified factory
|
||||
*/
|
||||
final public function getData($key) {
|
||||
if(isset($this->data[$key]))
|
||||
return $this->data[$key];
|
||||
|
||||
return array();
|
||||
}
|
||||
/**
|
||||
* execute
|
||||
* executes the datagraph and populates Doctrine_Collections
|
||||
* @param string $params
|
||||
* @return Doctrine_Collection the root collection
|
||||
*/
|
||||
private function execute($params = array()) {
|
||||
|
||||
switch(count($this->tnames)):
|
||||
case 0:
|
||||
throw new DQLException();
|
||||
break;
|
||||
case 1:
|
||||
$query = $this->getQuery();
|
||||
|
||||
$keys = array_keys($this->tnames);
|
||||
|
||||
$name = $this->tnames[$keys[0]]->getComponentName();
|
||||
$stmt = $this->session->execute($query,$params);
|
||||
|
||||
while($data = $stmt->fetch(PDO::FETCH_ASSOC)):
|
||||
foreach($data as $key => $value):
|
||||
$e = explode("__",$key);
|
||||
if(count($e) > 1) {
|
||||
$data[$e[1]] = $value;
|
||||
} else {
|
||||
$data[$e[0]] = $value;
|
||||
}
|
||||
unset($data[$key]);
|
||||
endforeach;
|
||||
$this->data[$name][] = $data;
|
||||
endwhile;
|
||||
|
||||
return $this->getCollection($keys[0]);
|
||||
break;
|
||||
default:
|
||||
$query = $this->getQuery();
|
||||
|
||||
$keys = array_keys($this->tnames);
|
||||
$root = $keys[0];
|
||||
$stmt = $this->session->execute($query,$params);
|
||||
|
||||
$previd = array();
|
||||
|
||||
$coll = $this->getCollection($root);
|
||||
|
||||
$array = $this->parseData($stmt);
|
||||
|
||||
foreach($array as $data):
|
||||
|
||||
/**
|
||||
* remove duplicated data rows and map data into objects
|
||||
*/
|
||||
foreach($data as $key => $row):
|
||||
if(empty($row) || empty($row['id']))
|
||||
continue;
|
||||
|
||||
$key = ucwords($key);
|
||||
$name = $this->tnames[$key]->getComponentName();
|
||||
|
||||
if( ! isset($previd[$name]))
|
||||
$previd[$name] = array();
|
||||
|
||||
|
||||
if($previd[$name] !== $row) {
|
||||
$this->tnames[$name]->setData($row);
|
||||
$record = $this->tnames[$name]->getRecord();
|
||||
|
||||
if($name == $root) {
|
||||
$this->tnames[$name]->setData($row);
|
||||
$record = $this->tnames[$name]->getRecord();
|
||||
$coll->add($record);
|
||||
} else {
|
||||
$last = $coll->getLast();
|
||||
|
||||
if( ! $last->hasReference($name)) {
|
||||
$last->initReference($this->getCollection($name),$this->connectors[$name]);
|
||||
}
|
||||
$last->addReference($record);
|
||||
}
|
||||
}
|
||||
|
||||
$previd[$name] = $row;
|
||||
endforeach;
|
||||
endforeach;
|
||||
|
||||
return $coll;
|
||||
endswitch;
|
||||
}
|
||||
/**
|
||||
* parseData
|
||||
* @return array
|
||||
*/
|
||||
public function parseData(PDOStatement $stmt) {
|
||||
$array = array();
|
||||
while($data = $stmt->fetch(PDO::FETCH_ASSOC)):
|
||||
/**
|
||||
* parse the data into two-dimensional array
|
||||
*/
|
||||
foreach($data as $key => $value):
|
||||
$e = explode("__",$key);
|
||||
|
||||
if(count($e) > 1) {
|
||||
$data[$e[0]][$e[1]] = $value;
|
||||
} else {
|
||||
$data[0][$e[0]] = $value;
|
||||
}
|
||||
unset($data[$key]);
|
||||
endforeach;
|
||||
$array[] = $data;
|
||||
endwhile;
|
||||
$stmt->closeCursor();
|
||||
return $array;
|
||||
}
|
||||
/**
|
||||
* @return Doctrine_Table
|
||||
*/
|
||||
public function getTable($name) {
|
||||
return $this->tnames[$name];
|
||||
}
|
||||
/**
|
||||
* getCollection
|
||||
* @param integer $index
|
||||
*/
|
||||
private function getCollection($name) {
|
||||
switch($this->fetchModes[$name]):
|
||||
case 0:
|
||||
$coll = new Doctrine_Collection_Immediate($this,$name);
|
||||
break;
|
||||
case 1:
|
||||
$coll = new Doctrine_Collection_Batch($this,$name);
|
||||
break;
|
||||
case 2:
|
||||
$coll = new Doctrine_Collection_Lazy($this,$name);
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unknown fetchmode");
|
||||
endswitch;
|
||||
|
||||
return $coll;
|
||||
}
|
||||
/**
|
||||
* query the database with DQL (Doctrine Query Language)
|
||||
*
|
||||
* @param string $query DQL query
|
||||
* @param array $params parameters
|
||||
*/
|
||||
public function query($query,$params = array()) {
|
||||
$this->parseQuery($query);
|
||||
|
||||
if($this->aggregate) {
|
||||
$keys = array_keys($this->tnames);
|
||||
$query = $this->getQuery();
|
||||
$stmt = $this->tnames[$keys[0]]->getSession()->select($query);
|
||||
$data = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if(count($data) == 1) {
|
||||
return current($data);
|
||||
} else {
|
||||
return $data;
|
||||
}
|
||||
} else {
|
||||
return $this->execute($params);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* DQL PARSER
|
||||
*/
|
||||
final public function parseQuery($query) {
|
||||
$this->clear();
|
||||
$e = self::bracketExplode($query," ","(",")");
|
||||
|
||||
$parts = array();
|
||||
foreach($e as $k=>$part):
|
||||
switch(strtolower($part)):
|
||||
case "select":
|
||||
case "from":
|
||||
case "where":
|
||||
case "limit":
|
||||
case "offset":
|
||||
$p = $part;
|
||||
$parts[$part] = array();
|
||||
break;
|
||||
case "order":
|
||||
$p = $part;
|
||||
$i = $k+1;
|
||||
if(isset($e[$i]) && strtolower($e[$i]) == "by") {
|
||||
$parts[$part] = array();
|
||||
}
|
||||
break;
|
||||
case "by":
|
||||
continue;
|
||||
default:
|
||||
$parts[$p][] = $part;
|
||||
endswitch;
|
||||
endforeach;
|
||||
|
||||
foreach($parts as $k => $part) {
|
||||
$part = implode(" ",$part);
|
||||
switch($k):
|
||||
case "SELECT":
|
||||
$this->parseSelect($part);
|
||||
break;
|
||||
case "FROM":
|
||||
$this->parseFrom($part);
|
||||
break;
|
||||
case "WHERE":
|
||||
$this->addWhere($this->parseWhere($part));
|
||||
break;
|
||||
case "ORDER":
|
||||
$this->parseOrderBy($part);
|
||||
break;
|
||||
case "LIMIT":
|
||||
$this->limit = trim($part);
|
||||
break;
|
||||
case "OFFSET":
|
||||
$this->offset = trim($part);
|
||||
break;
|
||||
endswitch;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* DQL SELECT PARSER
|
||||
* parses the select part of the query string
|
||||
* @param string $str
|
||||
* @return void
|
||||
*/
|
||||
private function parseSelect($str) {
|
||||
$this->aggregate = true;
|
||||
foreach(explode(",",trim($str)) as $reference) {
|
||||
|
||||
$e = explode(" AS ",trim($reference));
|
||||
|
||||
$f = explode("(",$e[0]);
|
||||
$a = explode(".",$f[1]);
|
||||
$field = substr(array_pop($a),0,-1);
|
||||
|
||||
$reference = trim(implode(".",$a));
|
||||
|
||||
$objTable = $this->load($reference);
|
||||
if(isset($e[1]))
|
||||
$s = " AS $e[1]";
|
||||
|
||||
$this->fields[]= $f[0]."(".$objTable->getTableName().".$field)$s";
|
||||
|
||||
}
|
||||
}
|
||||
/**
|
||||
* DQL FROM PARSER
|
||||
* parses the from part of the query string
|
||||
|
||||
* @param string $str
|
||||
* @return void
|
||||
*/
|
||||
private function parseFrom($str) {
|
||||
foreach(explode(",",trim($str)) as $reference) {
|
||||
$reference = trim($reference);
|
||||
$e = explode("-",$reference);
|
||||
$reference = $e[0];
|
||||
$table = $this->load($reference);
|
||||
|
||||
if(isset($e[1])) {
|
||||
switch(strtolower($e[1])):
|
||||
case "i":
|
||||
case "immediate":
|
||||
$fetchmode = Doctrine::FETCH_IMMEDIATE;
|
||||
break;
|
||||
case "b":
|
||||
case "batch":
|
||||
$fetchmode = Doctrine::FETCH_BATCH;
|
||||
break;
|
||||
case "l":
|
||||
case "lazy":
|
||||
$fetchmode = Doctrine::FETCH_LAZY;
|
||||
break;
|
||||
default:
|
||||
throw new DQLException("Unknown fetchmode '$e[1]'. The availible fetchmodes are 'i', 'b' and 'l'.");
|
||||
endswitch;
|
||||
} else
|
||||
$fetchmode = $table->getAttribute(Doctrine::ATTR_FETCHMODE);
|
||||
|
||||
if( ! $this->aggregate) {
|
||||
$this->loadFields($table,$fetchmode);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* DQL ORDER BY PARSER
|
||||
* parses the order by part of the query string
|
||||
*
|
||||
* @param string $str
|
||||
* @return void
|
||||
*/
|
||||
private function parseOrderBy($str) {
|
||||
foreach(explode(",",trim($str)) as $r) {
|
||||
$r = trim($r);
|
||||
$e = explode(" ",$r);
|
||||
$a = explode(".",$e[0]);
|
||||
|
||||
if(count($a) > 1) {
|
||||
$field = array_pop($a);
|
||||
$reference = implode(".",$a);
|
||||
$name = end($a);
|
||||
$this->load($reference);
|
||||
$tname = $this->tnames[$name]->getTableName();
|
||||
|
||||
$r = $tname.".".$field;
|
||||
if(isset($e[1])) $r .= " ".$e[1];
|
||||
$this->orderby[] = $r;
|
||||
} else {
|
||||
$this->orderby[] = $r;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* DQL WHERE PARSER
|
||||
* parses the where part of the query string
|
||||
*
|
||||
*
|
||||
* @param string $str
|
||||
* @return string
|
||||
*/
|
||||
private function parseWhere($str) {
|
||||
$tmp = trim($str);
|
||||
$str = self::bracketTrim($tmp,"(",")");
|
||||
|
||||
$brackets = false;
|
||||
while($tmp != $str) {
|
||||
$brackets = true;
|
||||
$tmp = $str;
|
||||
$str = self::bracketTrim($str,"(",")");
|
||||
}
|
||||
|
||||
$parts = self::bracketExplode($str," && ","(",")");
|
||||
if(count($parts) > 1) {
|
||||
$ret = array();
|
||||
foreach($parts as $part) {
|
||||
$ret[] = $this->parseWhere($part);
|
||||
}
|
||||
$r = implode(" && ",$ret);
|
||||
} else {
|
||||
$parts = self::bracketExplode($str," || ","(",")");
|
||||
if(count($parts) > 1) {
|
||||
$ret = array();
|
||||
foreach($parts as $part) {
|
||||
$ret[] = $this->parseWhere($part);
|
||||
}
|
||||
$r = implode(" || ",$ret);
|
||||
} else {
|
||||
return $this->loadWhere($parts[0]);
|
||||
}
|
||||
}
|
||||
if($brackets)
|
||||
return "(".$r.")";
|
||||
else
|
||||
return $r;
|
||||
}
|
||||
/**
|
||||
* trims brackets
|
||||
*
|
||||
* @param string $str
|
||||
* @param string $e1 the first bracket, usually '('
|
||||
* @param string $e2 the second bracket, usually ')'
|
||||
*/
|
||||
public static function bracketTrim($str,$e1,$e2) {
|
||||
if(substr($str,0,1) == $e1 && substr($str,-1) == $e2)
|
||||
return substr($str,1,-1);
|
||||
else
|
||||
return $str;
|
||||
}
|
||||
/**
|
||||
* bracketExplode
|
||||
* usage:
|
||||
* $str = (age < 20 && age > 18) && email LIKE 'John@example.com'
|
||||
* now exploding $str with parameters $d = ' && ', $e1 = '(' and $e2 = ')'
|
||||
* would return an array:
|
||||
* array("(age < 20 && age > 18)", "email LIKE 'John@example.com'")
|
||||
*
|
||||
* @param string $str
|
||||
* @param string $d the delimeter which explodes the string
|
||||
* @param string $e1 the first bracket, usually '('
|
||||
* @param string $e2 the second bracket, usually ')'
|
||||
*
|
||||
*/
|
||||
public static function bracketExplode($str,$d,$e1,$e2) {
|
||||
$str = explode("$d",$str);
|
||||
$i = 0;
|
||||
$term = array();
|
||||
foreach($str as $key=>$val) {
|
||||
if (empty($term[$i])) {
|
||||
$term[$i] = trim($val);
|
||||
$s1 = substr_count($term[$i],"$e1");
|
||||
$s2 = substr_count($term[$i],"$e2");
|
||||
if($s1 == $s2) $i++;
|
||||
} else {
|
||||
$term[$i] .= "$d".trim($val);
|
||||
$c1 = substr_count($term[$i],"$e1");
|
||||
$c2 = substr_count($term[$i],"$e2");
|
||||
if($c1 == $c2) $i++;
|
||||
}
|
||||
}
|
||||
return $term;
|
||||
}
|
||||
/**
|
||||
* loadWhere
|
||||
*
|
||||
*/
|
||||
private function loadWhere($where) {
|
||||
$e = explode(" ",$where);
|
||||
$r = array_shift($e);
|
||||
$a = explode(".",$r);
|
||||
|
||||
if(count($a) > 1) {
|
||||
$field = array_pop($a);
|
||||
$operator = array_shift($e);
|
||||
$value = implode(" ",$e);
|
||||
$reference = implode(".",$a);
|
||||
$objTable = $this->session->getTable(end($a));
|
||||
$where = $objTable->getTableName().".".$field." ".$operator." ".$value;
|
||||
if(count($a) > 1 && isset($a[1])) {
|
||||
$root = $a[0];
|
||||
$fk = $this->tnames[$root]->getForeignKey($a[1]);
|
||||
if($fk instanceof Doctrine_Association) {
|
||||
$asf = $fk->getAssociationFactory();
|
||||
switch($fk->getType()):
|
||||
case Doctrine_Table::ONE_AGGREGATE:
|
||||
case Doctrine_Table::ONE_COMPOSITE:
|
||||
|
||||
break;
|
||||
case Doctrine_Table::MANY_AGGREGATE:
|
||||
case Doctrine_Table::MANY_COMPOSITE:
|
||||
$b = array_shift($a);
|
||||
$b = array_shift($a);
|
||||
$graph = new Doctrine_DQL_Parser($this->session);
|
||||
$graph->parseQuery("FROM $b WHERE $where");
|
||||
$where = $this->tnames[$root]->getTableName().".id IN (SELECT ".$fk->getLocal()." FROM ".$asf->getTableName()." WHERE ".$fk->getForeign()." IN (".$graph->getQuery()."))";
|
||||
break;
|
||||
endswitch;
|
||||
} else
|
||||
$this->load($reference);
|
||||
|
||||
} else
|
||||
$this->load($reference);
|
||||
}
|
||||
return $where;
|
||||
}
|
||||
/**
|
||||
* @param string $path the path of the loadable component
|
||||
* @param integer $fetchmode optional fetchmode, if not set the components default fetchmode will be used
|
||||
* @throws DQLException
|
||||
*/
|
||||
final public function load($path, $fetchmode = Doctrine::FETCH_LAZY) {
|
||||
$e = explode(".",$path);
|
||||
foreach($e as $key => $name) {
|
||||
$low = strtolower($name);
|
||||
$name = ucwords($low);
|
||||
|
||||
try {
|
||||
if($key == 0) {
|
||||
|
||||
$objTable = $this->session->getTable($name);
|
||||
if(count($e) == 1) {
|
||||
$tname = $objTable->getTableName();
|
||||
$this->from[$tname] = true;
|
||||
}
|
||||
} else {
|
||||
$fk = $objTable->getForeignKey($name);
|
||||
$tname = $objTable->getTableName();
|
||||
$next = $fk->getTable();
|
||||
$tname2 = $next->getTableName();
|
||||
|
||||
$this->connectors[$name] = $fk;
|
||||
|
||||
if($fk instanceof Doctrine_ForeignKey ||
|
||||
$fk instanceof Doctrine_LocalKey) {
|
||||
switch($fk->getType()):
|
||||
case Doctrine_Table::ONE_AGGREGATE:
|
||||
case Doctrine_Table::ONE_COMPOSITE:
|
||||
|
||||
$this->where[] = "(".$tname.".".$fk->getLocal()." = ".$tname2.".".$fk->getForeign().")";
|
||||
$this->from[$tname] = true;
|
||||
$this->from[$tname2] = true;
|
||||
break;
|
||||
case Doctrine_Table::MANY_AGGREGATE:
|
||||
case Doctrine_Table::MANY_COMPOSITE:
|
||||
$this->join[$tname] = "LEFT JOIN ".$tname2." ON ".$tname.".".$fk->getLocal()." = ".$tname2.".".$fk->getForeign();
|
||||
$this->joined[] = $tname2;
|
||||
$this->from[$tname] = true;
|
||||
break;
|
||||
endswitch;
|
||||
} elseif($fk instanceof Doctrine_Association) {
|
||||
$asf = $fk->getAssociationFactory();
|
||||
|
||||
switch($fk->getType()):
|
||||
case Doctrine_Table::ONE_AGGREGATE:
|
||||
case Doctrine_Table::ONE_COMPOSITE:
|
||||
|
||||
break;
|
||||
case Doctrine_Table::MANY_AGGREGATE:
|
||||
case Doctrine_Table::MANY_COMPOSITE:
|
||||
|
||||
//$this->addWhere("SELECT ".$fk->getLocal()." FROM ".$asf->getTableName()." WHERE ".$fk->getForeign()." IN (SELECT ".$fk->getTable()->getComponentName().")");
|
||||
$this->from[$tname] = true;
|
||||
break;
|
||||
endswitch;
|
||||
}
|
||||
|
||||
$objTable = $next;
|
||||
}
|
||||
if( ! isset($this->tnames[$name])) {
|
||||
$this->tnames[$name] = $objTable;
|
||||
}
|
||||
|
||||
} catch(Doctrine_Exception $e) {
|
||||
throw new DQLException();
|
||||
} catch(InvalidKeyException $e) {
|
||||
throw new DQLException();
|
||||
}
|
||||
}
|
||||
return $objTable;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
96
classes/DataDict.class.php
Normal file
96
classes/DataDict.class.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
class Doctrine_DataDict {
|
||||
private $table;
|
||||
public function __construct(Doctrine_Table $table) {
|
||||
$this->table = $table;
|
||||
$manager = $this->table->getSession()->getManager();
|
||||
|
||||
require_once($manager->getRoot()."/adodb-hack/adodb.inc.php");
|
||||
|
||||
$dbh = $this->table->getSession()->getDBH();
|
||||
|
||||
$this->dict = NewDataDictionary($dbh);
|
||||
}
|
||||
|
||||
public function metaColumns() {
|
||||
return $this->dict->metaColumns($this->table->getTableName());
|
||||
}
|
||||
|
||||
public function createTable() {
|
||||
foreach($this->table->getColumns() as $name => $args) {
|
||||
|
||||
$r[] = $name." ".$this->getADOType($args[0],$args[1])." ".$args[2];
|
||||
}
|
||||
$dbh = $this->table->getSession()->getDBH();
|
||||
|
||||
$r = implode(", ",$r);
|
||||
$a = $this->dict->createTableSQL($this->table->getTableName(),$r);
|
||||
|
||||
$return = true;
|
||||
foreach($a as $sql) {
|
||||
try {
|
||||
$dbh->query($sql);
|
||||
} catch(PDOException $e) {
|
||||
$return = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
/**
|
||||
* converts doctrine type to adodb type
|
||||
*
|
||||
* @param string $type column type
|
||||
* @param integer $length column length
|
||||
*/
|
||||
public function getADOType($type,$length) {
|
||||
switch($type):
|
||||
case "string":
|
||||
case "s":
|
||||
if($length < 255)
|
||||
return "C($length)";
|
||||
elseif($length < 4000)
|
||||
return "X";
|
||||
break;
|
||||
case "mbstring":
|
||||
if($length < 255)
|
||||
return "C2($length)";
|
||||
|
||||
return "X2";
|
||||
case "clob":
|
||||
return "XL";
|
||||
break;
|
||||
case "float":
|
||||
case "f":
|
||||
case "double":
|
||||
return "F";
|
||||
break;
|
||||
case "timestamp":
|
||||
case "t":
|
||||
return "T";
|
||||
break;
|
||||
case "boolean":
|
||||
case "bool":
|
||||
return "L";
|
||||
break;
|
||||
case "integer":
|
||||
case "int":
|
||||
case "i":
|
||||
if(empty($length))
|
||||
return "I8";
|
||||
elseif($length < 4)
|
||||
return "I1";
|
||||
elseif($length < 6)
|
||||
return "I2";
|
||||
elseif($length < 10)
|
||||
return "I4";
|
||||
elseif($length <= 20)
|
||||
return "I8";
|
||||
else
|
||||
throw new Doctrine_Exception("Too long integer (max length is 20).");
|
||||
|
||||
break;
|
||||
endswitch;
|
||||
}
|
||||
}
|
||||
?>
|
151
classes/Debugger.class.php
Normal file
151
classes/Debugger.class.php
Normal file
@ -0,0 +1,151 @@
|
||||
<?php
|
||||
require_once("EventListener.class.php");
|
||||
|
||||
class Doctrine_DebugMessage {
|
||||
private $code;
|
||||
private $object;
|
||||
public function __construct($object, $code) {
|
||||
$this->object = $object;
|
||||
$this->code = $code;
|
||||
}
|
||||
final public function getCode() {
|
||||
return $this->code;
|
||||
}
|
||||
final public function getObject() {
|
||||
return $this->object;
|
||||
}
|
||||
}
|
||||
class Doctrine_Debugger extends Doctrine_EventListener {
|
||||
const EVENT_LOAD = 1;
|
||||
const EVENT_PRELOAD = 2;
|
||||
const EVENT_SLEEP = 3;
|
||||
const EVENT_WAKEUP = 4;
|
||||
const EVENT_UPDATE = 5;
|
||||
const EVENT_PREUPDATE = 6;
|
||||
const EVENT_CREATE = 7;
|
||||
const EVENT_PRECREATE = 8;
|
||||
|
||||
const EVENT_SAVE = 9;
|
||||
const EVENT_PRESAVE = 10;
|
||||
const EVENT_INSERT = 11;
|
||||
const EVENT_PREINSERT = 12;
|
||||
const EVENT_DELETE = 13;
|
||||
const EVENT_PREDELETE = 14;
|
||||
const EVENT_EVICT = 15;
|
||||
const EVENT_PREEVICT = 16;
|
||||
const EVENT_CLOSE = 17;
|
||||
const EVENT_PRECLOSE = 18;
|
||||
|
||||
const EVENT_OPEN = 19;
|
||||
const EVENT_COMMIT = 20;
|
||||
const EVENT_PRECOMMIT = 21;
|
||||
const EVENT_ROLLBACK = 22;
|
||||
const EVENT_PREROLLBACK = 23;
|
||||
const EVENT_BEGIN = 24;
|
||||
const EVENT_PREBEGIN = 25;
|
||||
const EVENT_COLLDELETE = 26;
|
||||
const EVENT_PRECOLLDELETE = 27;
|
||||
private $debug;
|
||||
|
||||
public function getMessages() {
|
||||
return $this->debug;
|
||||
}
|
||||
|
||||
|
||||
public function onLoad(Doctrine_Record $record) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($record,self::EVENT_LOAD);
|
||||
}
|
||||
public function onPreLoad(Doctrine_Record $record) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($record,self::EVENT_PRELOAD);
|
||||
}
|
||||
|
||||
public function onSleep(Doctrine_Record $record) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($record,self::EVENT_SLEEP);
|
||||
}
|
||||
|
||||
public function onWakeUp(Doctrine_Record $record) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($record,self::EVENT_WAKEUP);
|
||||
}
|
||||
|
||||
public function onUpdate(Doctrine_Record $record) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($record,self::EVENT_UPDATE);
|
||||
}
|
||||
public function onPreUpdate(Doctrine_Record $record) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($record,self::EVENT_PREUPDATE);
|
||||
}
|
||||
|
||||
public function onCreate(Doctrine_Record $record) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($record,self::EVENT_CREATE);
|
||||
}
|
||||
public function onPreCreate(Doctrine_Record $record) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($record,self::EVENT_PRECREATE);
|
||||
}
|
||||
|
||||
public function onSave(Doctrine_Record $record) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($record,self::EVENT_SAVE);
|
||||
}
|
||||
public function onPreSave(Doctrine_Record $record) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($record,self::EVENT_PRESAVE);
|
||||
}
|
||||
|
||||
public function onInsert(Doctrine_Record $record) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($record,self::EVENT_INSERT);
|
||||
}
|
||||
public function onPreInsert(Doctrine_Record $record) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($record,self::EVENT_PREINSERT);
|
||||
}
|
||||
|
||||
public function onDelete(Doctrine_Record $record) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($record,self::EVENT_DELETE);
|
||||
}
|
||||
public function onPreDelete(Doctrine_Record $record) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($record,self::EVENT_PREDELETE);
|
||||
}
|
||||
|
||||
public function onEvict(Doctrine_Record $record) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($record,self::EVENT_EVICT);
|
||||
}
|
||||
public function onPreEvict(Doctrine_Record $record) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($record,self::EVENT_PREEVICT);
|
||||
}
|
||||
|
||||
public function onClose(Doctrine_Session $session) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($session,self::EVENT_CLOSE);
|
||||
}
|
||||
public function onPreClose(Doctrine_Session $session) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($session,self::EVENT_PRECLOSE);
|
||||
}
|
||||
|
||||
public function onOpen(Doctrine_Session $session) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($session,self::EVENT_OPEN);
|
||||
}
|
||||
|
||||
public function onTransactionCommit(Doctrine_Session $session) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($session,self::EVENT_COMMIT);
|
||||
}
|
||||
public function onPreTransactionCommit(Doctrine_Session $session) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($session,self::EVENT_PRECOMMIT);
|
||||
}
|
||||
|
||||
public function onTransactionRollback(Doctrine_Session $session) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($session,self::EVENT_ROLLBACK);
|
||||
}
|
||||
public function onPreTransactionRollback(Doctrine_Session $session) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($session,self::EVENT_PREROLLBACK);
|
||||
}
|
||||
|
||||
public function onTransactionBegin(Doctrine_Session $session) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($session,self::EVENT_BEGIN);
|
||||
}
|
||||
public function onPreTransactionBegin(Doctrine_Session $session) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($session,self::EVENT_PREBEGIN);
|
||||
}
|
||||
|
||||
public function onCollectionDelete(Doctrine_Collection $collection) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($collection,self::EVENT_COLLDELETE);
|
||||
}
|
||||
public function onPreCollectionDelete(Doctrine_Collection $collection) {
|
||||
$this->debug[] = new Doctrine_DebugMessage($collection,self::EVENT_PRECOLLDELETE);
|
||||
}
|
||||
}
|
||||
?>
|
268
classes/Doctrine.class.php
Normal file
268
classes/Doctrine.class.php
Normal file
@ -0,0 +1,268 @@
|
||||
<?php
|
||||
require_once("Exception.class.php");
|
||||
/**
|
||||
* Doctrine
|
||||
* the base class of Doctrine framework
|
||||
*/
|
||||
final class Doctrine {
|
||||
/**
|
||||
* ERROR MODE CONSTANTS
|
||||
*/
|
||||
|
||||
/**
|
||||
* NO PRIMARY KEY COLUMN ERROR
|
||||
* no primary key column found error code
|
||||
*/
|
||||
const ERR_NO_PK = 0;
|
||||
/**
|
||||
* PRIMARY KEY MISMATCH ERROR
|
||||
* this error code is used when user uses factory refresh for a
|
||||
* given Doctrine_Record and the old primary key doesn't match the new one
|
||||
*/
|
||||
const ERR_REFRESH = 1;
|
||||
/**
|
||||
* FIND ERROR
|
||||
* this code used when for example Doctrine_Table::find() is called and
|
||||
* a Data Access Object is not found
|
||||
*/
|
||||
const ERR_FIND = 2;
|
||||
/**
|
||||
* TABLE NOT FOUND ERROR
|
||||
* this error code is used when user tries to initialize
|
||||
* a table and there is no database table for this factory
|
||||
*/
|
||||
const ERR_NOSUCH_TABLE = 3;
|
||||
/**
|
||||
* NAMING ERROR
|
||||
* this code is used when user defined Doctrine_Table is badly named
|
||||
*/
|
||||
const ERR_NAMING = 5;
|
||||
/**
|
||||
* TABLE INSTANCE ERROR
|
||||
* this code is used when user tries to initialize
|
||||
* a table that is already initialized
|
||||
*/
|
||||
const ERR_TABLE_INSTANCE = 6;
|
||||
/**
|
||||
* NO OPEN SESSIONS ERROR
|
||||
* error code which is used when user tries to get
|
||||
* current session are there are no sessions open
|
||||
*/
|
||||
const ERR_NO_SESSIONS = 7;
|
||||
/**
|
||||
* MAPPING ERROR
|
||||
* if there is something wrong with mapping logic
|
||||
* this error code is used
|
||||
*/
|
||||
const ERR_MAPPING = 8;
|
||||
|
||||
/**
|
||||
* ATTRIBUTE CONSTANTS
|
||||
*/
|
||||
|
||||
/**
|
||||
* event listener attribute
|
||||
*/
|
||||
const ATTR_LISTENER = 1;
|
||||
/**
|
||||
* fetchmode attribute
|
||||
*/
|
||||
const ATTR_FETCHMODE = 2;
|
||||
/**
|
||||
* cache directory attribute
|
||||
*/
|
||||
const ATTR_CACHE_DIR = 3;
|
||||
/**
|
||||
* cache time to live attribute
|
||||
*/
|
||||
const ATTR_CACHE_TTL = 4;
|
||||
/**
|
||||
* cache size attribute
|
||||
*/
|
||||
const ATTR_CACHE_SIZE = 5;
|
||||
/**
|
||||
* cache slam defense probability
|
||||
*/
|
||||
const ATTR_CACHE_SLAM = 6;
|
||||
/**
|
||||
* cache container attribute
|
||||
*/
|
||||
const ATTR_CACHE = 7;
|
||||
/**
|
||||
* batch size attribute
|
||||
*/
|
||||
const ATTR_BATCH_SIZE = 8;
|
||||
/**
|
||||
* primary key columns attribute
|
||||
*/
|
||||
const ATTR_PK_COLUMNS = 9;
|
||||
/**
|
||||
* primary key type attribute
|
||||
*/
|
||||
const ATTR_PK_TYPE = 10;
|
||||
/**
|
||||
* locking attribute
|
||||
*/
|
||||
const ATTR_LOCKMODE = 11;
|
||||
/**
|
||||
* validatate attribute
|
||||
*/
|
||||
const ATTR_VLD = 12;
|
||||
/**
|
||||
* name prefix attribute
|
||||
*/
|
||||
const ATTR_NAME_PREFIX = 13;
|
||||
/**
|
||||
* create tables attribute
|
||||
*/
|
||||
const ATTR_CREATE_TABLES = 14;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* CACHE CONSTANTS
|
||||
*/
|
||||
|
||||
/**
|
||||
* file cache constant
|
||||
*/
|
||||
const CACHE_FILE = 0;
|
||||
/**
|
||||
* constant for disabling the caching
|
||||
*/
|
||||
const CACHE_NONE = 1;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* FETCHMODE CONSTANTS
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMMEDIATE FETCHING
|
||||
* mode for immediate fetching
|
||||
*/
|
||||
const FETCH_IMMEDIATE = 0;
|
||||
/**
|
||||
* BATCH FETCHING
|
||||
* mode for batch fetching
|
||||
*/
|
||||
const FETCH_BATCH = 1;
|
||||
/**
|
||||
* LAZY FETCHING
|
||||
* mode for lazy fetching
|
||||
*/
|
||||
const FETCH_LAZY = 2;
|
||||
|
||||
/**
|
||||
* LOCKMODE CONSTANTS
|
||||
*/
|
||||
|
||||
/**
|
||||
* mode for optimistic locking
|
||||
*/
|
||||
const LOCK_OPTIMISTIC = 0;
|
||||
/**
|
||||
* mode for pessimistic locking
|
||||
*/
|
||||
const LOCK_PESSIMISTIC = 1;
|
||||
|
||||
/**
|
||||
* PRIMARY KEY TYPE CONSTANTS
|
||||
*/
|
||||
|
||||
/**
|
||||
* auto-incremented/(sequence updated) primary key
|
||||
*/
|
||||
const INCREMENT_KEY = 0;
|
||||
/**
|
||||
* unique key
|
||||
*/
|
||||
const UNIQUE_KEY = 1;
|
||||
|
||||
|
||||
/**
|
||||
* @var string $path doctrine root directory
|
||||
*/
|
||||
private static $path;
|
||||
|
||||
public static function getPath() {
|
||||
if(! self::$path)
|
||||
self::$path = dirname(__FILE__);
|
||||
|
||||
return self::$path;
|
||||
}
|
||||
/**
|
||||
* loads all runtime classes
|
||||
*/
|
||||
public static function loadAll() {
|
||||
if(! self::$path)
|
||||
self::$path = dirname(__FILE__);
|
||||
|
||||
$dir = dir(self::$path);
|
||||
$a = array();
|
||||
while (false !== ($entry = $dir->read())) {
|
||||
switch($entry):
|
||||
case ".":
|
||||
case "..":
|
||||
break;
|
||||
case "Cache":
|
||||
case "Record":
|
||||
case "Collection":
|
||||
case "Table":
|
||||
case "Validator":
|
||||
case "Exception":
|
||||
case "Session":
|
||||
case "DQL":
|
||||
$a[] = self::$path.DIRECTORY_SEPARATOR.$entry;
|
||||
break;
|
||||
default:
|
||||
if(is_file(self::$path.DIRECTORY_SEPARATOR.$entry)) {
|
||||
require_once($entry);
|
||||
}
|
||||
endswitch;
|
||||
}
|
||||
foreach($a as $dirname) {
|
||||
$dir = dir($dirname);
|
||||
$path = $dirname.DIRECTORY_SEPARATOR;
|
||||
while (false !== ($entry = $dir->read())) {
|
||||
if(is_file($path.$entry)) {
|
||||
require_once($path.$entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* simple autoload function
|
||||
*/
|
||||
public static function autoload($classname) {
|
||||
if(! self::$path)
|
||||
self::$path = dirname(__FILE__);
|
||||
|
||||
$e = explode("_",$classname);
|
||||
|
||||
if($e[0] != "Doctrine")
|
||||
return false;
|
||||
|
||||
if(end($e) != "Exception") {
|
||||
if(count($e) > 2) {
|
||||
array_shift($e);
|
||||
$dir = array_shift($e);
|
||||
$class = self::$path.DIRECTORY_SEPARATOR.$dir.DIRECTORY_SEPARATOR.implode('',$e).".class.php";
|
||||
} elseif(count($e) > 1) {
|
||||
$class = self::$path.DIRECTORY_SEPARATOR.$e[1].".class.php";
|
||||
} else
|
||||
return false;
|
||||
} else {
|
||||
$class = self::$path.DIRECTORY_SEPARATOR."Exception".DIRECTORY_SEPARATOR.$e[1].".class.php";
|
||||
}
|
||||
|
||||
if( ! file_exists($class)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
require_once($class);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
?>
|
124
classes/EventListener.class.php
Normal file
124
classes/EventListener.class.php
Normal file
@ -0,0 +1,124 @@
|
||||
<?php
|
||||
/**
|
||||
* interface for event listening, forces all classes that extend
|
||||
* Doctrine_EventListener to have the same method arguments as their parent
|
||||
*/
|
||||
interface iDoctrine_EventListener {
|
||||
|
||||
public function onLoad(Doctrine_Record $record);
|
||||
public function onPreLoad(Doctrine_Record $record);
|
||||
|
||||
public function onUpdate(Doctrine_Record $record);
|
||||
public function onPreUpdate(Doctrine_Record $record);
|
||||
|
||||
public function onCreate(Doctrine_Record $record);
|
||||
public function onPreCreate(Doctrine_Record $record);
|
||||
|
||||
public function onSave(Doctrine_Record $record);
|
||||
public function onPreSave(Doctrine_Record $record);
|
||||
|
||||
public function onInsert(Doctrine_Record $record);
|
||||
public function onPreInsert(Doctrine_Record $record);
|
||||
|
||||
public function onDelete(Doctrine_Record $record);
|
||||
public function onPreDelete(Doctrine_Record $record);
|
||||
|
||||
public function onEvict(Doctrine_Record $record);
|
||||
public function onPreEvict(Doctrine_Record $record);
|
||||
|
||||
public function onSaveCascade(Doctrine_Record $record);
|
||||
public function onPreSaveCascade(Doctrine_Record $record);
|
||||
|
||||
public function onDeleteCascade(Doctrine_Record $record);
|
||||
public function onPreDeleteCascade(Doctrine_Record $record);
|
||||
|
||||
public function onSleep(Doctrine_Record $record);
|
||||
|
||||
public function onWakeUp(Doctrine_Record $record);
|
||||
|
||||
public function onClose(Doctrine_Session $session);
|
||||
public function onPreClose(Doctrine_Session $session);
|
||||
|
||||
public function onOpen(Doctrine_Session $session);
|
||||
|
||||
public function onTransactionCommit(Doctrine_Session $session);
|
||||
public function onPreTransactionCommit(Doctrine_Session $session);
|
||||
|
||||
public function onTransactionRollback(Doctrine_Session $session);
|
||||
public function onPreTransactionRollback(Doctrine_Session $session);
|
||||
|
||||
public function onTransactionBegin(Doctrine_Session $session);
|
||||
public function onPreTransactionBegin(Doctrine_Session $session);
|
||||
|
||||
public function onCollectionDelete(Doctrine_Collection $collection);
|
||||
public function onPreCollectionDelete(Doctrine_Collection $collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Doctrine_EventListener all event listeners extend this base class
|
||||
* the empty methods allow child classes to only implement the methods they need to implement
|
||||
*
|
||||
*
|
||||
* @author Konsta Vesterinen
|
||||
* @package Doctrine ORM
|
||||
* @url www.phpdoctrine.com
|
||||
* @license LGPL
|
||||
* @version 1.0 alpha
|
||||
*
|
||||
*/
|
||||
abstract class Doctrine_EventListener implements iDoctrine_EventListener {
|
||||
|
||||
public function onLoad(Doctrine_Record $record) { }
|
||||
public function onPreLoad(Doctrine_Record $record) { }
|
||||
|
||||
public function onSleep(Doctrine_Record $record) { }
|
||||
|
||||
public function onWakeUp(Doctrine_Record $record) { }
|
||||
|
||||
public function onUpdate(Doctrine_Record $record) { }
|
||||
public function onPreUpdate(Doctrine_Record $record) { }
|
||||
|
||||
public function onCreate(Doctrine_Record $record) { }
|
||||
public function onPreCreate(Doctrine_Record $record) { }
|
||||
|
||||
public function onSave(Doctrine_Record $record) { }
|
||||
public function onPreSave(Doctrine_Record $record) { }
|
||||
|
||||
public function onInsert(Doctrine_Record $record) { }
|
||||
public function onPreInsert(Doctrine_Record $record) { }
|
||||
|
||||
public function onDelete(Doctrine_Record $record) { }
|
||||
public function onPreDelete(Doctrine_Record $record) { }
|
||||
|
||||
public function onEvict(Doctrine_Record $record) { }
|
||||
public function onPreEvict(Doctrine_Record $record) { }
|
||||
|
||||
public function onSaveCascade(Doctrine_Record $record) { }
|
||||
public function onPreSaveCascade(Doctrine_Record $record) { }
|
||||
|
||||
public function onDeleteCascade(Doctrine_Record $record) { }
|
||||
public function onPreDeleteCascade(Doctrine_Record $record) { }
|
||||
|
||||
public function onClose(Doctrine_Session $session) { }
|
||||
public function onPreClose(Doctrine_Session $session) { }
|
||||
|
||||
public function onOpen(Doctrine_Session $session) { }
|
||||
|
||||
public function onTransactionCommit(Doctrine_Session $session) { }
|
||||
public function onPreTransactionCommit(Doctrine_Session $session) { }
|
||||
|
||||
public function onTransactionRollback(Doctrine_Session $session) { }
|
||||
public function onPreTransactionRollback(Doctrine_Session $session) { }
|
||||
|
||||
public function onTransactionBegin(Doctrine_Session $session) { }
|
||||
public function onPreTransactionBegin(Doctrine_Session $session) { }
|
||||
|
||||
public function onCollectionDelete(Doctrine_Collection $collection) { }
|
||||
public function onPreCollectionDelete(Doctrine_Collection $collection) { }
|
||||
}
|
||||
/**
|
||||
* an emtpy listener all components use this by default
|
||||
*/
|
||||
class EmptyEventListener extends Doctrine_EventListener { }
|
||||
|
||||
?>
|
6
classes/Exception.class.php
Normal file
6
classes/Exception.class.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
class InvalidKeyException extends Exception { }
|
||||
class InvalidTypeException extends Exception { }
|
||||
class Doctrine_Exception extends Exception { }
|
||||
class DQLException extends Doctrine_Exception { }
|
||||
?>
|
10
classes/Exception/Find.class.php
Normal file
10
classes/Exception/Find.class.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
/**
|
||||
* thrown when user tries to find a Doctrine_Record for given primary key and that object is not found
|
||||
*/
|
||||
class Doctrine_Find_Exception extends Doctrine_Exception {
|
||||
public function __construct() {
|
||||
parent::__construct("Couldn't find Data Access Object.",Doctrine::ERR_FIND);
|
||||
}
|
||||
}
|
||||
?>
|
10
classes/Exception/Mapping.class.php
Normal file
10
classes/Exception/Mapping.class.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
/**
|
||||
* thrown when user tries to get a foreign key object but the mapping is not done right
|
||||
*/
|
||||
class Doctrine_Mapping_Exception extends Doctrine_Exception {
|
||||
public function __construct() {
|
||||
parent::__construct("An error occured in the mapping logic.",Doctrine::ERR_MAPPING);
|
||||
}
|
||||
}
|
||||
?>
|
11
classes/Exception/Naming.class.php
Normal file
11
classes/Exception/Naming.class.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* thrown when user defined Doctrine_Table is badly named
|
||||
*/
|
||||
class Doctrine_Naming_Exception extends Doctrine_Exception {
|
||||
public function __construct() {
|
||||
parent::__construct("Badly named Doctrine_Table. Each Doctrine_Table
|
||||
must be in format [Name]Table.", Doctrine::ERR_NAMING);
|
||||
}
|
||||
}
|
||||
?>
|
10
classes/Exception/PrimaryKey.class.php
Normal file
10
classes/Exception/PrimaryKey.class.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
/**
|
||||
* thrown when Doctrine_Record is loaded and there is no primary key field
|
||||
*/
|
||||
class Doctrine_PrimaryKey_Exception extends Doctrine_Exception {
|
||||
public function __construct() {
|
||||
parent::__construct("No primary key column found. Each data set must have primary key column.", Doctrine::ERR_NO_PK);
|
||||
}
|
||||
}
|
||||
?>
|
11
classes/Exception/Refresh.class.php
Normal file
11
classes/Exception/Refresh.class.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* thrown when Doctrine_Record is refreshed and the refreshed primary key doens't match the old one
|
||||
*/
|
||||
class Doctrine_Refresh_Exception extends Doctrine_Exception {
|
||||
public function __construct() {
|
||||
parent::__construct("The refreshed primary key doesn't match the
|
||||
one in the record memory.", Doctrine::ERR_REFRESH);
|
||||
}
|
||||
}
|
||||
?>
|
12
classes/Exception/Session.class.php
Normal file
12
classes/Exception/Session.class.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* thrown when user tries to get the current
|
||||
* session and there are no open sessions
|
||||
*/
|
||||
class Doctrine_Session_Exception extends Doctrine_Exception {
|
||||
public function __construct() {
|
||||
parent::__construct("There are no opened sessions. Use
|
||||
Doctrine_Manager::getInstance()->openSession() to open a new session.",Doctrine::ERR_NO_SESSIONS);
|
||||
}
|
||||
}
|
||||
?>
|
13
classes/Exception/Table.class.php
Normal file
13
classes/Exception/Table.class.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
/**
|
||||
* thrown when user tries to initialize a new instance of Doctrine_Table,
|
||||
* while there already exists an instance of that table
|
||||
*/
|
||||
class Doctrine_Table_Exception extends Doctrine_Exception {
|
||||
public function __construct() {
|
||||
parent::__construct("Couldn't initialize table. One instance of this
|
||||
tabke already exists. Always use Doctrine_Session::getTable(\$name)
|
||||
to get on instance of a Doctrine_Table.",Doctrine::ERR_TABLE_INSTANCE);
|
||||
}
|
||||
}
|
||||
?>
|
11
classes/Exception/Validator.class.php
Normal file
11
classes/Exception/Validator.class.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
class Doctrine_Validator_Exception extends Doctrine_Exception {
|
||||
private $validator;
|
||||
public function __construct(Doctrine_Validator $validator) {
|
||||
$this->validator = $validator;
|
||||
}
|
||||
public function getErrorStack() {
|
||||
return $this->validator->getErrorStack();
|
||||
}
|
||||
}
|
||||
?>
|
6
classes/ForeignKey.class.php
Normal file
6
classes/ForeignKey.class.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Foreign Key
|
||||
*/
|
||||
class Doctrine_ForeignKey extends Doctrine_Relation { }
|
||||
?>
|
22
classes/FormBuilder.class.php
Normal file
22
classes/FormBuilder.class.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* Doctrine_Form_Builder
|
||||
*/
|
||||
class Doctrine_Form_Builder {
|
||||
public static function buildForm(Doctrine_Record $record) {
|
||||
|
||||
}
|
||||
}
|
||||
class Doctrine_Element {
|
||||
private $attributes = array();
|
||||
private $data;
|
||||
|
||||
public function toHtml() {
|
||||
return "<".$this->name.">"."</>";
|
||||
}
|
||||
}
|
||||
class InputElement {
|
||||
private $attributes = array();
|
||||
|
||||
}
|
||||
?>
|
140
classes/Lib.php
Normal file
140
classes/Lib.php
Normal file
@ -0,0 +1,140 @@
|
||||
<?php
|
||||
class Doctrine_Lib {
|
||||
/**
|
||||
* @param integer $state the state of record
|
||||
* @see Doctrine_Record::STATE_* constants
|
||||
* @return string string representation of given state
|
||||
*/
|
||||
public static function getRecordStateAsString($state) {
|
||||
switch($state):
|
||||
case Doctrine_Record::STATE_PROXY:
|
||||
return "proxy";
|
||||
break;
|
||||
case Doctrine_Record::STATE_CLEAN:
|
||||
return "persistent clean";
|
||||
break;
|
||||
case Doctrine_Record::STATE_DIRTY:
|
||||
return "persistent dirty";
|
||||
break;
|
||||
case Doctrine_Record::STATE_TDIRTY:
|
||||
return "transient dirty";
|
||||
break;
|
||||
case Doctrine_Record::STATE_TCLEAN:
|
||||
return "transient clean";
|
||||
break;
|
||||
endswitch;
|
||||
}
|
||||
/**
|
||||
* returns a string representation of Doctrine_Record object
|
||||
* @param Doctrine_Record $record
|
||||
* @return string
|
||||
*/
|
||||
public function getRecordAsString(Doctrine_Record $record) {
|
||||
$r[] = "<pre>";
|
||||
$r[] = "Component : ".$record->getTable()->getComponentName();
|
||||
$r[] = "ID : ".$record->getID();
|
||||
$r[] = "References : ".count($record->getReferences());
|
||||
$r[] = "State : ".Doctrine_Lib::getRecordStateAsString($record->getState());
|
||||
$r[] = "OID : ".$record->getOID();
|
||||
$r[] = "</pre>";
|
||||
return implode("\n",$r)."<br />";
|
||||
}
|
||||
/**
|
||||
* getStateAsString
|
||||
* returns a given session state as string
|
||||
* @param integer $state session state
|
||||
*/
|
||||
public static function getSessionStateAsString($state) {
|
||||
switch($state):
|
||||
case Doctrine_Session::STATE_OPEN:
|
||||
return "open";
|
||||
break;
|
||||
case Doctrine_Session::STATE_CLOSED:
|
||||
return "closed";
|
||||
break;
|
||||
case Doctrine_Session::STATE_BUSY:
|
||||
return "busy";
|
||||
break;
|
||||
case Doctrine_Session::STATE_ACTIVE:
|
||||
return "active";
|
||||
break;
|
||||
endswitch;
|
||||
}
|
||||
/**
|
||||
* returns a string representation of Doctrine_Session object
|
||||
* @param Doctrine_Session $session
|
||||
* @return string
|
||||
*/
|
||||
public function getSessionAsString(Doctrine_Session $session) {
|
||||
$r[] = "<pre>";
|
||||
$r[] = "Doctrine_Session object";
|
||||
$r[] = "State : ".Doctrine_Session::getStateAsString($session->getState());
|
||||
$r[] = "Open Transactions : ".$session->getTransactionLevel();
|
||||
$r[] = "Open Factories : ".$session->count();
|
||||
$sum = 0;
|
||||
$rsum = 0;
|
||||
$csum = 0;
|
||||
foreach($session->getTables() as $objTable) {
|
||||
if($objTable->getCache() instanceof Doctrine_Cache_File) {
|
||||
$sum += array_sum($objTable->getCache()->getStats());
|
||||
$rsum += $objTable->getRepository()->count();
|
||||
$csum += $objTable->getCache()->count();
|
||||
}
|
||||
}
|
||||
$r[] = "Cache Hits : ".$sum." hits ";
|
||||
$r[] = "Cache : ".$csum." objects ";
|
||||
|
||||
$r[] = "Repositories : ".$rsum." objects ";
|
||||
$queries = false;
|
||||
if($session->getDBH() instanceof Doctrine_DB) {
|
||||
$handler = "Doctrine Database Handler";
|
||||
$queries = count($this->dbh->getQueries());
|
||||
$sum = array_sum($this->dbh->getExecTimes());
|
||||
} elseif($this->dbh instanceof PDO) {
|
||||
$handler = "PHP Native PDO Driver";
|
||||
} else
|
||||
$handler = "Unknown Database Handler";
|
||||
|
||||
$r[] = "DB Handler : ".$handler;
|
||||
if($queries) {
|
||||
$r[] = "Executed Queries : ".$queries;
|
||||
$r[] = "Sum of Exec Times : ".$sum;
|
||||
}
|
||||
|
||||
$r[] = "</pre>";
|
||||
return implode("\n",$r)."<br>";
|
||||
}
|
||||
/**
|
||||
* returns a string representation of Doctrine_Table object
|
||||
* @param Doctrine_Table $table
|
||||
* @return string
|
||||
*/
|
||||
public function getTableAsString(Doctrine_Table $table) {
|
||||
$r[] = "<pre>";
|
||||
$r[] = "Component : ".$this->getComponentName();
|
||||
$r[] = "Table : ".$this->getTableName();
|
||||
$r[] = "Repository : ".$this->getRepository()->count()." objects";
|
||||
if($this->cache instanceof Doctrine_Cache_File) {
|
||||
$r[] = "Cache : ".$this->getCache()->count()." objects";
|
||||
$r[] = "Cache hits : ".array_sum($this->getCache()->getStats())." hits";
|
||||
}
|
||||
$r[] = "</pre>";
|
||||
return implode("\n",$r)."<br>";
|
||||
}
|
||||
/**
|
||||
* returns a string representation of Doctrine_Collection object
|
||||
* @param Doctrine_Collection $collection
|
||||
* @return string
|
||||
*/
|
||||
public function getCollectionAsString(Doctrine_Collection $collection) {
|
||||
$r[] = "<pre>";
|
||||
$r[] = get_class($collection);
|
||||
|
||||
foreach($collection as $key => $record) {
|
||||
$r[] = "Key : ".$key." ID : ".$record->getID();
|
||||
}
|
||||
$r[] = "</pre>";
|
||||
return implode("\n",$r);
|
||||
}
|
||||
}
|
||||
?>
|
6
classes/LocalKey.class.php
Normal file
6
classes/LocalKey.class.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Local Key
|
||||
*/
|
||||
class Doctrine_LocalKey extends Doctrine_Relation { }
|
||||
?>
|
207
classes/Manager.class.php
Normal file
207
classes/Manager.class.php
Normal file
@ -0,0 +1,207 @@
|
||||
<?php
|
||||
require_once("Configurable.class.php");
|
||||
require_once("EventListener.class.php");
|
||||
/**
|
||||
* @author Konsta Vesterinen
|
||||
* @package Doctrine ORM
|
||||
* @url www.phpdoctrine.com
|
||||
* @license LGPL
|
||||
* @version 1.0 alpha
|
||||
*/
|
||||
class Doctrine_Manager extends Doctrine_Configurable implements Countable, IteratorAggregate {
|
||||
/**
|
||||
* @var array $session an array containing all the opened sessions
|
||||
*/
|
||||
private $sessions = array();
|
||||
/**
|
||||
* @var integer $index
|
||||
*/
|
||||
private $index = 0;
|
||||
/**
|
||||
* @var integer $currIndex
|
||||
*/
|
||||
private $currIndex = 0;
|
||||
/**
|
||||
* @var string $root
|
||||
*/
|
||||
private $root;
|
||||
|
||||
|
||||
/**
|
||||
* constructor
|
||||
*/
|
||||
private function __construct() {
|
||||
$this->root = dirname(__FILE__);
|
||||
}
|
||||
/**
|
||||
* setDefaultAttributes
|
||||
*/
|
||||
final public function setDefaultAttributes() {
|
||||
static $init = false;
|
||||
if( ! $init) {
|
||||
$init = true;
|
||||
$attributes = array(
|
||||
Doctrine::ATTR_CACHE_DIR => "%ROOT%".DIRECTORY_SEPARATOR."cachedir",
|
||||
Doctrine::ATTR_FETCHMODE => Doctrine::FETCH_LAZY,
|
||||
Doctrine::ATTR_CACHE_TTL => 100,
|
||||
Doctrine::ATTR_CACHE_SIZE => 100,
|
||||
Doctrine::ATTR_CACHE => Doctrine::CACHE_FILE,
|
||||
Doctrine::ATTR_BATCH_SIZE => 5,
|
||||
Doctrine::ATTR_LISTENER => new EmptyEventListener(),
|
||||
Doctrine::ATTR_PK_COLUMNS => array("id"),
|
||||
Doctrine::ATTR_PK_TYPE => Doctrine::INCREMENT_KEY,
|
||||
Doctrine::ATTR_LOCKMODE => 1,
|
||||
Doctrine::ATTR_VLD => false,
|
||||
Doctrine::ATTR_CREATE_TABLES => true
|
||||
);
|
||||
foreach($attributes as $attribute => $value) {
|
||||
$old = $this->getAttribute($attribute);
|
||||
if($old === null)
|
||||
$this->setAttribute($attribute,$value);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @return string the root directory of Doctrine
|
||||
*/
|
||||
final public function getRoot() {
|
||||
return $this->root;
|
||||
}
|
||||
/**
|
||||
* getInstance this class uses the singleton pattern
|
||||
*/
|
||||
final public static function getInstance() {
|
||||
static $instance;
|
||||
if( ! isset($instance))
|
||||
$instance = new Doctrine_Manager();
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* openSession open a new session and save it to Doctrine_Manager->sessions
|
||||
* @param PDO $pdo PDO database driver
|
||||
* @param string $name name of the session, if empty numeric key is used
|
||||
* @return Doctrine_Session the opened session object
|
||||
*/
|
||||
final public function openSession(PDO $pdo, $name = null) {
|
||||
// initialize the default attributes
|
||||
$this->setDefaultAttributes();
|
||||
|
||||
if($name !== null) {
|
||||
$name = (string) $name;
|
||||
if(isset($this->sessions[$name]))
|
||||
throw new InvalidKeyException();
|
||||
|
||||
} else {
|
||||
$name = $this->index;
|
||||
$this->index++;
|
||||
}
|
||||
switch($pdo->getAttribute(PDO::ATTR_DRIVER_NAME)):
|
||||
case "mysql":
|
||||
$this->sessions[$name] = new Doctrine_Session_Mysql($this,$pdo);
|
||||
break;
|
||||
case "sqlite":
|
||||
$this->sessions[$name] = new Doctrine_Session_Sqlite($this,$pdo);
|
||||
break;
|
||||
case "pgsql":
|
||||
$this->sessions[$name] = new Doctrine_Session_Pgsql($this,$pdo);
|
||||
break;
|
||||
case "oci":
|
||||
$this->sessions[$name] = new Doctrine_Session_Oracle($this,$pdo);
|
||||
break;
|
||||
case "mssql":
|
||||
$this->sessions[$name] = new Doctrine_Session_Mssql($this,$pdo);
|
||||
break;
|
||||
case "firebird":
|
||||
$this->sessions[$name] = new Doctrine_Session_Firebird($this,$pdo);
|
||||
break;
|
||||
case "informix":
|
||||
$this->sessions[$name] = new Doctrine_Session_Informix($this,$pdo);
|
||||
break;
|
||||
endswitch;
|
||||
|
||||
|
||||
$this->currIndex = $name;
|
||||
return $this->sessions[$name];
|
||||
}
|
||||
/**
|
||||
* getSession
|
||||
* @param integer $index
|
||||
* @return object Doctrine_Session
|
||||
* @throws InvalidKeyException
|
||||
*/
|
||||
final public function getSession($index) {
|
||||
if( ! isset($this->sessions[$index]))
|
||||
throw new InvalidKeyException();
|
||||
|
||||
$this->currIndex = $index;
|
||||
return $this->sessions[$index];
|
||||
}
|
||||
/**
|
||||
* closes the session
|
||||
*
|
||||
* @param Doctrine_Session $session
|
||||
* @return void
|
||||
*/
|
||||
final public function closeSession(Doctrine_Session $session) {
|
||||
$session->close();
|
||||
unset($session);
|
||||
}
|
||||
/**
|
||||
* getSessions
|
||||
* @return array
|
||||
*/
|
||||
final public function getSessions() {
|
||||
return $this->sessions;
|
||||
}
|
||||
/**
|
||||
* setCurrentSession
|
||||
* @param mixed $key the session key
|
||||
* @throws InvalidKeyException
|
||||
* @return void
|
||||
*/
|
||||
final public function setCurrentSession($key) {
|
||||
$key = (string) $key;
|
||||
if( ! isset($this->sessions[$key]))
|
||||
throw new InvalidKeyException();
|
||||
|
||||
$this->currIndex = $key;
|
||||
}
|
||||
/**
|
||||
* count
|
||||
* @return integer the number of open sessions
|
||||
*/
|
||||
public function count() {
|
||||
return count($this->sessions);
|
||||
}
|
||||
/**
|
||||
* getIterator
|
||||
* @return ArrayIterator
|
||||
*/
|
||||
public function getIterator() {
|
||||
return new ArrayIterator($this->sessions);
|
||||
}
|
||||
/**
|
||||
* getCurrentSession
|
||||
* @return object Doctrine_Session
|
||||
*/
|
||||
final public function getCurrentSession() {
|
||||
$i = $this->currIndex;
|
||||
if( ! isset($this->sessions[$i]))
|
||||
throw new Doctrine_Session_Exception();
|
||||
|
||||
return $this->sessions[$i];
|
||||
}
|
||||
/**
|
||||
* __toString
|
||||
*/
|
||||
public function __toString() {
|
||||
$r[] = "<pre>";
|
||||
$r[] = "Doctrine_Manager";
|
||||
$r[] = "Sessions : ".count($this->sessions);
|
||||
$r[] = "</pre>";
|
||||
return implode("\n",$r);
|
||||
}
|
||||
}
|
||||
?>
|
999
classes/Record.class.php
Normal file
999
classes/Record.class.php
Normal file
@ -0,0 +1,999 @@
|
||||
<?php
|
||||
require_once("Access.class.php");
|
||||
/**
|
||||
* Doctrine_Record
|
||||
*/
|
||||
abstract class Doctrine_Record extends Doctrine_Access implements Countable, IteratorAggregate {
|
||||
/**
|
||||
* STATE CONSTANTS
|
||||
*/
|
||||
|
||||
/**
|
||||
* DIRTY STATE
|
||||
* a Doctrine_Record is in dirty state when its properties are changed
|
||||
*/
|
||||
const STATE_DIRTY = 1;
|
||||
/**
|
||||
* TDIRTY STATE
|
||||
* a Doctrine_Record is in transient dirty state when it is created and some of its fields are modified
|
||||
* but it is NOT yet persisted into database
|
||||
*/
|
||||
const STATE_TDIRTY = 2;
|
||||
/**
|
||||
* CLEAN STATE
|
||||
* a Doctrine_Record is in clean state when all of its properties are loaded from the database
|
||||
* and none of its properties are changed
|
||||
*/
|
||||
const STATE_CLEAN = 3;
|
||||
/**
|
||||
* PROXY STATE
|
||||
* a Doctrine_Record is in proxy state when its properties are not fully loaded
|
||||
*/
|
||||
const STATE_PROXY = 4;
|
||||
/**
|
||||
* NEW TCLEAN
|
||||
* a Doctrine_Record is in transient clean state when it is created and none of its fields are modified
|
||||
*/
|
||||
const STATE_TCLEAN = 5;
|
||||
/**
|
||||
* DELETED STATE
|
||||
* a Doctrine_Record turns into deleted state when it is deleted
|
||||
*/
|
||||
const STATE_DELETED = 6;
|
||||
|
||||
/**
|
||||
* FETCHMODE CONSTANTS
|
||||
*/
|
||||
|
||||
/**
|
||||
* @var object Doctrine_Table $table the factory that created this data access object
|
||||
*/
|
||||
protected $table;
|
||||
/**
|
||||
* @var integer $id the primary key of this object
|
||||
*/
|
||||
protected $id;
|
||||
/**
|
||||
* @var array $data the dao data
|
||||
*/
|
||||
protected $data = array();
|
||||
|
||||
/**
|
||||
* @var array $modified an array containing properties that have been modified
|
||||
*/
|
||||
private $modified = array();
|
||||
/**
|
||||
* @var integer $state the state of this data access object
|
||||
* @see STATE_* constants
|
||||
*/
|
||||
private $state;
|
||||
/**
|
||||
* @var array $collections the collections this dao is in
|
||||
*/
|
||||
private $collections = array();
|
||||
/**
|
||||
* @var mixed $references an array containing all the references
|
||||
*/
|
||||
private $references = array();
|
||||
/**
|
||||
* @var mixed $originals an array containing all the original references
|
||||
*/
|
||||
private $originals = array();
|
||||
/**
|
||||
* @var integer $index this index is used for creating object identifiers
|
||||
*/
|
||||
private static $index = 1;
|
||||
/**
|
||||
* @var integer $oid object identifier
|
||||
*/
|
||||
private $oid;
|
||||
/**
|
||||
* @var boolean $loaded whether or not this object has its data loaded from database
|
||||
*/
|
||||
private $loaded = false;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
* @param Doctrine_Table $table a Doctrine_Table object
|
||||
* @throws Doctrine_Session_Exception if object is created using the new operator and there are no
|
||||
* open sessions
|
||||
*/
|
||||
public function __construct($table = null) {
|
||||
if(isset($table) && $table instanceof Doctrine_Table) {
|
||||
$this->table = $table;
|
||||
$exists = ( ! $this->table->isNewEntry());
|
||||
} else {
|
||||
$this->table = Doctrine_Manager::getInstance()->getCurrentSession()->getTable(get_class($this));
|
||||
$exists = false;
|
||||
}
|
||||
|
||||
// Check if the current session has the records table in its registry
|
||||
// If not this is record is only used for creating table definition and setting up
|
||||
// relations.
|
||||
|
||||
if($this->table->getSession()->hasTable($this->table->getComponentName())) {
|
||||
|
||||
$this->oid = self::$index;
|
||||
|
||||
self::$index++;
|
||||
|
||||
|
||||
if( ! $exists) {
|
||||
// listen the onPreCreate event
|
||||
$this->table->getAttribute(Doctrine::ATTR_LISTENER)->onPreCreate($this);
|
||||
} else {
|
||||
// listen the onPreLoad event
|
||||
$this->table->getAttribute(Doctrine::ATTR_LISTENER)->onPreLoad($this);
|
||||
}
|
||||
// get the data array
|
||||
$this->data = $this->table->getData();
|
||||
|
||||
// clean data array
|
||||
$cols = $this->cleanData();
|
||||
|
||||
if( ! $exists) {
|
||||
|
||||
|
||||
if($cols > 0)
|
||||
$this->state = Doctrine_Record::STATE_TDIRTY;
|
||||
else
|
||||
$this->state = Doctrine_Record::STATE_TCLEAN;
|
||||
|
||||
|
||||
|
||||
// listen the onCreate event
|
||||
$this->table->getAttribute(Doctrine::ATTR_LISTENER)->onCreate($this);
|
||||
} else {
|
||||
$this->state = Doctrine_Record::STATE_CLEAN;
|
||||
|
||||
if($cols <= 1)
|
||||
$this->state = Doctrine_Record::STATE_PROXY;
|
||||
else
|
||||
$this->loaded = true;
|
||||
|
||||
// id property is protected
|
||||
$keys = $this->table->getPrimaryKeys();
|
||||
if(count($keys) == 1) {
|
||||
$this->id = $this->data[$keys[0]];
|
||||
} else {
|
||||
/**
|
||||
$this->id = array();
|
||||
foreach($keys as $key) {
|
||||
$this->id[] = $this->data[$key];
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// listen the onLoad event
|
||||
$this->table->getAttribute(Doctrine::ATTR_LISTENER)->onLoad($this);
|
||||
}
|
||||
// add data access object to registry
|
||||
$this->table->getRepository()->add($this);
|
||||
|
||||
unset($this->data['id']);
|
||||
|
||||
$this->table->setData(array());
|
||||
|
||||
$this->table->getCache()->store($this);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* setUp
|
||||
* implemented by child classes
|
||||
*/
|
||||
public function setUp() { }
|
||||
/**
|
||||
* return the object identifier
|
||||
* @return integer
|
||||
*/
|
||||
public function getOID() {
|
||||
return $this->oid;
|
||||
}
|
||||
/**
|
||||
* isLoaded
|
||||
*/
|
||||
public function isLoaded() {
|
||||
return $this->loaded;
|
||||
}
|
||||
/**
|
||||
* cleanData
|
||||
* modifies data array
|
||||
* example:
|
||||
*
|
||||
* $data = array("name"=>"John","lastname"=> null,"id"=>1,"unknown"=>"unknown");
|
||||
* $names = array("name","lastname","id");
|
||||
* $data after operation:
|
||||
* $data = array("name"=>"John","lastname" => array(),"id"=>1);
|
||||
*/
|
||||
private function cleanData() {
|
||||
$cols = 0;
|
||||
$tmp = $this->data;
|
||||
|
||||
$this->data = array();
|
||||
|
||||
foreach($this->table->getColumnNames() as $name) {
|
||||
if( ! isset($tmp[$name])) {
|
||||
$this->data[$name] = array();
|
||||
|
||||
} else {
|
||||
$cols++;
|
||||
$this->data[$name] = $tmp[$name];
|
||||
}
|
||||
}
|
||||
|
||||
return $cols;
|
||||
}
|
||||
/**
|
||||
* this method is automatically called when this Doctrine_Record is serialized
|
||||
*/
|
||||
public function __sleep() {
|
||||
$this->table->getAttribute(Doctrine::ATTR_LISTENER)->onSleep($this);
|
||||
|
||||
$this->table = $this->table->getComponentName();
|
||||
// unset all vars that won't need to be serialized
|
||||
|
||||
unset($this->modified);
|
||||
unset($this->associations);
|
||||
unset($this->state);
|
||||
unset($this->collections);
|
||||
unset($this->references);
|
||||
unset($this->originals);
|
||||
unset($this->oid);
|
||||
unset($this->loaded);
|
||||
|
||||
foreach($this->data as $k=>$v) {
|
||||
if($v instanceof Doctrine_Record)
|
||||
$this->data[$k] = array();
|
||||
}
|
||||
return array_keys(get_object_vars($this));
|
||||
}
|
||||
/**
|
||||
* __wakeup
|
||||
* this method is automatically called everytime a Doctrine_Record object is unserialized
|
||||
*/
|
||||
public function __wakeup() {
|
||||
$this->modified = array();
|
||||
$this->state = Doctrine_Record::STATE_CLEAN;
|
||||
|
||||
$name = $this->table;
|
||||
|
||||
$manager = Doctrine_Manager::getInstance();
|
||||
$sess = $manager->getCurrentSession();
|
||||
|
||||
$this->oid = self::$index;
|
||||
self::$index++;
|
||||
|
||||
$this->table = $sess->getTable($name);
|
||||
|
||||
$this->table->getRepository()->add($this);
|
||||
|
||||
$this->loaded = true;
|
||||
|
||||
$this->cleanData();
|
||||
|
||||
|
||||
unset($this->data['id']);
|
||||
|
||||
$this->table->getAttribute(Doctrine::ATTR_LISTENER)->onWakeUp($this);
|
||||
|
||||
}
|
||||
/**
|
||||
* addCollection
|
||||
* @param Doctrine_Collection $collection
|
||||
* @param mixed $key
|
||||
*/
|
||||
final public function addCollection(Doctrine_Collection $collection,$key = null) {
|
||||
if($key !== null) {
|
||||
if(isset($this->collections[$key]))
|
||||
throw InvalidKeyException();
|
||||
|
||||
$this->collections[$key] = $collection;
|
||||
} else {
|
||||
$this->collections[] = $collection;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* getCollection
|
||||
* @param integer $key
|
||||
* @return Doctrine_Collection
|
||||
*/
|
||||
final public function getCollection($key) {
|
||||
return $this->collections[$key];
|
||||
}
|
||||
/**
|
||||
* hasCollections
|
||||
* @return boolean whether or not this dao is part of a collection
|
||||
*/
|
||||
final public function hasCollections() {
|
||||
return (! empty($this->collections));
|
||||
}
|
||||
/**
|
||||
* getState
|
||||
* @see Doctrine_Record::STATE_* constants
|
||||
* @return integer the current state
|
||||
*/
|
||||
final public function getState() {
|
||||
return $this->state;
|
||||
}
|
||||
/**
|
||||
* refresh refresh internal data from the database
|
||||
* @return boolean
|
||||
*/
|
||||
final public function refresh() {
|
||||
if($this->getID() == null) return false;
|
||||
|
||||
$query = $this->table->getQuery()." WHERE ".implode(" = ? && ",$this->table->getPrimaryKeys())." = ?";
|
||||
$this->data = $this->table->getSession()->execute($query,array($this->getID()))->fetch(PDO::FETCH_ASSOC);
|
||||
unset($this->data["id"]);
|
||||
$this->modified = array();
|
||||
$this->cleanData();
|
||||
$this->state = Doctrine_Record::STATE_CLEAN;
|
||||
|
||||
$this->getTable()->getCache()->store($this);
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* factoryRefresh
|
||||
* @throws Doctrine_Exception
|
||||
* @return void
|
||||
*/
|
||||
final public function factoryRefresh() {
|
||||
$data = $this->table->getData();
|
||||
|
||||
if($this->id != $data["id"])
|
||||
throw new Doctrine_Refresh_Exception();
|
||||
|
||||
$this->data = $data;
|
||||
$this->cleanData();
|
||||
unset($this->data["id"]);
|
||||
$this->state = Doctrine_Record::STATE_CLEAN;
|
||||
$this->modified = array();
|
||||
|
||||
$this->getTable()->getCache()->store($this);
|
||||
}
|
||||
/**
|
||||
* return the factory that created this data access object
|
||||
* @return object Doctrine_Table a Doctrine_Table object
|
||||
*/
|
||||
final public function getTable() {
|
||||
return $this->table;
|
||||
}
|
||||
/**
|
||||
* return all the internal data
|
||||
* @return array an array containing all the properties
|
||||
*/
|
||||
final public function getData() {
|
||||
return $this->data;
|
||||
}
|
||||
/**
|
||||
* get
|
||||
* returns a value of a property or related component
|
||||
*
|
||||
* @param $name name of the property or related component
|
||||
* @throws InvalidKeyException
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($name) {
|
||||
if(isset($this->data[$name])) {
|
||||
|
||||
// check if the property is not loaded (= it is an empty array)
|
||||
if(is_array($this->data[$name]) && ! $this->loaded) {
|
||||
|
||||
// no use trying to load the data from database if the Doctrine_Record is new or clean
|
||||
if($this->state != Doctrine_Record::STATE_TDIRTY &&
|
||||
$this->state != Doctrine_Record::STATE_TCLEAN &&
|
||||
$this->state != Doctrine_Record::STATE_CLEAN) {
|
||||
|
||||
$this->loaded = true;
|
||||
|
||||
if( ! empty($this->collections)) {
|
||||
foreach($this->collections as $collection) {
|
||||
$collection->load($this);
|
||||
}
|
||||
} else {
|
||||
$this->refresh();
|
||||
}
|
||||
$this->state = Doctrine_Record::STATE_CLEAN;
|
||||
}
|
||||
|
||||
if(is_array($this->data[$name]))
|
||||
return null;
|
||||
|
||||
return $this->data[$name];
|
||||
}
|
||||
return $this->data[$name];
|
||||
}
|
||||
if($name == "id")
|
||||
return $this->id;
|
||||
|
||||
if( ! isset($this->references[$name]))
|
||||
$this->loadReference($name);
|
||||
|
||||
|
||||
return $this->references[$name];
|
||||
}
|
||||
/**
|
||||
* rawSet
|
||||
* doctrine uses this function internally, not recommended for developers
|
||||
*
|
||||
* @param mixed $name name of the property or reference
|
||||
* @param mixed $value value of the property or reference
|
||||
*/
|
||||
final public function rawSet($name,$value) {
|
||||
if($value instanceof Doctrine_Record)
|
||||
$id = $value->getID();
|
||||
|
||||
if( ! empty($id))
|
||||
$value = $id;
|
||||
|
||||
$this->data[$name] = $value;
|
||||
}
|
||||
/**
|
||||
* set
|
||||
* method for altering properties and Doctrine_Record references
|
||||
*
|
||||
* @param mixed $name name of the property or reference
|
||||
* @param mixed $value value of the property or reference
|
||||
* @throws InvalidKeyException
|
||||
* @throws InvalidTypeException
|
||||
* @return void
|
||||
*/
|
||||
public function set($name,$value) {
|
||||
if(isset($this->data[$name])) {
|
||||
$old = $this->get($name);
|
||||
|
||||
if($value instanceof Doctrine_Record) {
|
||||
$id = $value->getID();
|
||||
|
||||
if( ! empty($id))
|
||||
$value = $value->getID();
|
||||
}
|
||||
|
||||
if($old !== $value) {
|
||||
$this->data[$name] = $value;
|
||||
|
||||
$this->modified[] = $name;
|
||||
|
||||
switch($this->state):
|
||||
case Doctrine_Record::STATE_CLEAN:
|
||||
case Doctrine_Record::STATE_PROXY:
|
||||
$this->state = Doctrine_Record::STATE_DIRTY;
|
||||
break;
|
||||
case Doctrine_Record::STATE_TCLEAN:
|
||||
$this->state = Doctrine_Record::STATE_TDIRTY;
|
||||
break;
|
||||
endswitch;
|
||||
}
|
||||
} else {
|
||||
// if not found, throws InvalidKeyException
|
||||
|
||||
$fk = $this->table->getForeignKey($name);
|
||||
|
||||
if($value->getTable()->getComponentName() != $name)
|
||||
throw new InvalidKeyException();
|
||||
|
||||
// one-to-many or one-to-one relation
|
||||
if($fk instanceof Doctrine_ForeignKey ||
|
||||
$fk instanceof Doctrine_LocalKey) {
|
||||
switch($fk->getType()):
|
||||
case Doctrine_Table::MANY_COMPOSITE:
|
||||
case Doctrine_Table::MANY_AGGREGATE:
|
||||
// one-to-many relation found
|
||||
if( ! ($value instanceof Doctrine_Collection))
|
||||
throw new InvalidTypeException("Couldn't call Doctrine::set(), second argument should be an instance of Doctrine_Collection when setting one-to-many references.");
|
||||
|
||||
$value->setReference($this,$fk);
|
||||
break;
|
||||
case Doctrine_Table::ONE_COMPOSITE:
|
||||
case Doctrine_Table::ONE_AGGREGATE:
|
||||
// one-to-one relation found
|
||||
if( ! ($value instanceof Doctrine_Record))
|
||||
throw new InvalidTypeException("Couldn't call Doctrine::set(), second argument should be an instance of Doctrine_Record when setting one-to-one references.");
|
||||
|
||||
if($fk->getLocal() == "id") {
|
||||
$this->references[$name]->set($fk->getForeign(),$this);
|
||||
} else {
|
||||
$this->set($fk->getLocal(),$value);
|
||||
}
|
||||
break;
|
||||
endswitch;
|
||||
|
||||
} elseif($fk instanceof Doctrine_Association) {
|
||||
// many-to-many relation found
|
||||
if( ! ($value instanceof Doctrine_Collection))
|
||||
throw new InvalidTypeException("Couldn't call Doctrine::set(), second argument should be an instance of Doctrine_Collection when setting one-to-many references.");
|
||||
}
|
||||
|
||||
$this->references[$name] = $value;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* applies the changes made to this object into database
|
||||
* this method is smart enough to know if any changes are made
|
||||
* and whether to use INSERT or UPDATE statement
|
||||
*
|
||||
* this method also saves the related composites
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
final public function save() {
|
||||
$this->table->getSession()->beginTransaction();
|
||||
|
||||
// listen the onPreSave event
|
||||
$this->table->getAttribute(Doctrine::ATTR_LISTENER)->onPreSave($this);
|
||||
|
||||
|
||||
|
||||
$saveLater = $this->table->getSession()->saveRelated($this);
|
||||
|
||||
$this->table->getSession()->save($this);
|
||||
|
||||
foreach($saveLater as $fk) {
|
||||
$table = $fk->getTable();
|
||||
$foreign = $fk->getForeign();
|
||||
$local = $fk->getLocal();
|
||||
|
||||
$name = $table->getComponentName();
|
||||
if(isset($this->references[$name])) {
|
||||
$obj = $this->references[$name];
|
||||
$obj->save();
|
||||
}
|
||||
}
|
||||
|
||||
// save the MANY-TO-MANY associations
|
||||
|
||||
$this->saveAssociations();
|
||||
|
||||
$this->table->getSession()->commit();
|
||||
}
|
||||
/**
|
||||
* returns an array of modified fields and associated values
|
||||
* @return array
|
||||
*/
|
||||
final public function getModified() {
|
||||
$a = array();
|
||||
|
||||
foreach($this->modified as $k=>$v) {
|
||||
$a[$v] = $this->data[$v];
|
||||
}
|
||||
return $a;
|
||||
}
|
||||
/**
|
||||
* this class implements countable interface
|
||||
* @return integer the number of columns
|
||||
*/
|
||||
public function count() {
|
||||
return count($this->data);
|
||||
}
|
||||
/**
|
||||
* getIterator
|
||||
* @return ArrayIterator an ArrayIterator that iterates through the data
|
||||
*/
|
||||
public function getIterator() {
|
||||
return new ArrayIterator($this->data);
|
||||
}
|
||||
/**
|
||||
* saveAssociations
|
||||
* save the associations of many-to-many relations
|
||||
* this method also deletes associations that do not exist anymore
|
||||
* @return void
|
||||
*/
|
||||
final public function saveAssociations() {
|
||||
foreach($this->table->getForeignKeys() as $fk):
|
||||
$table = $fk->getTable();
|
||||
$name = $table->getComponentName();
|
||||
|
||||
|
||||
if($fk instanceof Doctrine_Association) {
|
||||
switch($fk->getType()):
|
||||
case Doctrine_Table::MANY_COMPOSITE:
|
||||
|
||||
break;
|
||||
case Doctrine_Table::MANY_AGGREGATE:
|
||||
$asf = $fk->getAssociationFactory();
|
||||
if(isset($this->references[$name])) {
|
||||
|
||||
$new = $this->references[$name];
|
||||
|
||||
if( ! isset($this->originals[$name])) {
|
||||
$this->loadReference($name);
|
||||
}
|
||||
|
||||
$r = $this->getRelationOperations($name,$new);
|
||||
|
||||
foreach($r["delete"] as $record) {
|
||||
$query = "DELETE FROM ".$asf->getTableName()." WHERE ".$fk->getForeign()." = ?"
|
||||
." && ".$fk->getLocal()." = ?";
|
||||
$this->table->getSession()->execute($query, array($record->getID(),$this->getID()));
|
||||
}
|
||||
foreach($r["add"] as $record) {
|
||||
$reldao = $asf->create();
|
||||
$reldao->set($fk->getForeign(),$record);
|
||||
$reldao->set($fk->getLocal(),$this);
|
||||
$reldao->save();
|
||||
}
|
||||
$this->originals[$name] = clone $this->references[$name];
|
||||
}
|
||||
break;
|
||||
endswitch;
|
||||
} elseif($fk instanceof Doctrine_ForeignKey ||
|
||||
$fk instanceof Doctrine_LocalKey) {
|
||||
|
||||
switch($fk->getType()):
|
||||
case Doctrine_Table::ONE_COMPOSITE:
|
||||
if(isset($this->originals[$name]) && $this->originals[$name]->getID() != $this->references[$name]->getID())
|
||||
$this->originals[$name]->delete();
|
||||
|
||||
break;
|
||||
case Doctrine_Table::MANY_COMPOSITE:
|
||||
if(isset($this->references[$name])) {
|
||||
$new = $this->references[$name];
|
||||
|
||||
if( ! isset($this->originals[$name]))
|
||||
$this->loadReference($name);
|
||||
|
||||
$r = $this->getRelationOperations($name,$new);
|
||||
|
||||
foreach($r["delete"] as $record) {
|
||||
$record->delete();
|
||||
}
|
||||
|
||||
$this->originals[$name] = clone $this->references[$name];
|
||||
}
|
||||
break;
|
||||
endswitch;
|
||||
}
|
||||
endforeach;
|
||||
}
|
||||
/**
|
||||
* get the records that need to be added
|
||||
* and/or deleted in order to change the old collection
|
||||
* to the new one
|
||||
*
|
||||
* The algorithm here is very simple and definitely not
|
||||
* the fastest one, since we have to iterate through the collections twice.
|
||||
* the complexity of this algorithm is O(2*n^2)
|
||||
*
|
||||
* First we iterate through the new collection and get the
|
||||
* records that do not exist in the old collection (Doctrine_Records that need to be added).
|
||||
*
|
||||
* Then we iterate through the old collection and get the records
|
||||
* that do not exists in the new collection (Doctrine_Records that need to be deleted).
|
||||
*/
|
||||
final public function getRelationOperations($name, Doctrine_Collection $new) {
|
||||
$r["add"] = array();
|
||||
$r["delete"] = array();
|
||||
|
||||
|
||||
|
||||
foreach($new as $k=>$record) {
|
||||
|
||||
$found = false;
|
||||
|
||||
if($record->getID() !== null) {
|
||||
foreach($this->originals[$name] as $k2 => $record2) {
|
||||
if($record2->getID() == $record->getID()) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( ! $found) {
|
||||
$this->originals[$name][] = $record;
|
||||
$r["add"][] = $record;
|
||||
}
|
||||
}
|
||||
|
||||
foreach($this->originals[$name] as $k => $record) {
|
||||
if($record->getID() === null)
|
||||
continue;
|
||||
|
||||
$found = false;
|
||||
foreach($new as $k2=>$record2) {
|
||||
if($record2->getID() == $record->getID()) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( ! $found) {
|
||||
$r["delete"][] = $record;
|
||||
unset($this->originals[$name][$k]);
|
||||
}
|
||||
}
|
||||
|
||||
return $r;
|
||||
}
|
||||
/**
|
||||
* getOriginals
|
||||
*/
|
||||
final public function getOriginals($name) {
|
||||
if( ! isset($this->originals[$name]))
|
||||
throw new InvalidKeyException();
|
||||
|
||||
return $this->originals[$name];
|
||||
}
|
||||
/**
|
||||
* deletes this data access object and all the related composites
|
||||
* this operation is isolated by a transaction
|
||||
*
|
||||
* this event can be listened by the onPreDelete and onDelete listeners
|
||||
*
|
||||
* @return boolean true on success, false on failure
|
||||
*/
|
||||
final public function delete() {
|
||||
$this->table->getSession()->delete($this);
|
||||
}
|
||||
/**
|
||||
* returns a copy of this object
|
||||
* @return DAO
|
||||
*/
|
||||
final public function copy() {
|
||||
return $this->table->create($this->data);
|
||||
}
|
||||
/**
|
||||
* @param integer $id
|
||||
* @return void
|
||||
*/
|
||||
final public function setID($id = null) {
|
||||
if($id === null) {
|
||||
$this->id = null;
|
||||
$this->cleanData();
|
||||
$this->state = Doctrine_Record::STATE_TCLEAN;
|
||||
$this->modified = array();
|
||||
} else {
|
||||
$this->id = $id;
|
||||
$this->state = Doctrine_Record::STATE_CLEAN;
|
||||
$this->modified = array();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* return the primary key this object is pointing at
|
||||
* @return int id
|
||||
*/
|
||||
final public function getID() {
|
||||
return $this->id;
|
||||
}
|
||||
/**
|
||||
* hasRefence
|
||||
* @param string $name
|
||||
*/
|
||||
public function hasReference($name) {
|
||||
return isset($this->references[$name]);
|
||||
}
|
||||
/**
|
||||
* @param Doctrine_Collection $coll
|
||||
* @param string $connectorField
|
||||
*/
|
||||
public function initReference(Doctrine_Collection $coll, Doctrine_Relation $connector) {
|
||||
$name = $coll->getTable()->getComponentName();
|
||||
$coll->setReference($this, $connector);
|
||||
$this->references[$name] = $coll;
|
||||
$this->originals[$name] = clone $coll;
|
||||
}
|
||||
/**
|
||||
* addReference
|
||||
*/
|
||||
public function addReference(Doctrine_Record $record) {
|
||||
$name = $record->getTable()->getComponentName();
|
||||
$this->references[$name]->add($record);
|
||||
$this->originals[$name]->add($record);
|
||||
}
|
||||
/**
|
||||
* getReferences
|
||||
* @return array all references
|
||||
*/
|
||||
public function getReferences() {
|
||||
return $this->references;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidKeyException
|
||||
* @param name
|
||||
* @return void
|
||||
*/
|
||||
final public function loadReference($name) {
|
||||
$fk = $this->table->getForeignKey($name);
|
||||
$table = $fk->getTable();
|
||||
$name = $table->getComponentName();
|
||||
|
||||
|
||||
switch($this->getState()):
|
||||
case Doctrine_Record::STATE_TDIRTY:
|
||||
case Doctrine_Record::STATE_TCLEAN:
|
||||
|
||||
if($fk->getType() == Doctrine_Table::ONE_COMPOSITE || $fk->getType() == Doctrine_Table::ONE_AGGREGATE) {
|
||||
// ONE-TO-ONE
|
||||
$this->references[$name] = $table->create();
|
||||
|
||||
if($fk instanceof Doctrine_ForeignKey) {
|
||||
$this->references[$name]->set($fk->getForeign(),$this);
|
||||
} else {
|
||||
$this->set($fk->getLocal(),$this->references[$name]);
|
||||
}
|
||||
} else {
|
||||
|
||||
$this->references[$name] = new Doctrine_Collection($table);
|
||||
if($fk instanceof Doctrine_ForeignKey) {
|
||||
// ONE-TO-MANY
|
||||
$this->references[$name]->setReference($this,$fk);
|
||||
}
|
||||
$this->originals[$name] = new Doctrine_Collection($table);
|
||||
}
|
||||
break;
|
||||
case Doctrine_Record::STATE_DIRTY:
|
||||
case Doctrine_Record::STATE_CLEAN:
|
||||
case Doctrine_Record::STATE_PROXY:
|
||||
|
||||
$local = $fk->getLocal();
|
||||
|
||||
$coll = false;
|
||||
|
||||
if($fk instanceof Doctrine_ForeignKey ||
|
||||
$fk instanceof Doctrine_LocalKey) {
|
||||
|
||||
$graph = $table->getDQLParser();
|
||||
|
||||
// get the local identifier
|
||||
$id = $this->get($local);
|
||||
|
||||
if(empty($id)) {
|
||||
|
||||
$this->references[$name] = $table->create();
|
||||
|
||||
if($this->table->hasPrimaryKey($fk->getLocal())) {
|
||||
$this->references[$name]->set($fk->getForeign(),$this);
|
||||
} else {
|
||||
$this->set($fk->getLocal(),$this->references[$name]);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if($this->table->hasPrimaryKey($fk->getForeign())) {
|
||||
try {
|
||||
$coll = new Doctrine_Collection($table);
|
||||
|
||||
$coll[0] = $table->getCache()->fetch($id);
|
||||
|
||||
} catch(InvalidKeyException $e) {
|
||||
$coll = false;
|
||||
}
|
||||
}
|
||||
|
||||
if( ! $coll) {
|
||||
$query = "FROM ".$name." WHERE ".$name.".".$fk->getForeign()." = ?";
|
||||
$coll = $graph->query($query,array($id));
|
||||
}
|
||||
|
||||
if($fk->getType() == Doctrine_Table::ONE_COMPOSITE ||
|
||||
$fk->getType() == Doctrine_Table::ONE_AGGREGATE) {
|
||||
|
||||
if($coll->contains(0)) {
|
||||
$this->references[$name] = $coll[0];
|
||||
$this->originals[$name] = clone $coll[0];
|
||||
|
||||
} else {
|
||||
$this->references[$name] = $table->create();
|
||||
if($this->table->hasPrimaryKey($fk->getLocal())) {
|
||||
|
||||
$this->references[$name]->set($fk->getForeign(),$this);
|
||||
} else {
|
||||
$this->set($fk->getLocal(),$this->references[$name]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->references[$name] = $coll;
|
||||
$this->references[$name]->setReference($this,$fk);
|
||||
|
||||
|
||||
$this->originals[$name] = clone $coll;
|
||||
|
||||
}
|
||||
}
|
||||
} elseif($fk instanceof Doctrine_Association) {
|
||||
|
||||
$foreign = $fk->getForeign();
|
||||
|
||||
$asf = $fk->getAssociationFactory();
|
||||
$query = "SELECT ".$foreign." FROM ".$asf->getTableName()." WHERE ".$local." = ?";
|
||||
|
||||
$table = $fk->getTable();
|
||||
$graph = new Doctrine_DQL_Parser($table->getSession());
|
||||
|
||||
$q = "FROM ".$table->getComponentName()." WHERE ".$table->getComponentName().".id IN ($query)";
|
||||
|
||||
|
||||
$coll = $graph->query($q, array($this->getID()));
|
||||
|
||||
$this->references[$name] = $coll;
|
||||
$this->originals[$name] = clone $coll;
|
||||
|
||||
}
|
||||
break;
|
||||
endswitch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $objTableName
|
||||
* @param string $fkField
|
||||
* @return void
|
||||
*/
|
||||
final public function ownsOne($componentName,$foreignKey, $localKey = "id") {
|
||||
$this->table->bind($componentName,$foreignKey,Doctrine_Table::ONE_COMPOSITE, $localKey);
|
||||
}
|
||||
/**
|
||||
* @param string $objTableName
|
||||
* @param string $fkField
|
||||
* @return void
|
||||
*/
|
||||
final public function ownsMany($componentName,$foreignKey, $localKey = "id") {
|
||||
$this->table->bind($componentName,$foreignKey,Doctrine_Table::MANY_COMPOSITE, $localKey);
|
||||
}
|
||||
/**
|
||||
* @param string $objTableName
|
||||
* @param string $fkField
|
||||
* @return void
|
||||
*/
|
||||
final public function hasOne($componentName,$foreignKey, $localKey = "id") {
|
||||
$this->table->bind($componentName,$foreignKey,Doctrine_Table::ONE_AGGREGATE, $localKey);
|
||||
}
|
||||
/**
|
||||
* @param string $objTableName
|
||||
* @param string $fkField
|
||||
* @return void
|
||||
*/
|
||||
final public function hasMany($componentName,$foreignKey, $localKey = "id") {
|
||||
$this->table->bind($componentName,$foreignKey,Doctrine_Table::MANY_AGGREGATE, $localKey);
|
||||
}
|
||||
/**
|
||||
* setInheritanceMap
|
||||
* @param array $inheritanceMap
|
||||
* @return void
|
||||
*/
|
||||
final public function setInheritanceMap(array $inheritanceMap) {
|
||||
$this->table->setInheritanceMap($inheritanceMap);
|
||||
}
|
||||
/**
|
||||
* setPrimaryKey
|
||||
* @param string $key
|
||||
*/
|
||||
final public function setPrimaryKey($key) {
|
||||
$this->table->setPrimaryKey($key);
|
||||
}
|
||||
/**
|
||||
* setTableName
|
||||
* @param string $name table name
|
||||
* @return void
|
||||
*/
|
||||
final public function setTableName($name) {
|
||||
$this->table->setTableName($name);
|
||||
}
|
||||
/**
|
||||
* setAttribute
|
||||
* @param integer $attribute
|
||||
* @param mixed $value
|
||||
* @see Doctrine::ATTR_* constants
|
||||
* @return void
|
||||
*/
|
||||
final public function setAttribute($attribute, $value) {
|
||||
$this->table->setAttribute($attribute,$value);
|
||||
}
|
||||
/**
|
||||
* hasColumn
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @param integer $length
|
||||
* @param mixed $options
|
||||
* @return void
|
||||
*/
|
||||
final public function hasColumn($name, $type, $length = 20, $options = "") {
|
||||
$this->table->hasColumn($name, $type, $length, $options);
|
||||
}
|
||||
/**
|
||||
* returns a string representation of this object
|
||||
*/
|
||||
public function __toString() {
|
||||
return Doctrine_Lib::getRecordAsString($this);
|
||||
}
|
||||
}
|
||||
?>
|
83
classes/Relation.class.php
Normal file
83
classes/Relation.class.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/**
|
||||
* @class Doctrine_Relation
|
||||
*
|
||||
* @author Konsta Vesterinen
|
||||
* @package Doctrine ORM
|
||||
* @url www.phpdoctrine.com
|
||||
* @license LGPL
|
||||
* @version 1.0 alpha
|
||||
*
|
||||
*/
|
||||
class Doctrine_Relation {
|
||||
/**
|
||||
* @var Doctrine_Table $table foreign factory
|
||||
*/
|
||||
private $table;
|
||||
/**
|
||||
* @var string $local local field
|
||||
*/
|
||||
private $local;
|
||||
/**
|
||||
* @var string $foreign foreign field
|
||||
*/
|
||||
private $foreign;
|
||||
/**
|
||||
* @var integer $type bind type
|
||||
*/
|
||||
private $type;
|
||||
/**
|
||||
* @param Doctrine_Table $table
|
||||
* @param string $local
|
||||
* @param string $foreign
|
||||
* @param integer $type
|
||||
*/
|
||||
public function __construct(Doctrine_Table $table,$local,$foreign,$type) {
|
||||
$this->table = $table;
|
||||
$this->local = $local;
|
||||
$this->foreign = $foreign;
|
||||
$this->type = $type;
|
||||
}
|
||||
/**
|
||||
* @see Doctrine_Table::BIND_ONE, Doctrine_Table::BIND_MANY
|
||||
* @return integer bind type 1 or 0
|
||||
*/
|
||||
public function getType() {
|
||||
return $this->type;
|
||||
}
|
||||
/**
|
||||
* @return object Doctrine_Table foreign factory object
|
||||
*/
|
||||
public function getTable() {
|
||||
return $this->table;
|
||||
}
|
||||
/**
|
||||
* @return string the name of the local column
|
||||
*/
|
||||
public function getLocal() {
|
||||
return $this->local;
|
||||
}
|
||||
/**
|
||||
* @return string the name of the foreign column where
|
||||
* the local column is pointing at
|
||||
*/
|
||||
public function getForeign() {
|
||||
return $this->foreign;
|
||||
}
|
||||
/**
|
||||
* __toString
|
||||
*/
|
||||
public function __toString() {
|
||||
$r[] = "<pre>";
|
||||
$r[] = "Class : ".get_class($this);
|
||||
$r[] = "Component : ".$this->table->getComponentName();
|
||||
$r[] = "Table : ".$this->table->getTableName();
|
||||
$r[] = "Local key : ".$this->local;
|
||||
$r[] = "Foreign key : ".$this->foreign;
|
||||
$r[] = "Type : ".$this->type;
|
||||
$r[] = "</pre>";
|
||||
return implode("\n", $r);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
114
classes/Repository.class.php
Normal file
114
classes/Repository.class.php
Normal file
@ -0,0 +1,114 @@
|
||||
<?php
|
||||
/**
|
||||
* Doctrine_Repository
|
||||
* each record is added into Doctrine_Repository at the same time they are created,
|
||||
* loaded from the database or retrieved from the cache
|
||||
*
|
||||
* @author Konsta Vesterinen
|
||||
* @package Doctrine ORM
|
||||
* @url www.phpdoctrine.com
|
||||
* @license LGPL
|
||||
* @version 1.0 alpha
|
||||
*
|
||||
*/
|
||||
class Doctrine_Repository implements Countable, IteratorAggregate {
|
||||
/**
|
||||
* @var object Doctrine_Table $table
|
||||
*/
|
||||
private $table;
|
||||
/**
|
||||
* @var array $registry
|
||||
* an array of all records
|
||||
* keys representing record object identifiers
|
||||
*/
|
||||
private $registry = array();
|
||||
/**
|
||||
* constructor
|
||||
*/
|
||||
public function __construct(Doctrine_Table $table) {
|
||||
$this->table = $table;
|
||||
}
|
||||
/**
|
||||
* @return object Doctrine_Table
|
||||
*/
|
||||
public function getTable() {
|
||||
return $this->table;
|
||||
}
|
||||
/**
|
||||
* add
|
||||
* @param Doctrine_Record $record record to be added into registry
|
||||
*/
|
||||
public function add(Doctrine_Record $record) {
|
||||
$oid = $record->getOID();
|
||||
|
||||
if(isset($this->registry[$oid]))
|
||||
return false;
|
||||
|
||||
$this->registry[$oid] = $record;
|
||||
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* get
|
||||
* @param integer $oid
|
||||
* @throws InvalidKeyException
|
||||
*/
|
||||
public function get($oid) {
|
||||
if( ! isset($this->registry[$oid]))
|
||||
throw new InvalidKeyException();
|
||||
|
||||
return $this->registry[$oid];
|
||||
}
|
||||
/**
|
||||
* count
|
||||
* Doctrine_Registry implements interface Countable
|
||||
* @return integer the number of records this registry has
|
||||
*/
|
||||
public function count() {
|
||||
return count($this->registry);
|
||||
}
|
||||
/**
|
||||
* @param integer $oid object identifier
|
||||
* @return boolean whether ot not the operation was successful
|
||||
*/
|
||||
public function evict($oid) {
|
||||
if( ! isset($this->registry[$oid]))
|
||||
return false;
|
||||
|
||||
unset($this->registry[$oid]);
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @return integer number of records evicted
|
||||
*/
|
||||
public function evictAll() {
|
||||
$evicted = 0;
|
||||
foreach($this->registry as $oid=>$record) {
|
||||
if($this->evict($oid))
|
||||
$evicted++;
|
||||
}
|
||||
return $evicted;
|
||||
}
|
||||
/**
|
||||
* getIterator
|
||||
* @return ArrayIterator
|
||||
*/
|
||||
public function getIterator() {
|
||||
return new ArrayIterator($this->registry);
|
||||
}
|
||||
/**
|
||||
* contains
|
||||
* @param integer $oid object identifier
|
||||
*/
|
||||
public function contains($oid) {
|
||||
return isset($this->registry[$oid]);
|
||||
}
|
||||
/**
|
||||
* loadAll
|
||||
* @return void
|
||||
*/
|
||||
public function loadAll() {
|
||||
$this->table->findAll();
|
||||
}
|
||||
}
|
||||
?>
|
736
classes/Session.class.php
Normal file
736
classes/Session.class.php
Normal file
@ -0,0 +1,736 @@
|
||||
<?php
|
||||
require_once("Configurable.class.php");
|
||||
require_once("Record.class.php");
|
||||
/**
|
||||
* @author Konsta Vesterinen
|
||||
* @package Doctrine ORM
|
||||
* @url www.phpdoctrine.com
|
||||
* @license LGPL
|
||||
* @version 1.0 alpha
|
||||
*/
|
||||
abstract class Doctrine_Session extends Doctrine_Configurable implements Countable, IteratorAggregate {
|
||||
/**
|
||||
* Doctrine_Session is in open state when it is opened and there are no active transactions
|
||||
*/
|
||||
const STATE_OPEN = 0;
|
||||
/**
|
||||
* Doctrine_Session is in closed state when it is closed
|
||||
*/
|
||||
const STATE_CLOSED = 1;
|
||||
/**
|
||||
* Doctrine_Session is in active state when it has one active transaction
|
||||
*/
|
||||
const STATE_ACTIVE = 2;
|
||||
/**
|
||||
* Doctrine_Session is in busy state when it has multiple active transactions
|
||||
*/
|
||||
const STATE_BUSY = 3;
|
||||
/**
|
||||
* @var $dbh the database handle
|
||||
*/
|
||||
private $dbh;
|
||||
/**
|
||||
* @var array $tables an array containing all the initialized Doctrine_Table objects
|
||||
* keys representing Doctrine_Table component names and values as Doctrine_Table objects
|
||||
*/
|
||||
private $tables = array();
|
||||
/**
|
||||
* @see Doctrine_Session::STATE_* constants
|
||||
* @var boolean $state the current state of the session
|
||||
*/
|
||||
private $state = 0;
|
||||
/**
|
||||
* @var array $update two dimensional pending update list, the records in
|
||||
* this list will be updated when transaction is committed
|
||||
*/
|
||||
private $update = array(array());
|
||||
/**
|
||||
* @var array $insert two dimensional pending insert list, the records in
|
||||
* this list will be inserted when transaction is committed
|
||||
*/
|
||||
private $insert = array(array());
|
||||
/**
|
||||
* @var array $delete two dimensional pending delete list, the records in
|
||||
* this list will be deleted when transaction is committed
|
||||
*/
|
||||
private $delete = array(array());
|
||||
/**
|
||||
* @var integer $transaction_level the nesting level of transactions, used by transaction methods
|
||||
*/
|
||||
private $transaction_level = 0;
|
||||
|
||||
private $validator;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* the constructor
|
||||
* @param PDO $pdo -- database handle
|
||||
*/
|
||||
public function __construct(Doctrine_Manager $manager,PDO $pdo) {
|
||||
$this->dbh = $pdo;
|
||||
|
||||
$this->setParent($manager);
|
||||
|
||||
$this->state = Doctrine_Session::STATE_OPEN;
|
||||
|
||||
$this->dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
|
||||
$this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
$this->getAttribute(Doctrine::ATTR_LISTENER)->onOpen($this);
|
||||
}
|
||||
/**
|
||||
* @return integer the session state
|
||||
*/
|
||||
public function getState() {
|
||||
return $this->state;
|
||||
}
|
||||
/**
|
||||
* @return Doctrine_Manager
|
||||
*/
|
||||
public function getManager() {
|
||||
return $this->getParent();
|
||||
}
|
||||
/**
|
||||
* @return object PDO the database handle
|
||||
*/
|
||||
public function getDBH() {
|
||||
return $this->dbh;
|
||||
}
|
||||
/**
|
||||
* query
|
||||
* queries the database with Doctrine Query Language
|
||||
*/
|
||||
final public function query($query,array $params = array()) {
|
||||
$parser = new Doctrine_DQL_Parser($this);
|
||||
|
||||
return $parser->query($query, $params);
|
||||
}
|
||||
/**
|
||||
* queries the database with limit and offset
|
||||
* added to the query and returns a PDOStatement object
|
||||
*
|
||||
* @param string $query
|
||||
* @param integer $limit
|
||||
* @param integer $offset
|
||||
* @return PDOStatement
|
||||
*/
|
||||
public function select($query,$limit = 0,$offset = 0) {
|
||||
if($limit > 0 || $offset > 0)
|
||||
$query = $this->modifyLimitQuery($query,$limit,$offset);
|
||||
|
||||
return $this->dbh->query($query);
|
||||
}
|
||||
/**
|
||||
* @return object PDOStatement -- the PDOStatement object
|
||||
*/
|
||||
public function execute($query, array $params = array()) {
|
||||
if( ! empty($params)) {
|
||||
$stmt = $this->dbh->prepare($query);
|
||||
$stmt->execute($params);
|
||||
return $stmt;
|
||||
} else {
|
||||
return $this->dbh->query($query);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param $mixed -- Doctrine_Table name
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasTable($name) {
|
||||
return isset($this->tables[$name]);
|
||||
}
|
||||
/**
|
||||
* @param string $name component name
|
||||
* @throws Doctrine_Table_Exception
|
||||
* @return object Doctrine_Table
|
||||
*/
|
||||
public function getTable($name) {
|
||||
$name = ucwords(strtolower($name));
|
||||
|
||||
if(isset($this->tables[$name]))
|
||||
return $this->tables[$name];
|
||||
|
||||
$class = $name."Table";
|
||||
|
||||
if(class_exists($class) && in_array("Doctrine_Table", class_parents($class)))
|
||||
return new $class($name);
|
||||
else
|
||||
return new Doctrine_Table($name);
|
||||
}
|
||||
/**
|
||||
* @return array -- an array of all initialized factories
|
||||
*/
|
||||
public function getTables() {
|
||||
return $this->tables;
|
||||
}
|
||||
/**
|
||||
* @return ArrayIterator
|
||||
*/
|
||||
public function getIterator() {
|
||||
return new ArrayIterator($this->tables);
|
||||
}
|
||||
/**
|
||||
* @return integer
|
||||
*/
|
||||
public function count() {
|
||||
return count($this->tables);
|
||||
}
|
||||
/**
|
||||
* @param $objTable -- a Doctrine_Table object to be added into factory registry
|
||||
* @return boolean
|
||||
*/
|
||||
public function addTable(Doctrine_Table $objTable) {
|
||||
$name = $objTable->getComponentName();
|
||||
|
||||
if(isset($this->tables[$name]))
|
||||
return false;
|
||||
|
||||
$this->tables[$name] = $objTable;
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* create creates a record
|
||||
* @param string $name component name
|
||||
* @return Doctrine_Record Doctrine_Record object
|
||||
*/
|
||||
public function create($name) {
|
||||
return $this->getTable($name)->create();
|
||||
}
|
||||
/**
|
||||
* buildFlushTree
|
||||
* @return array
|
||||
*/
|
||||
public function buildFlushTree() {
|
||||
$tree = array();
|
||||
foreach($this->tables as $k => $table) {
|
||||
$tmp = array();
|
||||
$tmp[] = $table->getComponentName();
|
||||
$pos = 0;
|
||||
foreach($table->getForeignKeys() as $fk) {
|
||||
if($fk instanceof Doctrine_ForeignKey ||
|
||||
$fk instanceof Doctrine_LocalKey) {
|
||||
|
||||
$name = $fk->getTable()->getComponentName();
|
||||
$index = array_search($name,$tree);
|
||||
|
||||
if(isset($locked[$name])) {
|
||||
$pos = $index;
|
||||
continue;
|
||||
}
|
||||
|
||||
if($index !== false)
|
||||
unset($tree[$index]);
|
||||
|
||||
switch($fk->getType()):
|
||||
case Doctrine_Table::ONE_COMPOSITE:
|
||||
case Doctrine_Table::ONE_AGGREGATE:
|
||||
array_unshift($tmp,$name);
|
||||
break;
|
||||
case Doctrine_Table::MANY_COMPOSITE:
|
||||
case Doctrine_Table::MANY_AGGREGATE:
|
||||
$tmp[] = $name;
|
||||
break;
|
||||
endswitch;
|
||||
$locked[$name] = true;
|
||||
}
|
||||
}
|
||||
$index = array_search($k,$tree);
|
||||
|
||||
if($index === false) {
|
||||
if($pos != 0) {
|
||||
$first = array_splice($tree,0,$pos);
|
||||
$tree = array_merge($first, $tmp, $tree);
|
||||
} else {
|
||||
$tree = array_merge($tree,$tmp);
|
||||
}
|
||||
} else {
|
||||
$first = array_splice($tree,0,$index);
|
||||
array_splice($tree, 0, ($index + 1));
|
||||
$tree = array_merge($first, $tmp, $tree);
|
||||
}
|
||||
}
|
||||
return $tree;
|
||||
}
|
||||
|
||||
/**
|
||||
* flush saves all the records from all tables
|
||||
* this operation is isolated using a transaction
|
||||
* @return void
|
||||
*/
|
||||
public function flush() {
|
||||
$this->beginTransaction();
|
||||
$this->saveAll();
|
||||
$this->commit();
|
||||
}
|
||||
/**
|
||||
* saveAll save all the records from all tables
|
||||
*/
|
||||
private function saveAll() {
|
||||
$tree = $this->buildFlushTree();
|
||||
|
||||
foreach($tree as $name) {
|
||||
$table = $this->tables[$name];
|
||||
|
||||
foreach($table->getRepository() as $record) {
|
||||
$this->save($record);
|
||||
}
|
||||
}
|
||||
foreach($tree as $name) {
|
||||
$table = $this->tables[$name];
|
||||
foreach($table->getRepository() as $record) {
|
||||
$record->saveAssociations();
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* clear -- clears the whole registry
|
||||
* @return void
|
||||
*/
|
||||
public function clear() {
|
||||
foreach($this->tables as $k => $objTable) {
|
||||
$objTable->getRepository()->evictAll();
|
||||
}
|
||||
$this->tables = array();
|
||||
}
|
||||
/**
|
||||
* close
|
||||
* closes the session
|
||||
* @return void
|
||||
*/
|
||||
public function close() {
|
||||
$this->getAttribute(Doctrine::ATTR_LISTENER)->onPreClose($this);
|
||||
|
||||
$this->clear();
|
||||
$this->state = Doctrine_Session::STATE_CLOSED;
|
||||
|
||||
$this->getAttribute(Doctrine::ATTR_LISTENER)->onClose($this);
|
||||
}
|
||||
/**
|
||||
* get the current transaction nesting level
|
||||
* @return integer transaction nesting level
|
||||
*/
|
||||
public function getTransactionLevel() {
|
||||
return $this->transaction_level;
|
||||
}
|
||||
/**
|
||||
* beginTransaction
|
||||
* starts a new transaction
|
||||
* @return void
|
||||
*/
|
||||
public function beginTransaction() {
|
||||
if($this->transaction_level == 0) {
|
||||
|
||||
if($this->getAttribute(Doctrine::ATTR_LOCKMODE) == Doctrine::LOCK_PESSIMISTIC) {
|
||||
$this->getAttribute(Doctrine::ATTR_LISTENER)->onPreTransactionBegin($this);
|
||||
$this->dbh->beginTransaction();
|
||||
$this->getAttribute(Doctrine::ATTR_LISTENER)->onTransactionBegin($this);
|
||||
}
|
||||
$this->state = Doctrine_Session::STATE_ACTIVE;
|
||||
} else {
|
||||
$this->state = Doctrine_Session::STATE_BUSY;
|
||||
}
|
||||
$this->transaction_level++;
|
||||
}
|
||||
/**
|
||||
* commits the current transaction
|
||||
* if lockmode is optimistic this method starts a transaction
|
||||
* and commits it instantly
|
||||
* @return void
|
||||
*/
|
||||
public function commit() {
|
||||
$this->transaction_level--;
|
||||
|
||||
if($this->transaction_level == 0) {
|
||||
|
||||
|
||||
if($this->getAttribute(Doctrine::ATTR_LOCKMODE) == Doctrine::LOCK_OPTIMISTIC) {
|
||||
$this->getAttribute(Doctrine::ATTR_LISTENER)->onPreTransactionBegin($this);
|
||||
|
||||
$this->dbh->beginTransaction();
|
||||
|
||||
$this->getAttribute(Doctrine::ATTR_LISTENER)->onTransactionBegin($this);
|
||||
}
|
||||
|
||||
if($this->getAttribute(Doctrine::ATTR_VLD)) {
|
||||
$this->validator = new Doctrine_Validator();
|
||||
}
|
||||
|
||||
$this->bulkInsert();
|
||||
$this->bulkUpdate();
|
||||
$this->bulkDelete();
|
||||
|
||||
|
||||
if(isset($this->validator) && $this->validator->hasErrors()) {
|
||||
$this->rollback();
|
||||
throw new Doctrine_Validator_Exception($this->validator);
|
||||
}
|
||||
|
||||
$this->dbh->commit();
|
||||
$this->getAttribute(Doctrine::ATTR_LISTENER)->onTransactionCommit($this);
|
||||
|
||||
$this->delete = array(array());
|
||||
$this->state = Doctrine_Session::STATE_OPEN;
|
||||
|
||||
$this->validator = null;
|
||||
|
||||
} elseif($this->transaction_level == 1)
|
||||
$this->state = Doctrine_Session::STATE_ACTIVE;
|
||||
}
|
||||
/**
|
||||
* rollback
|
||||
* rolls back all the transactions
|
||||
* @return void
|
||||
*/
|
||||
public function rollback() {
|
||||
$this->getAttribute(Doctrine::ATTR_LISTENER)->onPreTransactionRollback($this);
|
||||
|
||||
$this->transaction_level = 0;
|
||||
$this->dbh->rollback();
|
||||
$this->state = Doctrine_Session::STATE_OPEN;
|
||||
|
||||
$this->getAttribute(Doctrine::ATTR_LISTENER)->onTransactionRollback($this);
|
||||
}
|
||||
/**
|
||||
* bulkInsert
|
||||
* inserts all the objects in the pending insert list into database
|
||||
* @return void
|
||||
*/
|
||||
public function bulkInsert() {
|
||||
foreach($this->insert as $name => $inserts) {
|
||||
if( ! isset($inserts[0]))
|
||||
continue;
|
||||
|
||||
$record = $inserts[0];
|
||||
$table = $record->getTable();
|
||||
$seq = $table->getSequenceName();
|
||||
$increment = false;
|
||||
$id = null;
|
||||
$keys = $table->getPrimaryKeys();
|
||||
if(count($keys) == 1 && $keys[0] == "id") {
|
||||
|
||||
// record uses auto_increment column
|
||||
|
||||
$sql = "SELECT MAX(id) FROM ".$record->getTable()->getTableName();
|
||||
$stmt = $this->dbh->query($sql);
|
||||
$data = $stmt->fetch(PDO::FETCH_NUM);
|
||||
$id = $data[0];
|
||||
$stmt->closeCursor();
|
||||
$increment = true;
|
||||
}
|
||||
|
||||
|
||||
foreach($inserts as $k => $record) {
|
||||
$record->getTable()->getAttribute(Doctrine::ATTR_LISTENER)->onPreSave($record);
|
||||
// listen the onPreInsert event
|
||||
$record->getTable()->getAttribute(Doctrine::ATTR_LISTENER)->onPreInsert($record);
|
||||
|
||||
if($increment) {
|
||||
// record uses auto_increment column
|
||||
$id++;
|
||||
}
|
||||
|
||||
$this->insert($record,$id);
|
||||
// listen the onInsert event
|
||||
$record->getTable()->getAttribute(Doctrine::ATTR_LISTENER)->onInsert($record);
|
||||
|
||||
$record->getTable()->getAttribute(Doctrine::ATTR_LISTENER)->onSave($record);
|
||||
|
||||
$record->getTable()->getCache()->store($record);
|
||||
}
|
||||
}
|
||||
$this->insert = array(array());
|
||||
}
|
||||
/**
|
||||
* bulkUpdate
|
||||
* updates all objects in the pending update list
|
||||
* @return void
|
||||
*/
|
||||
public function bulkUpdate() {
|
||||
foreach($this->update as $name => $updates) {
|
||||
foreach($updates as $k => $record) {
|
||||
$record->getTable()->getAttribute(Doctrine::ATTR_LISTENER)->onPreSave($record);
|
||||
// listen the onPreUpdate event
|
||||
$record->getTable()->getAttribute(Doctrine::ATTR_LISTENER)->onPreUpdate($record);
|
||||
|
||||
$this->update($record);
|
||||
// listen the onUpdate event
|
||||
$record->getTable()->getAttribute(Doctrine::ATTR_LISTENER)->onUpdate($record);
|
||||
|
||||
$record->getTable()->getAttribute(Doctrine::ATTR_LISTENER)->onSave($record);
|
||||
}
|
||||
}
|
||||
$this->update = array(array());
|
||||
}
|
||||
/**
|
||||
* bulkDelete
|
||||
* @return void
|
||||
*/
|
||||
public function bulkDelete() {
|
||||
foreach($this->delete as $name => $deletes) {
|
||||
$record = false;
|
||||
$ids = array();
|
||||
foreach($deletes as $k => $record) {
|
||||
$ids[] = $record->getID();
|
||||
$record->setID(null);
|
||||
}
|
||||
if($record instanceof Doctrine_Record) {
|
||||
$params = substr(str_repeat("?, ",count($ids)),0,-2);
|
||||
$query = "DELETE FROM ".$record->getTable()->getTableName()." WHERE id IN(".$params.")";
|
||||
$this->execute($query,$ids);
|
||||
|
||||
$record->getTable()->getCache()->deleteMultiple($ids);
|
||||
}
|
||||
}
|
||||
$this->delete = array(array());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param Doctrine_Collection $coll
|
||||
* @return void
|
||||
*/
|
||||
public function saveCollection(Doctrine_Collection $coll) {
|
||||
$this->beginTransaction();
|
||||
|
||||
foreach($coll as $key=>$record):
|
||||
$record->save();
|
||||
endforeach;
|
||||
|
||||
$this->commit();
|
||||
}
|
||||
/**
|
||||
* @param Doctrine_Collection $coll
|
||||
* @return void
|
||||
*/
|
||||
public function deleteCollection(Doctrine_Collection $coll) {
|
||||
$this->beginTransaction();
|
||||
foreach($coll as $k=>$record) {
|
||||
$record->delete();
|
||||
}
|
||||
$this->commit();
|
||||
}
|
||||
/**
|
||||
* @param Doctrine_Record $record
|
||||
* @return void
|
||||
*/
|
||||
|
||||
public function save(Doctrine_Record $record) {
|
||||
|
||||
switch($record->getState()):
|
||||
case Doctrine_Record::STATE_TDIRTY:
|
||||
$this->addInsert($record);
|
||||
break;
|
||||
case Doctrine_Record::STATE_DIRTY:
|
||||
case Doctrine_Record::STATE_PROXY:
|
||||
$this->addUpdate($record);
|
||||
break;
|
||||
case Doctrine_Record::STATE_CLEAN:
|
||||
case Doctrine_Record::STATE_TCLEAN:
|
||||
// do nothing
|
||||
break;
|
||||
endswitch;
|
||||
}
|
||||
/**
|
||||
* @param Doctrine_Record $record
|
||||
*/
|
||||
final public function saveRelated(Doctrine_Record $record) {
|
||||
$saveLater = array();
|
||||
foreach($record->getReferences() as $k=>$v) {
|
||||
$fk = $record->getTable()->getForeignKey($k);
|
||||
if($fk instanceof Doctrine_ForeignKey ||
|
||||
$fk instanceof Doctrine_LocalKey) {
|
||||
switch($fk->getType()):
|
||||
case Doctrine_Table::ONE_COMPOSITE:
|
||||
case Doctrine_Table::MANY_COMPOSITE:
|
||||
$local = $fk->getLocal();
|
||||
$foreign = $fk->getForeign();
|
||||
|
||||
if($record->getTable()->hasPrimaryKey($fk->getLocal())) {
|
||||
switch($record->getState()):
|
||||
case Doctrine_Record::STATE_TDIRTY:
|
||||
case Doctrine_Record::STATE_TCLEAN:
|
||||
$saveLater[$k] = $fk;
|
||||
break;
|
||||
case Doctrine_Record::STATE_CLEAN:
|
||||
case Doctrine_Record::STATE_DIRTY:
|
||||
$v->save();
|
||||
break;
|
||||
endswitch;
|
||||
} else {
|
||||
// ONE-TO-ONE relationship
|
||||
$obj = $record->get($fk->getTable()->getComponentName());
|
||||
|
||||
if($obj->getState() != Doctrine_Record::STATE_TCLEAN)
|
||||
$obj->save();
|
||||
|
||||
}
|
||||
break;
|
||||
endswitch;
|
||||
} elseif($fk instanceof Doctrine_Association) {
|
||||
$v->save();
|
||||
}
|
||||
}
|
||||
return $saveLater;
|
||||
}
|
||||
/**
|
||||
* @param Doctrine_Record $record
|
||||
* @return boolean
|
||||
*/
|
||||
private function update(Doctrine_Record $record) {
|
||||
$array = $record->getModified();
|
||||
if(empty($array))
|
||||
return false;
|
||||
|
||||
|
||||
|
||||
$set = array();
|
||||
foreach($array as $name => $value):
|
||||
$set[] = $name." = ?";
|
||||
|
||||
if($value instanceof Doctrine_Record) {
|
||||
$array[$name] = $value->getID();
|
||||
$record->set($name, $value->getID());
|
||||
}
|
||||
endforeach;
|
||||
|
||||
if(isset($this->validator)) {
|
||||
if( ! $this->validator->validateRecord($record)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$params = array_values($array);
|
||||
$params[] = $record->getID();
|
||||
|
||||
|
||||
$sql = "UPDATE ".$record->getTable()->getTableName()." SET ".implode(", ",$set)." WHERE ".implode(" = ? && ",$record->getTable()->getPrimaryKeys())." = ?";
|
||||
$stmt = $this->dbh->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
|
||||
$record->setID($record->getID());
|
||||
|
||||
$record->getTable()->getCache()->delete($record->getID());
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @param Doctrine_Record $record
|
||||
* @return boolean
|
||||
*/
|
||||
private function insert(Doctrine_Record $record,$id = null) {
|
||||
$array = $record->getModified();
|
||||
if(empty($array))
|
||||
return false;
|
||||
|
||||
|
||||
foreach($record->getTable()->getInheritanceMap() as $k=>$v):
|
||||
$array[$k] = $v;
|
||||
endforeach;
|
||||
|
||||
$seq = $record->getTable()->getSequenceName();
|
||||
if( ! empty($seq)) {
|
||||
$id = $this->getNextID($seq);
|
||||
$array["id"] = $id;
|
||||
}
|
||||
|
||||
foreach($array as $k => $value) {
|
||||
if($value instanceof Doctrine_Record) {
|
||||
$array[$k] = $value->getID();
|
||||
$record->set($k,$value->getID());
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($this->validator)) {
|
||||
if( ! $this->validator->validateRecord($record)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$strfields = join(", ", array_keys($array));
|
||||
$strvalues = substr(str_repeat("?, ",count($array)),0,-2);
|
||||
|
||||
$sql = "INSERT INTO ".$record->getTable()->getTableName()." (".$strfields.") VALUES (".$strvalues.")";
|
||||
|
||||
$stmt = $this->dbh->prepare($sql);
|
||||
|
||||
$stmt->execute(array_values($array));
|
||||
|
||||
$record->setID($id);
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* deletes all related composites
|
||||
* this method is always called internally when this data access object is deleted
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
final public function deleteComposites(Doctrine_Record $record) {
|
||||
foreach($record->getTable()->getForeignKeys() as $fk) {
|
||||
switch($fk->getType()):
|
||||
case Doctrine_Table::ONE_COMPOSITE:
|
||||
case Doctrine_Table::MANY_COMPOSITE:
|
||||
$obj = $record->get($fk->getTable()->getComponentName());
|
||||
$obj->delete();
|
||||
break;
|
||||
endswitch;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* deletes this data access object and all the related composites
|
||||
* this operation is isolated by a transaction
|
||||
*
|
||||
* this event can be listened by the onPreDelete and onDelete listeners
|
||||
*
|
||||
* @return boolean true on success, false on failure
|
||||
*/
|
||||
final public function delete(Doctrine_Record $record) {
|
||||
switch($record->getState()):
|
||||
case Doctrine_Record::STATE_PROXY:
|
||||
case Doctrine_Record::STATE_CLEAN:
|
||||
case Doctrine_Record::STATE_DIRTY:
|
||||
$this->beginTransaction();
|
||||
|
||||
$this->deleteComposites($record);
|
||||
$this->addDelete($record);
|
||||
|
||||
$this->commit();
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
endswitch;
|
||||
}
|
||||
/**
|
||||
* adds data access object into pending insert list
|
||||
* @param Doctrine_Record $record
|
||||
*/
|
||||
public function addInsert(Doctrine_Record $record) {
|
||||
$name = $record->getTable()->getComponentName();
|
||||
$this->insert[$name][] = $record;
|
||||
}
|
||||
/**
|
||||
* adds data access object into penging update list
|
||||
* @param Doctrine_Record $record
|
||||
*/
|
||||
public function addUpdate(Doctrine_Record $record) {
|
||||
$name = $record->getTable()->getComponentName();
|
||||
$this->update[$name][] = $record;
|
||||
}
|
||||
/**
|
||||
* adds data access object into pending delete list
|
||||
* @param Doctrine_Record $record
|
||||
*/
|
||||
public function addDelete(Doctrine_Record $record) {
|
||||
$name = $record->getTable()->getComponentName();
|
||||
$this->delete[$name][] = $record;
|
||||
}
|
||||
/**
|
||||
* returns a string representation of this object
|
||||
* @return string
|
||||
*/
|
||||
public function __toString() {
|
||||
return Doctrine_Lib::getSessionAsString($this);
|
||||
}
|
||||
}
|
||||
?>
|
10
classes/Session/Common.class.php
Normal file
10
classes/Session/Common.class.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
/**
|
||||
* standard session, the parent of pgsql, mysql and sqlite
|
||||
*/
|
||||
class Doctrine_Session_Common extends Doctrine_Session {
|
||||
public function modifyLimitQuery($query,$limit,$offset) {
|
||||
return $query." LIMIT ".$limit." OFFSET ".$offset;
|
||||
}
|
||||
}
|
||||
?>
|
20
classes/Session/Firebird.class.php
Normal file
20
classes/Session/Firebird.class.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* firebird driver
|
||||
*/
|
||||
class Doctrine_Session_Firebird extends Doctrine_Session {
|
||||
public function modifyLimitQuery($query,$limit,$offset) {
|
||||
return preg_replace("/([\s(])*SELECT/i","\\1SELECT TOP($from, $count)", $query);
|
||||
}
|
||||
/**
|
||||
* returns the next value in the given sequence
|
||||
* @param string $sequence
|
||||
* @return integer
|
||||
*/
|
||||
public function getNextID($sequence) {
|
||||
$stmt = $this->query("SELECT UNIQUE FROM ".$sequence);
|
||||
$data = $stmt->fetch(PDO::FETCH_NUM);
|
||||
return $data[0];
|
||||
}
|
||||
}
|
||||
?>
|
6
classes/Session/Informix.class.php
Normal file
6
classes/Session/Informix.class.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* informix database driver
|
||||
*/
|
||||
class Doctrine_Session_Informix extends Doctrine_Session { }
|
||||
?>
|
18
classes/Session/Mssql.class.php
Normal file
18
classes/Session/Mssql.class.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* mssql driver
|
||||
*/
|
||||
class Doctrine_Session_Mssql extends Doctrine_Session {
|
||||
/**
|
||||
* returns the next value in the given sequence
|
||||
* @param string $sequence
|
||||
* @return integer
|
||||
*/
|
||||
public function getNextID($sequence) {
|
||||
$this->query("INSERT INTO $sequence (vapor) VALUES (0)");
|
||||
$stmt = $this->query("SELECT @@IDENTITY FROM $sequence");
|
||||
$data = $stmt->fetch(PDO::FETCH_NUM);
|
||||
return $data[0];
|
||||
}
|
||||
}
|
||||
?>
|
38
classes/Session/Mysql.class.php
Normal file
38
classes/Session/Mysql.class.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
* mysql driver
|
||||
*/
|
||||
class Doctrine_Session_Mysql extends Doctrine_Session_Common {
|
||||
/**
|
||||
* deletes all data access object from the collection
|
||||
* @param Doctrine_Collection $coll
|
||||
*/
|
||||
|
||||
/**
|
||||
public function deleteCollection(Doctrine_Collection $coll) {
|
||||
|
||||
$a = $coll->getTable()->getCompositePaths();
|
||||
$a = array_merge(array($coll->getTable()->getComponentName()),$a);
|
||||
|
||||
$graph = new Doctrine_DQL_Parser($this);
|
||||
foreach($coll as $k=>$record) {
|
||||
switch($record->getState()):
|
||||
case Doctrine_Record::STATE_DIRTY:
|
||||
case Doctrine_Record::STATE_CLEAN:
|
||||
$ids[] = $record->getID();
|
||||
break;
|
||||
endswitch;
|
||||
}
|
||||
if(empty($ids))
|
||||
return array();
|
||||
|
||||
$graph->parseQuery("FROM ".implode(", ",$a)." WHERE ".$coll->getTable()->getTableName().".id IN(".implode(", ",$ids).")");
|
||||
|
||||
$query = $graph->buildDelete();
|
||||
|
||||
$this->getDBH()->query($query);
|
||||
return $ids;
|
||||
}
|
||||
*/
|
||||
}
|
||||
?>
|
25
classes/Session/Oracle.class.php
Normal file
25
classes/Session/Oracle.class.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* oracle driver
|
||||
*/
|
||||
class Doctrine_Session_Oracle extends Doctrine_Session {
|
||||
public function modifyLimitQuery($query,$limit,$offset) {
|
||||
$e = explode("select ",strtolower($query));
|
||||
$e2 = explode(" from ",$e[1]);
|
||||
$fields = $e2[0];
|
||||
|
||||
$query = "SELECT $fields FROM (SELECT rownum as linenum, $fields FROM ($query) WHERE rownum <= ($offset + $limit)) WHERE linenum >= ".++$offset;
|
||||
return $query;
|
||||
}
|
||||
/**
|
||||
* returns the next value in the given sequence
|
||||
* @param string $sequence
|
||||
* @return integer
|
||||
*/
|
||||
public function getNextID($sequence) {
|
||||
$stmt = $this->query("SELECT $sequence.nextval FROM dual");
|
||||
$data = $stmt->fetch(PDO::FETCH_NUM);
|
||||
return $data[0];
|
||||
}
|
||||
}
|
||||
?>
|
17
classes/Session/Pgsql.class.php
Normal file
17
classes/Session/Pgsql.class.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* pgsql driver
|
||||
*/
|
||||
class Doctrine_Session_Pgsql extends Doctrine_Session_Common {
|
||||
/**
|
||||
* returns the next value in the given sequence
|
||||
* @param string $sequence
|
||||
* @return integer
|
||||
*/
|
||||
public function getNextID($sequence) {
|
||||
$stmt = $this->query("SELECT NEXTVAL('$sequence')");
|
||||
$data = $stmt->fetch(PDO::FETCH_NUM);
|
||||
return $data[0];
|
||||
}
|
||||
}
|
||||
?>
|
6
classes/Session/Sqlite.class.php
Normal file
6
classes/Session/Sqlite.class.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* sqlite driver
|
||||
*/
|
||||
class Doctrine_Session_Sqlite extends Doctrine_Session_Common { }
|
||||
?>
|
617
classes/Table.class.php
Normal file
617
classes/Table.class.php
Normal file
@ -0,0 +1,617 @@
|
||||
<?php
|
||||
require_once("Configurable.class.php");
|
||||
/**
|
||||
* Doctrine_Table represents a database table
|
||||
* each Doctrine_Table holds the information of foreignKeys and associations
|
||||
*
|
||||
*
|
||||
* @author Konsta Vesterinen
|
||||
* @package Doctrine ORM
|
||||
* @url www.phpdoctrine.com
|
||||
* @license LGPL
|
||||
* @version 1.0 alpha
|
||||
*/
|
||||
class Doctrine_Table extends Doctrine_Configurable {
|
||||
/**
|
||||
* constant for ONE_TO_ONE and MANY_TO_ONE aggregate relationships
|
||||
*/
|
||||
const ONE_AGGREGATE = 0;
|
||||
/**
|
||||
* constant for ONE_TO_ONE and MANY_TO_ONE composite relationships
|
||||
*/
|
||||
const ONE_COMPOSITE = 1;
|
||||
/**
|
||||
* constant for MANY_TO_MANY and ONE_TO_MANY aggregate relationships
|
||||
*/
|
||||
const MANY_AGGREGATE = 2;
|
||||
/**
|
||||
* constant for MANY_TO_MANY and ONE_TO_MANY composite relationships
|
||||
*/
|
||||
const MANY_COMPOSITE = 3;
|
||||
|
||||
/**
|
||||
* @var boolean $isNewEntry whether ot not this table created a new record or not, used only internally
|
||||
*/
|
||||
private $isNewEntry = false;
|
||||
/**
|
||||
* @var array $data temporary data which is then loaded into Doctrine_Record::$data
|
||||
*/
|
||||
private $data = array();
|
||||
/**
|
||||
* @var array $foreignKeys an array containing all the Doctrine_ForeignKey objects for this table
|
||||
*/
|
||||
private $foreignKeys = array();
|
||||
/**
|
||||
* @var array $primaryKeys an array containing all primary key column names
|
||||
*/
|
||||
private $primaryKeys = array();
|
||||
/**
|
||||
* @var integer $primaryType
|
||||
*/
|
||||
private $primaryType;
|
||||
/**
|
||||
* @var string $query cached simple query
|
||||
*/
|
||||
private $query;
|
||||
/**
|
||||
* @var Doctrine_Session $session Doctrine_Session object that created this table
|
||||
*/
|
||||
private $session;
|
||||
/**
|
||||
* @var string $name name of the component, for example component name of the GroupTable is 'Group'
|
||||
*/
|
||||
private $name;
|
||||
/**
|
||||
* @var string $tableName database table name, in most cases this is the same as component name but in some cases
|
||||
* where one-table-multi-class inheritance is used this will be the name of the inherited table
|
||||
*/
|
||||
private $tableName;
|
||||
/**
|
||||
* @var string $sequenceName Some databases need sequences instead of auto incrementation primary keys, you can set specific
|
||||
* sequence for your table by calling setSequenceName()
|
||||
*/
|
||||
private $sequenceName;
|
||||
/**
|
||||
* @var Doctrine_Repository $repository first level cache
|
||||
*/
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* @var Doctrine_Cache $cache second level cache
|
||||
*/
|
||||
private $cache;
|
||||
/**
|
||||
* @var Doctrine_Table_Description $description columns object for this table
|
||||
*/
|
||||
private $columns;
|
||||
/**
|
||||
* @var array $bound bound relations
|
||||
*/
|
||||
private $bound = array();
|
||||
/**
|
||||
* @var array $inheritanceMap inheritanceMap is used for inheritance mapping, keys representing columns and values
|
||||
* the column values that should correspond to child classes
|
||||
*/
|
||||
private $inheritanceMap = array();
|
||||
/**
|
||||
* @var array $parents the parent classes of this component
|
||||
*/
|
||||
private $parents = array();
|
||||
|
||||
/**
|
||||
* the constructor
|
||||
* @throws Doctrine_ManagerException if there are no opened sessions
|
||||
* @throws Doctrine_TableException if there is already an instance of this table
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($name) {
|
||||
$this->session = Doctrine_Manager::getInstance()->getCurrentSession();
|
||||
|
||||
$this->setParent($this->session);
|
||||
|
||||
$name = ucwords(strtolower($name));
|
||||
|
||||
$this->name = $name;
|
||||
|
||||
if( ! class_exists($name) || empty($name))
|
||||
throw new Doctrine_Exception("Couldn't find class $name");
|
||||
|
||||
$record = new $name($this);
|
||||
$record->setUp();
|
||||
|
||||
$names = array();
|
||||
|
||||
$class = $name;
|
||||
|
||||
|
||||
|
||||
// get parent classes
|
||||
|
||||
do {
|
||||
if($class == "Doctrine_Record") break;
|
||||
|
||||
$name = ucwords(strtolower($class));
|
||||
$names[] = $name;
|
||||
} while($class = get_parent_class($class));
|
||||
|
||||
// reverse names
|
||||
$names = array_reverse($names);
|
||||
|
||||
|
||||
// create database table
|
||||
if(method_exists($record,"setTableDefinition")) {
|
||||
$record->setTableDefinition();
|
||||
|
||||
if(isset($this->columns)) {
|
||||
$method = new ReflectionMethod($name,"setTableDefinition");
|
||||
$class = $method->getDeclaringClass();
|
||||
|
||||
if( ! isset($this->tableName))
|
||||
$this->tableName = strtolower($class->getName());
|
||||
|
||||
switch(count($this->primaryKeys)):
|
||||
case 0:
|
||||
$this->columns = array_merge(array("id" => array("integer",11,"AUTOINCREMENT PRIMARY")), $this->columns);
|
||||
$this->primaryKeys[] = "id";
|
||||
break;
|
||||
case 1:
|
||||
|
||||
break;
|
||||
default:
|
||||
|
||||
endswitch;
|
||||
|
||||
if($this->getAttribute(Doctrine::ATTR_CREATE_TABLES)) {
|
||||
$dict = new Doctrine_DataDict($this);
|
||||
$dict->createTable($this->columns);
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
throw new Doctrine_Exception("Class '$name' has no table definition.");
|
||||
}
|
||||
|
||||
// save parents
|
||||
array_pop($names);
|
||||
$this->parents = $names;
|
||||
|
||||
$this->query = "SELECT ".implode(", ",array_keys($this->columns))." FROM ".$this->getTableName();
|
||||
|
||||
// check if an instance of this table is already initialized
|
||||
if( ! $this->session->addTable($this))
|
||||
throw new Doctrine_Table_Exception();
|
||||
|
||||
$this->initComponents();
|
||||
}
|
||||
/**
|
||||
* initializes components this table uses
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
final public function initComponents() {
|
||||
$this->repository = new Doctrine_Repository($this);
|
||||
|
||||
switch($this->getAttribute(Doctrine::ATTR_CACHE)):
|
||||
case Doctrine::CACHE_FILE:
|
||||
$this->cache = new Doctrine_Cache_File($this);
|
||||
break;
|
||||
case Doctrine::CACHE_NONE:
|
||||
$this->cache = new Doctrine_Cache($this);
|
||||
break;
|
||||
endswitch;
|
||||
}
|
||||
/**
|
||||
* hasColumn
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @param integer $length
|
||||
* @param mixed $options
|
||||
* @return void
|
||||
*/
|
||||
final public function hasColumn($name, $type, $length, $options = "") {
|
||||
$this->columns[$name] = array($type,$length,$options);
|
||||
|
||||
$e = explode("|",$options);
|
||||
if(in_array("primary",$e)) {
|
||||
$this->primaryKeys[] = $name;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* returns all primary keys
|
||||
* @return array
|
||||
*/
|
||||
final public function getPrimaryKeys() {
|
||||
return $this->primaryKeys;
|
||||
}
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
final public function hasPrimaryKey($key) {
|
||||
return in_array($key,$this->primaryKeys);
|
||||
}
|
||||
/**
|
||||
* @param $sequence
|
||||
* @return void
|
||||
*/
|
||||
final public function setSequenceName($sequence) {
|
||||
$this->sequenceName = $sequence;
|
||||
}
|
||||
/**
|
||||
* @return string sequence name
|
||||
*/
|
||||
final public function getSequenceName() {
|
||||
return $this->sequenceName;
|
||||
}
|
||||
/**
|
||||
* setInheritanceMap
|
||||
* @param array $inheritanceMap
|
||||
* @return void
|
||||
*/
|
||||
final public function setInheritanceMap(array $inheritanceMap) {
|
||||
$this->inheritanceMap = $inheritanceMap;
|
||||
}
|
||||
/**
|
||||
* @return array inheritance map (array keys as fields)
|
||||
*/
|
||||
final public function getInheritanceMap() {
|
||||
return $this->inheritanceMap;
|
||||
}
|
||||
/**
|
||||
* return all composite paths in the form [component1].[component2]. . .[componentN]
|
||||
* @return array
|
||||
*/
|
||||
final public function getCompositePaths() {
|
||||
$array = array();
|
||||
$name = $this->getComponentName();
|
||||
foreach($this->bound as $k=>$a) {
|
||||
try {
|
||||
$fk = $this->getForeignKey($k);
|
||||
switch($fk->getType()):
|
||||
case Doctrine_Table::ONE_COMPOSITE:
|
||||
case Doctrine_Table::MANY_COMPOSITE:
|
||||
$n = $fk->getTable()->getComponentName();
|
||||
$array[] = $name.".".$n;
|
||||
$e = $fk->getTable()->getCompositePaths();
|
||||
if( ! empty($e)) {
|
||||
foreach($e as $name) {
|
||||
$array[] = $name.".".$n.".".$name;
|
||||
}
|
||||
}
|
||||
break;
|
||||
endswitch;
|
||||
} catch(InvalidKeyException $e) {
|
||||
|
||||
}
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
/**
|
||||
* @var array bound relations
|
||||
*/
|
||||
final public function getBounds() {
|
||||
return $this->bound;
|
||||
}
|
||||
/**
|
||||
* @param string $name
|
||||
*/
|
||||
final public function getBound($name) {
|
||||
if( ! isset($this->bound[$name]))
|
||||
throw new InvalidKeyException();
|
||||
|
||||
return $this->bound[$name];
|
||||
}
|
||||
/**
|
||||
* @param string $objTableName
|
||||
* @param string $fkField
|
||||
* @return void
|
||||
*/
|
||||
final public function bind($objTableName,$fkField,$type,$localKey) {
|
||||
$name = (string) $objTableName;
|
||||
$field = (string) $fkField;
|
||||
|
||||
if(isset($this->foreignKeys[$name]))
|
||||
throw new InvalidKeyException();
|
||||
|
||||
$e = explode(".", $field);
|
||||
|
||||
// is reference table used?
|
||||
if($e[0] != $name && $e[0] == $this->name)
|
||||
$this->bound[$name] = array($field,Doctrine_Table::MANY_COMPOSITE);
|
||||
|
||||
$this->bound[$name] = array($field,$type,$localKey);
|
||||
}
|
||||
/**
|
||||
* getComponentName
|
||||
* @return string the component name
|
||||
*/
|
||||
final public function getComponentName() {
|
||||
return $this->name;
|
||||
}
|
||||
/**
|
||||
* @return Doctrine_Session
|
||||
*/
|
||||
final public function getSession() {
|
||||
return $this->session;
|
||||
}
|
||||
/**
|
||||
* @return Doctrine_Cache
|
||||
*/
|
||||
final public function getCache() {
|
||||
return $this->cache;
|
||||
}
|
||||
/**
|
||||
* @return Doctrine_Repository
|
||||
*/
|
||||
final public function getRepository() {
|
||||
return $this->repository;
|
||||
}
|
||||
/**
|
||||
* @param string $name component name of which a foreign key object is bound
|
||||
* @return Doctrine_ForeignKey
|
||||
*/
|
||||
final public function getForeignKey($name) {
|
||||
if(isset($this->foreignKeys[$name]))
|
||||
return $this->foreignKeys[$name];
|
||||
|
||||
if(isset($this->bound[$name])) {
|
||||
$type = $this->bound[$name][1];
|
||||
$field = $this->bound[$name][0];
|
||||
$e = explode(".",$field);
|
||||
$objTable = $this->session->getTable($name);
|
||||
|
||||
switch($e[0]):
|
||||
case $name:
|
||||
// ONE-TO-MANY or ONE-TO-ONE
|
||||
$foreignKey = new Doctrine_ForeignKey($objTable,$this->bound[$name][2],$e[1],$type);
|
||||
break;
|
||||
case $this->name:
|
||||
// ONE-TO-ONE
|
||||
|
||||
if($type <= Doctrine_Table::ONE_COMPOSITE)
|
||||
$foreignKey = new Doctrine_LocalKey($objTable,$e[1],$this->bound[$name][2],$type);
|
||||
else
|
||||
throw new Doctrine_Mapping_Exception();
|
||||
break;
|
||||
default:
|
||||
if(in_array($e[0], $this->parents)) {
|
||||
// ONE-TO-ONE
|
||||
if($type <= Doctrine_Table::ONE_COMPOSITE)
|
||||
$foreignKey = new Doctrine_LocalKey($objTable,$e[1],$this->bound[$name][2],$type);
|
||||
else
|
||||
throw new Doctrine_Mapping_Exception();
|
||||
} else {
|
||||
// POSSIBLY MANY-TO-MANY
|
||||
$bound = $objTable->getBound($this->name);
|
||||
$e2 = explode(".",$bound[0]);
|
||||
|
||||
if($e2[0] != $e[0])
|
||||
throw new Doctrine_Mapping_Exception();
|
||||
|
||||
$associationTable = $this->session->getTable($e2[0]);
|
||||
|
||||
$this->foreignKeys[$e2[0]] = new Doctrine_ForeignKey($associationTable,$this->bound[$name][2],$e2[1],Doctrine_Table::MANY_COMPOSITE);
|
||||
|
||||
$foreignKey = new Doctrine_Association($objTable,$associationTable,$e2[1],$e[1],$type);
|
||||
}
|
||||
endswitch;
|
||||
$this->foreignKeys[$name] = $foreignKey;
|
||||
return $this->foreignKeys[$name];
|
||||
} else {
|
||||
throw new InvalidKeyException();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @return array an array containing all foreign key objects
|
||||
*/
|
||||
final public function getForeignKeys() {
|
||||
$a = array();
|
||||
foreach($this->bound as $k=>$v) {
|
||||
$a[$k] = $this->getForeignKey($k);
|
||||
}
|
||||
return $a;
|
||||
}
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
final public function setTableName($name) {
|
||||
$this->tableName = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string database table name this class represents
|
||||
*/
|
||||
final public function getTableName() {
|
||||
return $this->tableName;
|
||||
}
|
||||
/**
|
||||
* createDAO
|
||||
* @param $array an array where keys are field names and values representing field values
|
||||
* @return Doctrine_Record A new Data Access Object. Uses an sql insert statement when saved
|
||||
*/
|
||||
final public function create(array $array = array()) {
|
||||
$this->data = $array;
|
||||
$this->isNewEntry = true;
|
||||
$record = $this->getRecord();
|
||||
$this->isNewEntry = false;
|
||||
return $record;
|
||||
}
|
||||
/**
|
||||
* @param $id database row id
|
||||
* @throws Doctrine_Find_Exception
|
||||
* @return DAOProxy a proxy for given database row, if the id is not set method
|
||||
* uses internal factory data (= data that was fetched by datagraph or collection)
|
||||
*/
|
||||
final public function find($id = null) {
|
||||
if($id !== null) {
|
||||
try {
|
||||
// try to get from cache
|
||||
$record = $this->cache->fetch($id);
|
||||
return $record;
|
||||
} catch(InvalidKeyException $e) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
$query = $this->query." WHERE ".implode(" = ? && ",$this->primaryKeys)." = ?";
|
||||
$query = $this->applyInheritance($query);
|
||||
|
||||
$params = array_merge(array($id), array_values($this->inheritanceMap));
|
||||
|
||||
$this->data = $this->session->execute($query,$params)->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if($this->data === false)
|
||||
throw new Doctrine_Find_Exception();
|
||||
}
|
||||
return $this->getRecord();
|
||||
}
|
||||
/**
|
||||
* applyInheritance
|
||||
* @param $where query where part to be modified
|
||||
* @return query where part with column aggregation inheritance added
|
||||
*/
|
||||
final public function applyInheritance($where) {
|
||||
if( ! empty($this->inheritanceMap)) {
|
||||
$a = array();
|
||||
foreach($this->inheritanceMap as $field => $value) {
|
||||
$a[] = $field." = ?";
|
||||
}
|
||||
$i = implode(" && ",$a);
|
||||
$where .= " && $i";
|
||||
}
|
||||
return $where;
|
||||
}
|
||||
/**
|
||||
* findAll
|
||||
* @return Doctrine_Collection a collection of all data access objects
|
||||
*/
|
||||
final public function findAll() {
|
||||
$graph = new Doctrine_DQL_Parser($this->session);
|
||||
$users = $graph->query("FROM ".$this->name);
|
||||
return $users;
|
||||
}
|
||||
/**
|
||||
* findBySql
|
||||
* @return Doctrine_Collection a collection of data access objects
|
||||
*/
|
||||
final public function findBySql($sql) {
|
||||
$graph = new Doctrine_DQL_Parser($this->session);
|
||||
$users = $graph->query("FROM ".$this->name." WHERE ".$sql);
|
||||
return $users;
|
||||
}
|
||||
/**
|
||||
* getRecord
|
||||
* @return Doctrine_Record
|
||||
*/
|
||||
public function getRecord() {
|
||||
return new $this->name($this);
|
||||
}
|
||||
/**
|
||||
* @param $id database row id
|
||||
* @throws Doctrine_Find_Exception
|
||||
* @return DAOProxy a proxy for given database row, if the id is not set method
|
||||
* uses internal factory data (= data that was fetched by datagraph or collection)
|
||||
*/
|
||||
final public function getProxy($id = null) {
|
||||
if($id !== null) {
|
||||
$id = (int) $id;
|
||||
try {
|
||||
// try to get from cache
|
||||
$record = $this->cache->fetch($id);
|
||||
return $record;
|
||||
} catch(InvalidKeyException $e) {
|
||||
// do nothing
|
||||
}
|
||||
$query = "SELECT ".implode(", ",$this->primaryKeys)." FROM ".$this->getTableName()." WHERE ".implode(" = ? && ",$this->primaryKeys)." = ?";
|
||||
$query = $this->applyInheritance($query);
|
||||
|
||||
$params = array_merge(array($id), array_values($this->inheritanceMap));
|
||||
|
||||
$this->data = $this->session->execute($query,$params)->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if($this->data === false)
|
||||
throw new Doctrine_Find_Exception();
|
||||
}
|
||||
return $this->getRecord();
|
||||
}
|
||||
/**
|
||||
* getTableDescription
|
||||
* @return Doctrine_Table_Description the columns object for this factory
|
||||
*/
|
||||
final public function getTableDescription() {
|
||||
return $this->columns;
|
||||
}
|
||||
/**
|
||||
* @param integer $fetchMode
|
||||
* @return Doctrine_DQL_Parser a Doctrine_DQL_Parser object
|
||||
*/
|
||||
public function getDQLParser() {
|
||||
$graph = new Doctrine_DQL_Parser($this->getSession());
|
||||
$graph->load($this->getComponentName());
|
||||
return $graph;
|
||||
}
|
||||
/**
|
||||
* execute
|
||||
*/
|
||||
public function execute($query, array $array = array()) {
|
||||
$coll = new Doctrine_Collection($this);
|
||||
$stmt = $this->session->getDBH()->prepare($query);
|
||||
$stmt->execute($array);
|
||||
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
$stmt->closeCursor();
|
||||
|
||||
foreach($data as $row) {
|
||||
$this->data = $row;
|
||||
try {
|
||||
$record = $this->getCache()->fetch($this->data["id"]);
|
||||
} catch(InvalidKeyException $e) {
|
||||
$record = $this->getRecord();
|
||||
}
|
||||
$coll->add($record);
|
||||
}
|
||||
return $coll;
|
||||
}
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
final public function getColumns() {
|
||||
return $this->columns;
|
||||
}
|
||||
/**
|
||||
* @return array an array containing all the column names
|
||||
*/
|
||||
public function getColumnNames() {
|
||||
return array_keys($this->columns);
|
||||
}
|
||||
/**
|
||||
* setData
|
||||
* @param array $data internal data, users are strongly discouraged to use this function
|
||||
* @return void
|
||||
*/
|
||||
public function setData(array $data) {
|
||||
$this->data = $data;
|
||||
}
|
||||
/**
|
||||
* @return boolean whether or not a newly created object is new or not
|
||||
*/
|
||||
final public function isNewEntry() {
|
||||
return $this->isNewEntry;
|
||||
}
|
||||
/**
|
||||
* @return string simple cached query
|
||||
*/
|
||||
final public function getQuery() {
|
||||
return $this->query;
|
||||
}
|
||||
/**
|
||||
* @return array internal data, used by Doctrine_Record instances when retrieving data from database
|
||||
*/
|
||||
final public function getData() {
|
||||
return $this->data;
|
||||
}
|
||||
/**
|
||||
* @return string string representation of this object
|
||||
*/
|
||||
public function __toString() {
|
||||
return Doctrine_Lib::getTableAsString($this);
|
||||
}
|
||||
}
|
||||
?>
|
111
classes/Validator.class.php
Normal file
111
classes/Validator.class.php
Normal file
@ -0,0 +1,111 @@
|
||||
<?php
|
||||
class Doctrine_Validator {
|
||||
const ERR_LENGTH = 0;
|
||||
const ERR_TYPE = 1;
|
||||
const ERR_VALID = 2;
|
||||
const ERR_UNIQUE = 3;
|
||||
|
||||
/**
|
||||
* @var array $stack error stack
|
||||
*/
|
||||
private $stack = array();
|
||||
/**
|
||||
* @var array $validators
|
||||
*/
|
||||
private static $validators = array();
|
||||
/**
|
||||
* @param string $name
|
||||
*/
|
||||
public static function getValidator($name) {
|
||||
if( ! isset(self::$validators[$name])) {
|
||||
$class = "Doctrine_Validator_".ucwords(strtolower($name));
|
||||
if(class_exists($class)) {
|
||||
self::$validators[$name] = new $class;
|
||||
} elseif(class_exists($name."Validator")) {
|
||||
self::$validators[$name] = new $name."Validator";
|
||||
} else
|
||||
throw new Doctrine_Exception("Validator named '$name' not availible.");
|
||||
}
|
||||
return self::$validators[$name];
|
||||
}
|
||||
/**
|
||||
* @param Doctrine_Record $record
|
||||
* @return void
|
||||
*/
|
||||
public function validateRecord(Doctrine_Record $record) {
|
||||
$modified = $record->getModified();
|
||||
$columns = $record->getTable()->getColumns();
|
||||
$name = $record->getTable()->getComponentName();
|
||||
|
||||
$err = array();
|
||||
foreach($modified as $key => $value) {
|
||||
$column = $columns[$key];
|
||||
|
||||
if(strlen($value) > $column[1]) {
|
||||
$err[$key] = Doctrine_Validator::ERR_LENGTH;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(self::gettype($value) !== $column[0]) {
|
||||
$err[$key] = Doctrine_Validator::ERR_TYPE;
|
||||
continue;
|
||||
}
|
||||
|
||||
$e = explode("|",$column[2]);
|
||||
|
||||
foreach($e as $k => $arg) {
|
||||
if(empty($arg) || $arg == "primary")
|
||||
continue;
|
||||
|
||||
$validator = self::getValidator($arg);
|
||||
if( ! $validator->validate($record,$key,$value)) {
|
||||
switch(strtolower($arg)):
|
||||
case "unique":
|
||||
$err[$key] = Doctrine_Validator::ERR_UNIQUE;
|
||||
break;
|
||||
default:
|
||||
$err[$key] = Doctrine_Validator::ERR_VALID;
|
||||
break;
|
||||
endswitch;
|
||||
}
|
||||
if(isset($err[$key]))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( ! empty($err)) {
|
||||
$this->stack[$name][] = $err;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasErrors() {
|
||||
return (count($this->stack) > 0);
|
||||
}
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getErrorStack() {
|
||||
return $this->stack;
|
||||
}
|
||||
/**
|
||||
* @param mixed $var
|
||||
*/
|
||||
public static function gettype($var) {
|
||||
$type = gettype($var);
|
||||
switch($type):
|
||||
case "string":
|
||||
if(preg_match("/^[0-9]*$/",$var)) return "integer";
|
||||
elseif(is_numeric($var)) return "float";
|
||||
else return $type;
|
||||
break;
|
||||
default:
|
||||
return $type;
|
||||
endswitch;
|
||||
}
|
||||
}
|
||||
?>
|
18
classes/Validator/Blank.class.php
Normal file
18
classes/Validator/Blank.class.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
class Doctrine_Validator_Blank {
|
||||
/**
|
||||
* @param Doctrine_Record $record
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return boolean
|
||||
*/
|
||||
public function validate(Doctrine_Record $record, $key, $value) {
|
||||
$string = str_replace("\n","",$value);
|
||||
$string = str_replace("\r","",$string);
|
||||
$string = str_replace("\t","",$string);
|
||||
$string = str_replace("\s","",$string);
|
||||
$string = str_replace(" ","",$string);
|
||||
if($string == "") return true;
|
||||
}
|
||||
}
|
||||
?>
|
264
classes/Validator/Country.class.php
Normal file
264
classes/Validator/Country.class.php
Normal file
@ -0,0 +1,264 @@
|
||||
<?php
|
||||
class Doctrine_Validator_Country {
|
||||
private static $countries = array(
|
||||
"ad" => "Andorra",
|
||||
"ae" => "United Arab Emirates",
|
||||
"af" => "Afghanistan",
|
||||
"ag" => "Antigua and Barbuda",
|
||||
"ai" => "Anguilla",
|
||||
"al" => "Albania",
|
||||
"am" => "Armenia",
|
||||
"an" => "Netherlands Antilles",
|
||||
"ao" => "Angola",
|
||||
"aq" => "Antarctica",
|
||||
"ar" => "Argentina",
|
||||
"as" => "American Samoa",
|
||||
"at" => "Austria",
|
||||
"au" => "Australia",
|
||||
"aw" => "Aruba",
|
||||
"az" => "Azerbaijan",
|
||||
"ba" => "Bosnia Hercegovina",
|
||||
"bb" => "Barbados",
|
||||
"bd" => "Bangladesh",
|
||||
"be" => "Belgium",
|
||||
"bf" => "Burkina Faso",
|
||||
"bg" => "Bulgaria",
|
||||
"bh" => "Bahrain",
|
||||
"bi" => "Burundi",
|
||||
"bj" => "Benin",
|
||||
"bm" => "Bermuda",
|
||||
"bn" => "Brunei Darussalam",
|
||||
"bo" => "Bolivia",
|
||||
"br" => "Brazil",
|
||||
"bs" => "Bahamas",
|
||||
"bt" => "Bhutan",
|
||||
"bv" => "Bouvet Island",
|
||||
"bw" => "Botswana",
|
||||
"by" => "Belarus (Byelorussia)",
|
||||
"bz" => "Belize",
|
||||
"ca" => "Canada",
|
||||
"cc" => "Cocos Islands",
|
||||
"cd" => 'Congo, The Democratic Republic of the',
|
||||
"cf" => "Central African Republic",
|
||||
"cg" => "Congo",
|
||||
"ch" => "Switzerland",
|
||||
"ci" => "Ivory Coast",
|
||||
"ck" => "Cook Islands",
|
||||
"cl" => "Chile",
|
||||
"cm" => "Cameroon",
|
||||
"cn" => "China",
|
||||
"co" => "Colombia",
|
||||
"cr" => "Costa Rica",
|
||||
"cs" => "Czechoslovakia",
|
||||
"cu" => "Cuba",
|
||||
"cv" => "Cape Verde",
|
||||
"cx" => "Christmas Island",
|
||||
"cy" => "Cyprus",
|
||||
"cz" => 'Czech Republic',
|
||||
"de" => "Germany",
|
||||
"dj" => "Djibouti",
|
||||
"dk" => 'Denmark',
|
||||
"dm" => "Dominica",
|
||||
"do" => "Dominican Republic",
|
||||
"dz" => "Algeria",
|
||||
"ec" => "Ecuador",
|
||||
"ee" => "Estonia",
|
||||
"eg" => "Egypt",
|
||||
"eh" => "Western Sahara",
|
||||
"er" => 'Eritrea',
|
||||
"es" => "Spain",
|
||||
"et" => "Ethiopia",
|
||||
"fi" => "Finland",
|
||||
"fj" => "Fiji",
|
||||
"fk" => "Falkland Islands",
|
||||
"fm" => "Micronesia",
|
||||
"fo" => "Faroe Islands",
|
||||
"fr" => "France",
|
||||
"fx" => 'France, Metropolitan FX',
|
||||
"ga" => "Gabon",
|
||||
"gb" => 'United Kingdom (Great Britain)',
|
||||
"gd" => "Grenada",
|
||||
"ge" => "Georgia",
|
||||
"gf" => "French Guiana",
|
||||
"gh" => "Ghana",
|
||||
"gi" => "Gibraltar",
|
||||
"gl" => "Greenland",
|
||||
"gm" => "Gambia",
|
||||
"gn" => "Guinea",
|
||||
"gp" => "Guadeloupe",
|
||||
"gq" => "Equatorial Guinea",
|
||||
"gr" => "Greece",
|
||||
"gs" => 'South Georgia and the South Sandwich Islands',
|
||||
"gt" => "Guatemala",
|
||||
"gu" => "Guam",
|
||||
"gw" => "Guinea-bissau",
|
||||
"gy" => "Guyana",
|
||||
"hk" => "Hong Kong",
|
||||
"hm" => "Heard and McDonald Islands",
|
||||
"hn" => "Honduras",
|
||||
"hr" => "Croatia",
|
||||
"ht" => "Haiti",
|
||||
"hu" => "Hungary",
|
||||
"id" => "Indonesia",
|
||||
"ie" => "Ireland",
|
||||
"il" => "Israel",
|
||||
"in" => "India",
|
||||
"io" => "British Indian Ocean Territory",
|
||||
"iq" => "Iraq",
|
||||
"ir" => "Iran",
|
||||
"is" => "Iceland",
|
||||
"it" => "Italy",
|
||||
"jm" => "Jamaica",
|
||||
"jo" => "Jordan",
|
||||
"jp" => "Japan",
|
||||
"ke" => "Kenya",
|
||||
"kg" => "Kyrgyzstan",
|
||||
"kh" => "Cambodia",
|
||||
"ki" => "Kiribati",
|
||||
"km" => "Comoros",
|
||||
"kn" => "Saint Kitts and Nevis",
|
||||
"kp" => "North Korea",
|
||||
"kr" => "South Korea",
|
||||
"kw" => "Kuwait",
|
||||
"ky" => "Cayman Islands",
|
||||
"kz" => "Kazakhstan",
|
||||
"la" => "Laos",
|
||||
"lb" => "Lebanon",
|
||||
"lc" => "Saint Lucia",
|
||||
"li" => "Lichtenstein",
|
||||
"lk" => "Sri Lanka",
|
||||
"lr" => "Liberia",
|
||||
"ls" => "Lesotho",
|
||||
"lt" => "Lithuania",
|
||||
"lu" => "Luxembourg",
|
||||
"lv" => "Latvia",
|
||||
"ly" => "Libya",
|
||||
"ma" => "Morocco",
|
||||
"mc" => "Monaco",
|
||||
"md" => "Moldova Republic",
|
||||
"mg" => "Madagascar",
|
||||
"mh" => "Marshall Islands",
|
||||
"mk" => 'Macedonia, The Former Yugoslav Republic of',
|
||||
"ml" => "Mali",
|
||||
"mm" => "Myanmar",
|
||||
"mn" => "Mongolia",
|
||||
"mo" => "Macau",
|
||||
"mp" => "Northern Mariana Islands",
|
||||
"mq" => "Martinique",
|
||||
"mr" => "Mauritania",
|
||||
"ms" => "Montserrat",
|
||||
"mt" => "Malta",
|
||||
"mu" => "Mauritius",
|
||||
"mv" => "Maldives",
|
||||
"mw" => "Malawi",
|
||||
"mx" => "Mexico",
|
||||
"my" => "Malaysia",
|
||||
"mz" => "Mozambique",
|
||||
"na" => "Namibia",
|
||||
"nc" => "New Caledonia",
|
||||
"ne" => "Niger",
|
||||
"nf" => "Norfolk Island",
|
||||
"ng" => "Nigeria",
|
||||
"ni" => "Nicaragua",
|
||||
"nl" => "Netherlands",
|
||||
"no" => "Norway",
|
||||
"np" => "Nepal",
|
||||
"nr" => "Nauru",
|
||||
"nt" => "Neutral Zone",
|
||||
"nu" => "Niue",
|
||||
"nz" => "New Zealand",
|
||||
"om" => "Oman",
|
||||
"pa" => "Panama",
|
||||
"pe" => "Peru",
|
||||
"pf" => "French Polynesia",
|
||||
"pg" => "Papua New Guinea",
|
||||
"ph" => "Philippines",
|
||||
"pk" => "Pakistan",
|
||||
"pl" => "Poland",
|
||||
"pm" => "St. Pierre and Miquelon",
|
||||
"pn" => "Pitcairn",
|
||||
"pr" => "Puerto Rico",
|
||||
"pt" => "Portugal",
|
||||
"pw" => "Palau",
|
||||
"py" => "Paraguay",
|
||||
"qa" => 'Qatar',
|
||||
"re" => "Reunion",
|
||||
"ro" => "Romania",
|
||||
"ru" => "Russia",
|
||||
"rw" => "Rwanda",
|
||||
"sa" => "Saudi Arabia",
|
||||
"sb" => "Solomon Islands",
|
||||
"sc" => "Seychelles",
|
||||
"sd" => "Sudan",
|
||||
"se" => "Sweden",
|
||||
"sg" => "Singapore",
|
||||
"sh" => "St. Helena",
|
||||
"si" => "Slovenia",
|
||||
"sj" => "Svalbard and Jan Mayen Islands",
|
||||
"sk" => 'Slovakia (Slovak Republic)',
|
||||
"sl" => "Sierra Leone",
|
||||
"sm" => "San Marino",
|
||||
"sn" => "Senegal",
|
||||
"so" => "Somalia",
|
||||
"sr" => "Suriname",
|
||||
"st" => "Sao Tome and Principe",
|
||||
"sv" => "El Salvador",
|
||||
"sy" => "Syria",
|
||||
"sz" => "Swaziland",
|
||||
"tc" => "Turks and Caicos Islands",
|
||||
"td" => "Chad",
|
||||
"tf" => "French Southern Territories",
|
||||
"tg" => "Togo",
|
||||
"th" => "Thailand",
|
||||
"tj" => "Tajikistan",
|
||||
"tk" => "Tokelau",
|
||||
"tm" => "Turkmenistan",
|
||||
"tn" => "Tunisia",
|
||||
"to" => "Tonga",
|
||||
"tp" => "East Timor",
|
||||
"tr" => "Turkey",
|
||||
"tt" => "Trinidad, Tobago",
|
||||
"tv" => "Tuvalu",
|
||||
"tw" => "Taiwan",
|
||||
"tz" => "Tanzania",
|
||||
"ua" => "Ukraine",
|
||||
"ug" => "Uganda",
|
||||
"uk" => "United Kingdom",
|
||||
"um" => "United States Minor Islands",
|
||||
"us" => "United States of America",
|
||||
"uy" => "Uruguay",
|
||||
"uz" => "Uzbekistan",
|
||||
"va" => "Vatican City",
|
||||
"vc" => "Saint Vincent, Grenadines",
|
||||
"ve" => "Venezuela",
|
||||
"vg" => "Virgin Islands (British)",
|
||||
"vi" => "Virgin Islands (USA)",
|
||||
"vn" => "Viet Nam",
|
||||
"vu" => "Vanuatu",
|
||||
"wf" => 'Wallis and Futuna Islands',
|
||||
"ws" => "Samoa",
|
||||
"ye" => 'Yemen',
|
||||
"yt" => 'Mayotte',
|
||||
"yu" => "Yugoslavia",
|
||||
"za" => "South Africa",
|
||||
"zm" => "Zambia",
|
||||
"zr" => "Zaire",
|
||||
"zw" => "Zimbabwe");
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function getCountries() {
|
||||
return self::$countries;
|
||||
}
|
||||
/**
|
||||
* @param Doctrine_Record $record
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return boolean
|
||||
*/
|
||||
public function validate(Doctrine_Record $record, $key, $value) {
|
||||
return isset(self::$countries[$value]);
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
13
classes/Validator/Date.class.php
Normal file
13
classes/Validator/Date.class.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
class Doctrine_Validator_Date {
|
||||
/**
|
||||
* @param Doctrine_Record $record
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return boolean
|
||||
*/
|
||||
public function validate(Doctrine_Record $record, $key, $value) {
|
||||
return checkdate($value);
|
||||
}
|
||||
}
|
||||
?>
|
46
classes/Validator/Email.class.php
Normal file
46
classes/Validator/Email.class.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
class Doctrine_Validator_Email {
|
||||
/**
|
||||
* @param Doctrine_Record $record
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return boolean
|
||||
*/
|
||||
public function validate(Doctrine_Record $record, $key, $value) {
|
||||
$parts = explode("@", $value);
|
||||
|
||||
if(count($parts) != 2)
|
||||
return false;
|
||||
|
||||
if(strlen($parts[0]) < 1 || strlen($parts[0]) > 64)
|
||||
return false;
|
||||
|
||||
if(strlen($parts[1]) < 1 || strlen($parts[1]) > 255)
|
||||
return false;
|
||||
|
||||
$local_array = explode(".", $parts[0]);
|
||||
for ($i = 0; $i < sizeof($local_array); $i++) {
|
||||
if (!ereg("^(([A-Za-z0-9!#$%&'*+/=?^_`{|}~-][A-Za-z0-9!#$%&'*+/=?^_`{|}~\.-]{0,63})|(\"[^(\\|\")]{0,62}\"))$", $parts[$i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!ereg("^\[?[0-9\.]+\]?$", $parts[1])) { // Check if domain is IP. If not, it should be valid domain name
|
||||
$domain_array = explode(".", $parts[1]);
|
||||
if (count($domain_array) < 2) {
|
||||
return false; // Not enough parts to domain
|
||||
}
|
||||
for ($i = 0; $i < sizeof($domain_array); $i++) {
|
||||
if (!ereg("^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|([A-Za-z0-9]+))$", $domain_array[$i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(function_exists("checkdnsrr")) {
|
||||
if( ! checkdnsrr($parts[1], "MX"))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
?>
|
16
classes/Validator/Htmlcolor.class.php
Normal file
16
classes/Validator/Htmlcolor.class.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
class Doctrine_Validator_HtmlColor {
|
||||
/**
|
||||
* @param Doctrine_Record $record
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return boolean
|
||||
*/
|
||||
public function validate(Doctrine_Record $record, $key, $value) {
|
||||
if( ! preg_match("/^#{0,1}[0-9]{6}$/",$color)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
?>
|
21
classes/Validator/Ip.class.php
Normal file
21
classes/Validator/Ip.class.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
class Doctrine_Validator_IP {
|
||||
/**
|
||||
* @param Doctrine_Record $record
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return boolean
|
||||
*/
|
||||
public function validate(Doctrine_Record $record, $key, $value) {
|
||||
$e = explode(".",$request);
|
||||
if(count($e) != 4) return false;
|
||||
|
||||
foreach($e as $k=>$v):
|
||||
if(! is_numeric($v)) return false;
|
||||
$v = (int) $v;
|
||||
if($v < 0 || $v > 255) return false;
|
||||
endforeach;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
?>
|
16
classes/Validator/Nospace.class.php
Normal file
16
classes/Validator/Nospace.class.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
class Doctrine_Validator_NoSpace {
|
||||
/**
|
||||
* @param Doctrine_Record $record
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return boolean
|
||||
*/
|
||||
public function validate(Doctrine_Record $record, $key, $value) {
|
||||
if(preg_match("/[\s\r\t\n]/", $value))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
?>
|
13
classes/Validator/Notnull.class.php
Normal file
13
classes/Validator/Notnull.class.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
class Doctrine_Validator_Notnull {
|
||||
/**
|
||||
* @param Doctrine_Record $record
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return boolean
|
||||
*/
|
||||
public function validate(Doctrine_Record $record, $key, $value) {
|
||||
return ($value === null);
|
||||
}
|
||||
}
|
||||
?>
|
31
classes/Validator/Range.class.php
Normal file
31
classes/Validator/Range.class.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
class Doctrine_Validator_Range {
|
||||
/**
|
||||
* @param integer $max
|
||||
*/
|
||||
public function setMin($min) {
|
||||
$this->min = $min;
|
||||
}
|
||||
/**
|
||||
* @param integer $max
|
||||
*/
|
||||
public function setMax($max) {
|
||||
$this->max = $max;
|
||||
}
|
||||
/**
|
||||
* @param Doctrine_Record $record
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return boolean
|
||||
*/
|
||||
public function validate(Doctrine_Record $record, $key, $value) {
|
||||
if($var < $this->min)
|
||||
return false;
|
||||
|
||||
if($var > $this->max)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
?>
|
13
classes/Validator/Regexp.class.php
Normal file
13
classes/Validator/Regexp.class.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
class Doctrine_Validator_Regexp {
|
||||
/**
|
||||
* @param Doctrine_Record $record
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return boolean
|
||||
*/
|
||||
public function validate(Doctrine_Record $record, $key, $value) {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
?>
|
13
classes/Validator/Required.class.php
Normal file
13
classes/Validator/Required.class.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
class Doctrine_Validator_Required {
|
||||
/**
|
||||
* @param Doctrine_Record $record
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return boolean
|
||||
*/
|
||||
public function validate(Doctrine_Record $record, $key, $value) {
|
||||
return ($value === null);
|
||||
}
|
||||
}
|
||||
?>
|
17
classes/Validator/Unique.class.php
Normal file
17
classes/Validator/Unique.class.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
class Doctrine_Validator_Unique {
|
||||
/**
|
||||
* @param Doctrine_Record $record
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return boolean
|
||||
*/
|
||||
public function validate(Doctrine_Record $record, $key, $value) {
|
||||
$table = $record->getTable();
|
||||
$sql = "SELECT id FROM ".$table->getTableName()." WHERE ".$key." = ?";
|
||||
$stmt = $table->getSession()->getDBH()->prepare($sql);
|
||||
$stmt->execute(array($value));
|
||||
return ( ! is_array($stmt->fetch()));
|
||||
}
|
||||
}
|
||||
?>
|
71
classes/Validator/Usstate.class.php
Normal file
71
classes/Validator/Usstate.class.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
class ValidatorUSState {
|
||||
private static $states = array (
|
||||
"AK" => true,
|
||||
"AL" => true,
|
||||
"AR" => true,
|
||||
"AZ" => true,
|
||||
"CA" => true,
|
||||
"CO" => true,
|
||||
"CT" => true,
|
||||
"DC" => true,
|
||||
"DE" => true,
|
||||
"FL" => true,
|
||||
"GA" => true,
|
||||
"HI" => true,
|
||||
"IA" => true,
|
||||
"ID" => true,
|
||||
"IL" => true,
|
||||
"IN" => true,
|
||||
"KS" => true,
|
||||
"KY" => true,
|
||||
"LA" => true,
|
||||
"MA" => true,
|
||||
"MD" => true,
|
||||
"ME" => true,
|
||||
"MI" => true,
|
||||
"MN" => true,
|
||||
"MO" => true,
|
||||
"MS" => true,
|
||||
"MT" => true,
|
||||
"NC" => true,
|
||||
"ND" => true,
|
||||
"NE" => true,
|
||||
"NH" => true,
|
||||
"NJ" => true,
|
||||
"NM" => true,
|
||||
"NV" => true,
|
||||
"NY" => true,
|
||||
"OH" => true,
|
||||
"OK" => true,
|
||||
"OR" => true,
|
||||
"PA" => true,
|
||||
"PR" => true,
|
||||
"RI" => true,
|
||||
"SC" => true,
|
||||
"SD" => true,
|
||||
"TN" => true,
|
||||
"TX" => true,
|
||||
"UT" => true,
|
||||
"VA" => true,
|
||||
"VI" => true,
|
||||
"VT" => true,
|
||||
"WA" => true,
|
||||
"WI" => true,
|
||||
"WV" => true,
|
||||
"WY" => true
|
||||
);
|
||||
public function getStates() {
|
||||
return self::$states;
|
||||
}
|
||||
/**
|
||||
* @param Doctrine_Record $record
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return boolean
|
||||
*/
|
||||
public function validate(Doctrine_Record $record, $key, $value) {
|
||||
return isset(self::$states[$value]);
|
||||
}
|
||||
}
|
||||
?>
|
1072
classes/adodb-hack/adodb-datadict.inc.php
Normal file
1072
classes/adodb-hack/adodb-datadict.inc.php
Normal file
File diff suppressed because it is too large
Load Diff
50
classes/adodb-hack/adodb.inc.php
Normal file
50
classes/adodb-hack/adodb.inc.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ADOdb Lite is a PHP class to encapsulate multiple database APIs and is compatible with
|
||||
* a subset of the ADODB Command Syntax.
|
||||
* Currently supports Frontbase, MaxDB, miniSQL, MSSQL, MSSQL Pro, MySQLi, MySQLt, MySQL, PostgresSQL,
|
||||
* PostgresSQL64, PostgresSQL7, PostgresSQL8, SqLite, SqLite Pro, Sybase and Sybase ASE.
|
||||
*
|
||||
*/
|
||||
|
||||
if (!defined('_ADODB_LAYER'))
|
||||
define('_ADODB_LAYER',1);
|
||||
|
||||
if (!defined('ADODB_DIR'))
|
||||
define('ADODB_DIR', dirname(__FILE__));
|
||||
|
||||
$ADODB_vers = 'V1.15 ADOdb Lite 25 March 2006 (c) 2005, 2006 Mark Dickenson. All rights reserved. Released LGPL.';
|
||||
|
||||
define('ADODB_FETCH_DEFAULT',0);
|
||||
define('ADODB_FETCH_NUM',1);
|
||||
define('ADODB_FETCH_ASSOC',2);
|
||||
define('ADODB_FETCH_BOTH',3);
|
||||
|
||||
GLOBAL $ADODB_FETCH_MODE;
|
||||
$ADODB_FETCH_MODE = ADODB_FETCH_DEFAULT; // DEFAULT, NUM, ASSOC or BOTH. Default follows native driver default...
|
||||
|
||||
|
||||
function NewDataDictionary(PDO $conn) {
|
||||
|
||||
$dbtype = $conn->getAttribute(PDO::ATTR_DRIVER_NAME);
|
||||
|
||||
include_once ADODB_DIR . '/adodb-datadict.inc.php';
|
||||
include_once ADODB_DIR . '/drivers/datadict-' . $dbtype . '.inc.php';
|
||||
|
||||
$class = "ADODB2_$dbtype";
|
||||
$dict = new $class();
|
||||
$dict->connection = $conn;
|
||||
$dict->upperName = strtoupper($dbtype);
|
||||
//$dict->quote = $conn->nameQuote;
|
||||
//$dict->debug_echo = $conn->debug_echo;
|
||||
|
||||
return $dict;
|
||||
}
|
||||
class ADOFieldObject {
|
||||
var $name = '';
|
||||
var $max_length=0;
|
||||
var $type="";
|
||||
}
|
||||
|
||||
?>
|
95
classes/adodb-hack/drivers/datadict-access.inc.php
Normal file
95
classes/adodb-hack/drivers/datadict-access.inc.php
Normal file
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
V4.80 8 Mar 2006 (c) 2000-2006 John Lim (jlim@natsoft.com.my). All rights reserved.
|
||||
Released under both BSD license and Lesser GPL library license.
|
||||
Whenever there is any discrepancy between the two licenses,
|
||||
the BSD license will take precedence.
|
||||
|
||||
Set tabs to 4 for best viewing.
|
||||
|
||||
*/
|
||||
|
||||
// security - hide paths
|
||||
if (!defined('ADODB_DIR')) die();
|
||||
|
||||
class ADODB2_access extends ADODB_DataDict {
|
||||
|
||||
var $databaseType = 'access';
|
||||
var $seqField = false;
|
||||
|
||||
|
||||
function ActualType($meta)
|
||||
{
|
||||
switch($meta) {
|
||||
case 'C': return 'TEXT';
|
||||
case 'XL':
|
||||
case 'X': return 'MEMO';
|
||||
|
||||
case 'C2': return 'TEXT'; // up to 32K
|
||||
case 'X2': return 'MEMO';
|
||||
|
||||
case 'B': return 'BINARY';
|
||||
|
||||
case 'D': return 'DATETIME';
|
||||
case 'T': return 'DATETIME';
|
||||
|
||||
case 'L': return 'BYTE';
|
||||
case 'I': return 'INTEGER';
|
||||
case 'I1': return 'BYTE';
|
||||
case 'I2': return 'SMALLINT';
|
||||
case 'I4': return 'INTEGER';
|
||||
case 'I8': return 'INTEGER';
|
||||
|
||||
case 'F': return 'DOUBLE';
|
||||
case 'N': return 'NUMERIC';
|
||||
default:
|
||||
return $meta;
|
||||
}
|
||||
}
|
||||
|
||||
// return string must begin with space
|
||||
function _CreateSuffix($fname, &$ftype, $fnotnull,$fdefault,$fautoinc,$fconstraint)
|
||||
{
|
||||
if ($fautoinc) {
|
||||
$ftype = 'COUNTER';
|
||||
return '';
|
||||
}
|
||||
if (substr($ftype,0,7) == 'DECIMAL') $ftype = 'DECIMAL';
|
||||
$suffix = '';
|
||||
if (strlen($fdefault)) {
|
||||
//$suffix .= " DEFAULT $fdefault";
|
||||
if ($this->debug) ADOConnection::outp("Warning: Access does not supported DEFAULT values (field $fname)");
|
||||
}
|
||||
if ($fnotnull) $suffix .= ' NOT NULL';
|
||||
if ($fconstraint) $suffix .= ' '.$fconstraint;
|
||||
return $suffix;
|
||||
}
|
||||
|
||||
function CreateDatabase($dbname,$options=false)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
function SetSchema($schema)
|
||||
{
|
||||
}
|
||||
|
||||
function AlterColumnSQL($tabname, $flds)
|
||||
{
|
||||
if ($this->debug) ADOConnection::outp("AlterColumnSQL not supported");
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
function DropColumnSQL($tabname, $flds)
|
||||
{
|
||||
if ($this->debug) ADOConnection::outp("DropColumnSQL not supported");
|
||||
return array();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
143
classes/adodb-hack/drivers/datadict-db2.inc.php
Normal file
143
classes/adodb-hack/drivers/datadict-db2.inc.php
Normal file
@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
V4.80 8 Mar 2006 (c) 2000-2006 John Lim (jlim@natsoft.com.my). All rights reserved.
|
||||
Released under both BSD license and Lesser GPL library license.
|
||||
Whenever there is any discrepancy between the two licenses,
|
||||
the BSD license will take precedence.
|
||||
|
||||
Set tabs to 4 for best viewing.
|
||||
|
||||
*/
|
||||
// security - hide paths
|
||||
if (!defined('ADODB_DIR')) die();
|
||||
|
||||
class ADODB2_db2 extends ADODB_DataDict {
|
||||
|
||||
var $databaseType = 'db2';
|
||||
var $seqField = false;
|
||||
|
||||
function ActualType($meta)
|
||||
{
|
||||
switch($meta) {
|
||||
case 'C': return 'VARCHAR';
|
||||
case 'XL': return 'CLOB';
|
||||
case 'X': return 'VARCHAR(3600)';
|
||||
|
||||
case 'C2': return 'VARCHAR'; // up to 32K
|
||||
case 'X2': return 'VARCHAR(3600)'; // up to 32000, but default page size too small
|
||||
|
||||
case 'B': return 'BLOB';
|
||||
|
||||
case 'D': return 'DATE';
|
||||
case 'T': return 'TIMESTAMP';
|
||||
|
||||
case 'L': return 'SMALLINT';
|
||||
case 'I': return 'INTEGER';
|
||||
case 'I1': return 'SMALLINT';
|
||||
case 'I2': return 'SMALLINT';
|
||||
case 'I4': return 'INTEGER';
|
||||
case 'I8': return 'BIGINT';
|
||||
|
||||
case 'F': return 'DOUBLE';
|
||||
case 'N': return 'DECIMAL';
|
||||
default:
|
||||
return $meta;
|
||||
}
|
||||
}
|
||||
|
||||
// return string must begin with space
|
||||
function _CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint)
|
||||
{
|
||||
$suffix = '';
|
||||
if ($fautoinc) return ' GENERATED ALWAYS AS IDENTITY'; # as identity start with
|
||||
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
|
||||
if ($fnotnull) $suffix .= ' NOT NULL';
|
||||
if ($fconstraint) $suffix .= ' '.$fconstraint;
|
||||
return $suffix;
|
||||
}
|
||||
|
||||
function AlterColumnSQL($tabname, $flds)
|
||||
{
|
||||
if ($this->debug) ADOConnection::outp("AlterColumnSQL not supported");
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
function DropColumnSQL($tabname, $flds)
|
||||
{
|
||||
if ($this->debug) ADOConnection::outp("DropColumnSQL not supported");
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
function ChangeTableSQL($tablename, $flds, $tableoptions = false)
|
||||
{
|
||||
|
||||
/**
|
||||
Allow basic table changes to DB2 databases
|
||||
DB2 will fatally reject changes to non character columns
|
||||
|
||||
*/
|
||||
|
||||
$validTypes = array("CHAR","VARC");
|
||||
$invalidTypes = array("BIGI","BLOB","CLOB","DATE", "DECI","DOUB", "INTE", "REAL","SMAL", "TIME");
|
||||
// check table exists
|
||||
$cols = &$this->MetaColumns($tablename);
|
||||
if ( empty($cols)) {
|
||||
return $this->CreateTableSQL($tablename, $flds, $tableoptions);
|
||||
}
|
||||
|
||||
// already exists, alter table instead
|
||||
list($lines,$pkey) = $this->_GenFields($flds);
|
||||
$alter = 'ALTER TABLE ' . $this->TableName($tablename);
|
||||
$sql = array();
|
||||
|
||||
foreach ( $lines as $id => $v ) {
|
||||
if ( isset($cols[$id]) && is_object($cols[$id]) ) {
|
||||
/**
|
||||
If the first field of $v is the fieldname, and
|
||||
the second is the field type/size, we assume its an
|
||||
attempt to modify the column size, so check that it is allowed
|
||||
$v can have an indeterminate number of blanks between the
|
||||
fields, so account for that too
|
||||
*/
|
||||
$vargs = explode(' ' , $v);
|
||||
// assume that $vargs[0] is the field name.
|
||||
$i=0;
|
||||
// Find the next non-blank value;
|
||||
for ($i=1;$i<sizeof($vargs);$i++)
|
||||
if ($vargs[$i] != '')
|
||||
break;
|
||||
|
||||
// if $vargs[$i] is one of the following, we are trying to change the
|
||||
// size of the field, if not allowed, simply ignore the request.
|
||||
if (in_array(substr($vargs[$i],0,4),$invalidTypes))
|
||||
continue;
|
||||
// insert the appropriate DB2 syntax
|
||||
if (in_array(substr($vargs[$i],0,4),$validTypes)) {
|
||||
array_splice($vargs,$i,0,array('SET','DATA','TYPE'));
|
||||
}
|
||||
|
||||
// Now Look for the NOT NULL statement as this is not allowed in
|
||||
// the ALTER table statement. If it is in there, remove it
|
||||
if (in_array('NOT',$vargs) && in_array('NULL',$vargs)) {
|
||||
for ($i=1;$i<sizeof($vargs);$i++)
|
||||
if ($vargs[$i] == 'NOT')
|
||||
break;
|
||||
array_splice($vargs,$i,2,'');
|
||||
}
|
||||
$v = implode(' ',$vargs);
|
||||
$sql[] = $alter . $this->alterCol . ' ' . $v;
|
||||
} else {
|
||||
$sql[] = $alter . $this->addCol . ' ' . $v;
|
||||
}
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
151
classes/adodb-hack/drivers/datadict-firebird.inc.php
Normal file
151
classes/adodb-hack/drivers/datadict-firebird.inc.php
Normal file
@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
V4.80 8 Mar 2006 (c) 2000-2006 John Lim (jlim@natsoft.com.my). All rights reserved.
|
||||
Released under both BSD license and Lesser GPL library license.
|
||||
Whenever there is any discrepancy between the two licenses,
|
||||
the BSD license will take precedence.
|
||||
|
||||
Set tabs to 4 for best viewing.
|
||||
|
||||
*/
|
||||
|
||||
class ADODB2_firebird extends ADODB_DataDict {
|
||||
|
||||
var $databaseType = 'firebird';
|
||||
var $seqField = false;
|
||||
var $seqPrefix = 'gen_';
|
||||
var $blobSize = 40000;
|
||||
|
||||
function ActualType($meta)
|
||||
{
|
||||
switch($meta) {
|
||||
case 'C': return 'VARCHAR';
|
||||
case 'XL': return 'VARCHAR(32000)';
|
||||
case 'X': return 'VARCHAR(4000)';
|
||||
|
||||
case 'C2': return 'VARCHAR'; // up to 32K
|
||||
case 'X2': return 'VARCHAR(4000)';
|
||||
|
||||
case 'B': return 'BLOB';
|
||||
|
||||
case 'D': return 'DATE';
|
||||
case 'T': return 'TIMESTAMP';
|
||||
|
||||
case 'L': return 'SMALLINT';
|
||||
case 'I': return 'INTEGER';
|
||||
case 'I1': return 'SMALLINT';
|
||||
case 'I2': return 'SMALLINT';
|
||||
case 'I4': return 'INTEGER';
|
||||
case 'I8': return 'INTEGER';
|
||||
|
||||
case 'F': return 'DOUBLE PRECISION';
|
||||
case 'N': return 'DECIMAL';
|
||||
default:
|
||||
return $meta;
|
||||
}
|
||||
}
|
||||
|
||||
function NameQuote($name = NULL)
|
||||
{
|
||||
if (!is_string($name)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$name = trim($name);
|
||||
|
||||
if ( !is_object($this->connection) ) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
$quote = $this->connection->nameQuote;
|
||||
|
||||
// if name is of the form `name`, quote it
|
||||
if ( preg_match('/^`(.+)`$/', $name, $matches) ) {
|
||||
return $quote . $matches[1] . $quote;
|
||||
}
|
||||
|
||||
// if name contains special characters, quote it
|
||||
if ( !preg_match('/^[' . $this->nameRegex . ']+$/', $name) ) {
|
||||
return $quote . $name . $quote;
|
||||
}
|
||||
|
||||
return $quote . $name . $quote;
|
||||
}
|
||||
|
||||
function CreateDatabase($dbname, $options=false)
|
||||
{
|
||||
$options = $this->_Options($options);
|
||||
$sql = array();
|
||||
|
||||
$sql[] = "DECLARE EXTERNAL FUNCTION LOWER CSTRING(80) RETURNS CSTRING(80) FREE_IT ENTRY_POINT 'IB_UDF_lower' MODULE_NAME 'ib_udf'";
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
function _DropAutoIncrement($t)
|
||||
{
|
||||
if (strpos($t,'.') !== false) {
|
||||
$tarr = explode('.',$t);
|
||||
return 'DROP GENERATOR '.$tarr[0].'."gen_'.$tarr[1].'"';
|
||||
}
|
||||
return 'DROP GENERATOR "GEN_'.$t;
|
||||
}
|
||||
|
||||
|
||||
function _CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned)
|
||||
{
|
||||
$suffix = '';
|
||||
|
||||
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
|
||||
if ($fnotnull) $suffix .= ' NOT NULL';
|
||||
if ($fautoinc) $this->seqField = $fname;
|
||||
if ($fconstraint) $suffix .= ' '.$fconstraint;
|
||||
|
||||
return $suffix;
|
||||
}
|
||||
|
||||
/*
|
||||
CREATE or replace TRIGGER jaddress_insert
|
||||
before insert on jaddress
|
||||
for each row
|
||||
begin
|
||||
IF ( NEW."seqField" IS NULL OR NEW."seqField" = 0 ) THEN
|
||||
NEW."seqField" = GEN_ID("GEN_tabname", 1);
|
||||
end;
|
||||
*/
|
||||
function _Triggers($tabname,$tableoptions)
|
||||
{
|
||||
if (!$this->seqField) return array();
|
||||
|
||||
$tab1 = preg_replace( '/"/', '', $tabname );
|
||||
if ($this->schema) {
|
||||
$t = strpos($tab1,'.');
|
||||
if ($t !== false) $tab = substr($tab1,$t+1);
|
||||
else $tab = $tab1;
|
||||
$seqField = $this->seqField;
|
||||
$seqname = $this->schema.'.'.$this->seqPrefix.$tab;
|
||||
$trigname = $this->schema.'.trig_'.$this->seqPrefix.$tab;
|
||||
} else {
|
||||
$seqField = $this->seqField;
|
||||
$seqname = $this->seqPrefix.$tab1;
|
||||
$trigname = 'trig_'.$seqname;
|
||||
}
|
||||
if (isset($tableoptions['REPLACE']))
|
||||
{ $sql[] = "DROP GENERATOR \"$seqname\"";
|
||||
$sql[] = "CREATE GENERATOR \"$seqname\"";
|
||||
$sql[] = "ALTER TRIGGER \"$trigname\" BEFORE INSERT OR UPDATE AS BEGIN IF ( NEW.$seqField IS NULL OR NEW.$seqField = 0 ) THEN NEW.$seqField = GEN_ID(\"$seqname\", 1); END";
|
||||
}
|
||||
else
|
||||
{ $sql[] = "CREATE GENERATOR \"$seqname\"";
|
||||
$sql[] = "CREATE TRIGGER \"$trigname\" FOR $tabname BEFORE INSERT OR UPDATE AS BEGIN IF ( NEW.$seqField IS NULL OR NEW.$seqField = 0 ) THEN NEW.$seqField = GEN_ID(\"$seqname\", 1); END";
|
||||
}
|
||||
|
||||
$this->seqField = false;
|
||||
return $sql;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
125
classes/adodb-hack/drivers/datadict-generic.inc.php
Normal file
125
classes/adodb-hack/drivers/datadict-generic.inc.php
Normal file
@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
V4.80 8 Mar 2006 (c) 2000-2006 John Lim (jlim@natsoft.com.my). All rights reserved.
|
||||
Released under both BSD license and Lesser GPL library license.
|
||||
Whenever there is any discrepancy between the two licenses,
|
||||
the BSD license will take precedence.
|
||||
|
||||
Set tabs to 4 for best viewing.
|
||||
|
||||
*/
|
||||
|
||||
// security - hide paths
|
||||
if (!defined('ADODB_DIR')) die();
|
||||
|
||||
class ADODB2_generic extends ADODB_DataDict {
|
||||
|
||||
var $databaseType = 'generic';
|
||||
var $seqField = false;
|
||||
|
||||
|
||||
function ActualType($meta)
|
||||
{
|
||||
switch($meta) {
|
||||
case 'C': return 'VARCHAR';
|
||||
case 'XL':
|
||||
case 'X': return 'VARCHAR(250)';
|
||||
|
||||
case 'C2': return 'VARCHAR';
|
||||
case 'X2': return 'VARCHAR(250)';
|
||||
|
||||
case 'B': return 'VARCHAR';
|
||||
|
||||
case 'D': return 'DATE';
|
||||
case 'T': return 'DATE';
|
||||
|
||||
case 'L': return 'DECIMAL(1)';
|
||||
case 'I': return 'DECIMAL(10)';
|
||||
case 'I1': return 'DECIMAL(3)';
|
||||
case 'I2': return 'DECIMAL(5)';
|
||||
case 'I4': return 'DECIMAL(10)';
|
||||
case 'I8': return 'DECIMAL(20)';
|
||||
|
||||
case 'F': return 'DECIMAL(32,8)';
|
||||
case 'N': return 'DECIMAL';
|
||||
default:
|
||||
return $meta;
|
||||
}
|
||||
}
|
||||
|
||||
function AlterColumnSQL($tabname, $flds)
|
||||
{
|
||||
if ($this->debug) ADOConnection::outp("AlterColumnSQL not supported");
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
function DropColumnSQL($tabname, $flds)
|
||||
{
|
||||
if ($this->debug) ADOConnection::outp("DropColumnSQL not supported");
|
||||
return array();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
//db2
|
||||
function ActualType($meta)
|
||||
{
|
||||
switch($meta) {
|
||||
case 'C': return 'VARCHAR';
|
||||
case 'X': return 'VARCHAR';
|
||||
|
||||
case 'C2': return 'VARCHAR'; // up to 32K
|
||||
case 'X2': return 'VARCHAR';
|
||||
|
||||
case 'B': return 'BLOB';
|
||||
|
||||
case 'D': return 'DATE';
|
||||
case 'T': return 'TIMESTAMP';
|
||||
|
||||
case 'L': return 'SMALLINT';
|
||||
case 'I': return 'INTEGER';
|
||||
case 'I1': return 'SMALLINT';
|
||||
case 'I2': return 'SMALLINT';
|
||||
case 'I4': return 'INTEGER';
|
||||
case 'I8': return 'BIGINT';
|
||||
|
||||
case 'F': return 'DOUBLE';
|
||||
case 'N': return 'DECIMAL';
|
||||
default:
|
||||
return $meta;
|
||||
}
|
||||
}
|
||||
|
||||
// ifx
|
||||
function ActualType($meta)
|
||||
{
|
||||
switch($meta) {
|
||||
case 'C': return 'VARCHAR';// 255
|
||||
case 'X': return 'TEXT';
|
||||
|
||||
case 'C2': return 'NVARCHAR';
|
||||
case 'X2': return 'TEXT';
|
||||
|
||||
case 'B': return 'BLOB';
|
||||
|
||||
case 'D': return 'DATE';
|
||||
case 'T': return 'DATETIME';
|
||||
|
||||
case 'L': return 'SMALLINT';
|
||||
case 'I': return 'INTEGER';
|
||||
case 'I1': return 'SMALLINT';
|
||||
case 'I2': return 'SMALLINT';
|
||||
case 'I4': return 'INTEGER';
|
||||
case 'I8': return 'DECIMAL(20)';
|
||||
|
||||
case 'F': return 'FLOAT';
|
||||
case 'N': return 'DECIMAL';
|
||||
default:
|
||||
return $meta;
|
||||
}
|
||||
}
|
||||
*/
|
||||
?>
|
67
classes/adodb-hack/drivers/datadict-ibase.inc.php
Normal file
67
classes/adodb-hack/drivers/datadict-ibase.inc.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
V4.80 8 Mar 2006 (c) 2000-2006 John Lim (jlim@natsoft.com.my). All rights reserved.
|
||||
Released under both BSD license and Lesser GPL library license.
|
||||
Whenever there is any discrepancy between the two licenses,
|
||||
the BSD license will take precedence.
|
||||
|
||||
Set tabs to 4 for best viewing.
|
||||
|
||||
*/
|
||||
|
||||
// security - hide paths
|
||||
if (!defined('ADODB_DIR')) die();
|
||||
|
||||
class ADODB2_ibase extends ADODB_DataDict {
|
||||
|
||||
var $databaseType = 'ibase';
|
||||
var $seqField = false;
|
||||
|
||||
|
||||
function ActualType($meta)
|
||||
{
|
||||
switch($meta) {
|
||||
case 'C': return 'VARCHAR';
|
||||
case 'XL':
|
||||
case 'X': return 'VARCHAR(4000)';
|
||||
|
||||
case 'C2': return 'VARCHAR'; // up to 32K
|
||||
case 'X2': return 'VARCHAR(4000)';
|
||||
|
||||
case 'B': return 'BLOB';
|
||||
|
||||
case 'D': return 'DATE';
|
||||
case 'T': return 'TIMESTAMP';
|
||||
|
||||
case 'L': return 'SMALLINT';
|
||||
case 'I': return 'INTEGER';
|
||||
case 'I1': return 'SMALLINT';
|
||||
case 'I2': return 'SMALLINT';
|
||||
case 'I4': return 'INTEGER';
|
||||
case 'I8': return 'INTEGER';
|
||||
|
||||
case 'F': return 'DOUBLE PRECISION';
|
||||
case 'N': return 'DECIMAL';
|
||||
default:
|
||||
return $meta;
|
||||
}
|
||||
}
|
||||
|
||||
function AlterColumnSQL($tabname, $flds)
|
||||
{
|
||||
if ($this->debug) ADOConnection::outp("AlterColumnSQL not supported");
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
function DropColumnSQL($tabname, $flds)
|
||||
{
|
||||
if ($this->debug) ADOConnection::outp("DropColumnSQL not supported");
|
||||
return array();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
80
classes/adodb-hack/drivers/datadict-informix.inc.php
Normal file
80
classes/adodb-hack/drivers/datadict-informix.inc.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
V4.80 8 Mar 2006 (c) 2000-2006 John Lim (jlim@natsoft.com.my). All rights reserved.
|
||||
Released under both BSD license and Lesser GPL library license.
|
||||
Whenever there is any discrepancy between the two licenses,
|
||||
the BSD license will take precedence.
|
||||
|
||||
Set tabs to 4 for best viewing.
|
||||
|
||||
*/
|
||||
|
||||
// security - hide paths
|
||||
if (!defined('ADODB_DIR')) die();
|
||||
|
||||
class ADODB2_informix extends ADODB_DataDict {
|
||||
|
||||
var $databaseType = 'informix';
|
||||
var $seqField = false;
|
||||
|
||||
|
||||
function ActualType($meta)
|
||||
{
|
||||
switch($meta) {
|
||||
case 'C': return 'VARCHAR';// 255
|
||||
case 'XL':
|
||||
case 'X': return 'TEXT';
|
||||
|
||||
case 'C2': return 'NVARCHAR';
|
||||
case 'X2': return 'TEXT';
|
||||
|
||||
case 'B': return 'BLOB';
|
||||
|
||||
case 'D': return 'DATE';
|
||||
case 'T': return 'DATETIME';
|
||||
|
||||
case 'L': return 'SMALLINT';
|
||||
case 'I': return 'INTEGER';
|
||||
case 'I1': return 'SMALLINT';
|
||||
case 'I2': return 'SMALLINT';
|
||||
case 'I4': return 'INTEGER';
|
||||
case 'I8': return 'DECIMAL(20)';
|
||||
|
||||
case 'F': return 'FLOAT';
|
||||
case 'N': return 'DECIMAL';
|
||||
default:
|
||||
return $meta;
|
||||
}
|
||||
}
|
||||
|
||||
function AlterColumnSQL($tabname, $flds)
|
||||
{
|
||||
if ($this->debug) ADOConnection::outp("AlterColumnSQL not supported");
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
function DropColumnSQL($tabname, $flds)
|
||||
{
|
||||
if ($this->debug) ADOConnection::outp("DropColumnSQL not supported");
|
||||
return array();
|
||||
}
|
||||
|
||||
// return string must begin with space
|
||||
function _CreateSuffix($fname, &$ftype, $fnotnull,$fdefault,$fautoinc,$fconstraint)
|
||||
{
|
||||
if ($fautoinc) {
|
||||
$ftype = 'SERIAL';
|
||||
return '';
|
||||
}
|
||||
$suffix = '';
|
||||
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
|
||||
if ($fnotnull) $suffix .= ' NOT NULL';
|
||||
if ($fconstraint) $suffix .= ' '.$fconstraint;
|
||||
return $suffix;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
282
classes/adodb-hack/drivers/datadict-mssql.inc.php
Normal file
282
classes/adodb-hack/drivers/datadict-mssql.inc.php
Normal file
@ -0,0 +1,282 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
V4.80 8 Mar 2006 (c) 2000-2006 John Lim (jlim@natsoft.com.my). All rights reserved.
|
||||
Released under both BSD license and Lesser GPL library license.
|
||||
Whenever there is any discrepancy between the two licenses,
|
||||
the BSD license will take precedence.
|
||||
|
||||
Set tabs to 4 for best viewing.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
In ADOdb, named quotes for MS SQL Server use ". From the MSSQL Docs:
|
||||
|
||||
Note Delimiters are for identifiers only. Delimiters cannot be used for keywords,
|
||||
whether or not they are marked as reserved in SQL Server.
|
||||
|
||||
Quoted identifiers are delimited by double quotation marks ("):
|
||||
SELECT * FROM "Blanks in Table Name"
|
||||
|
||||
Bracketed identifiers are delimited by brackets ([ ]):
|
||||
SELECT * FROM [Blanks In Table Name]
|
||||
|
||||
Quoted identifiers are valid only when the QUOTED_IDENTIFIER option is set to ON. By default,
|
||||
the Microsoft OLE DB Provider for SQL Server and SQL Server ODBC driver set QUOTED_IDENTIFIER ON
|
||||
when they connect.
|
||||
|
||||
In Transact-SQL, the option can be set at various levels using SET QUOTED_IDENTIFIER,
|
||||
the quoted identifier option of sp_dboption, or the user options option of sp_configure.
|
||||
|
||||
When SET ANSI_DEFAULTS is ON, SET QUOTED_IDENTIFIER is enabled.
|
||||
|
||||
Syntax
|
||||
|
||||
SET QUOTED_IDENTIFIER { ON | OFF }
|
||||
|
||||
|
||||
*/
|
||||
|
||||
// security - hide paths
|
||||
if (!defined('ADODB_DIR')) die();
|
||||
|
||||
class ADODB2_mssql extends ADODB_DataDict {
|
||||
var $databaseType = 'mssql';
|
||||
var $dropIndex = 'DROP INDEX %2$s.%1$s';
|
||||
var $renameTable = "EXEC sp_rename '%s','%s'";
|
||||
var $renameColumn = "EXEC sp_rename '%s.%s','%s'";
|
||||
|
||||
var $typeX = 'TEXT'; ## Alternatively, set it to VARCHAR(4000)
|
||||
var $typeXL = 'TEXT';
|
||||
|
||||
//var $alterCol = ' ALTER COLUMN ';
|
||||
|
||||
function MetaType($t,$len=-1,$fieldobj=false)
|
||||
{
|
||||
if (is_object($t)) {
|
||||
$fieldobj = $t;
|
||||
$t = $fieldobj->type;
|
||||
$len = $fieldobj->max_length;
|
||||
}
|
||||
|
||||
$len = -1; // mysql max_length is not accurate
|
||||
switch (strtoupper($t)) {
|
||||
case 'R':
|
||||
case 'INT':
|
||||
case 'INTEGER': return 'I';
|
||||
case 'BIT':
|
||||
case 'TINYINT': return 'I1';
|
||||
case 'SMALLINT': return 'I2';
|
||||
case 'BIGINT': return 'I8';
|
||||
|
||||
case 'REAL':
|
||||
case 'FLOAT': return 'F';
|
||||
default: return parent::MetaType($t,$len,$fieldobj);
|
||||
}
|
||||
}
|
||||
|
||||
function ActualType($meta)
|
||||
{
|
||||
switch(strtoupper($meta)) {
|
||||
|
||||
case 'C': return 'VARCHAR';
|
||||
case 'XL': return (isset($this)) ? $this->typeXL : 'TEXT';
|
||||
case 'X': return (isset($this)) ? $this->typeX : 'TEXT'; ## could be varchar(8000), but we want compat with oracle
|
||||
case 'C2': return 'NVARCHAR';
|
||||
case 'X2': return 'NTEXT';
|
||||
|
||||
case 'B': return 'IMAGE';
|
||||
|
||||
case 'D': return 'DATETIME';
|
||||
case 'T': return 'DATETIME';
|
||||
case 'L': return 'BIT';
|
||||
|
||||
case 'R':
|
||||
case 'I': return 'INT';
|
||||
case 'I1': return 'TINYINT';
|
||||
case 'I2': return 'SMALLINT';
|
||||
case 'I4': return 'INT';
|
||||
case 'I8': return 'BIGINT';
|
||||
|
||||
case 'F': return 'REAL';
|
||||
case 'N': return 'NUMERIC';
|
||||
default:
|
||||
return $meta;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function AddColumnSQL($tabname, $flds)
|
||||
{
|
||||
$tabname = $this->TableName ($tabname);
|
||||
$f = array();
|
||||
list($lines,$pkey) = $this->_GenFields($flds);
|
||||
$s = "ALTER TABLE $tabname $this->addCol";
|
||||
foreach($lines as $v) {
|
||||
$f[] = "\n $v";
|
||||
}
|
||||
$s .= implode(', ',$f);
|
||||
$sql[] = $s;
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/*
|
||||
function AlterColumnSQL($tabname, $flds)
|
||||
{
|
||||
$tabname = $this->TableName ($tabname);
|
||||
$sql = array();
|
||||
list($lines,$pkey) = $this->_GenFields($flds);
|
||||
foreach($lines as $v) {
|
||||
$sql[] = "ALTER TABLE $tabname $this->alterCol $v";
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
*/
|
||||
|
||||
function DropColumnSQL($tabname, $flds)
|
||||
{
|
||||
$tabname = $this->TableName ($tabname);
|
||||
if (!is_array($flds))
|
||||
$flds = explode(',',$flds);
|
||||
$f = array();
|
||||
$s = 'ALTER TABLE ' . $tabname;
|
||||
foreach($flds as $v) {
|
||||
$f[] = "\n$this->dropCol ".$this->NameQuote($v);
|
||||
}
|
||||
$s .= implode(', ',$f);
|
||||
$sql[] = $s;
|
||||
return $sql;
|
||||
}
|
||||
|
||||
// return string must begin with space
|
||||
function _CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint)
|
||||
{
|
||||
$suffix = '';
|
||||
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
|
||||
if ($fautoinc) $suffix .= ' IDENTITY(1,1)';
|
||||
if ($fnotnull) $suffix .= ' NOT NULL';
|
||||
else if ($suffix == '') $suffix .= ' NULL';
|
||||
if ($fconstraint) $suffix .= ' '.$fconstraint;
|
||||
return $suffix;
|
||||
}
|
||||
|
||||
/*
|
||||
CREATE TABLE
|
||||
[ database_name.[ owner ] . | owner. ] table_name
|
||||
( { < column_definition >
|
||||
| column_name AS computed_column_expression
|
||||
| < table_constraint > ::= [ CONSTRAINT constraint_name ] }
|
||||
|
||||
| [ { PRIMARY KEY | UNIQUE } [ ,...n ]
|
||||
)
|
||||
|
||||
[ ON { filegroup | DEFAULT } ]
|
||||
[ TEXTIMAGE_ON { filegroup | DEFAULT } ]
|
||||
|
||||
< column_definition > ::= { column_name data_type }
|
||||
[ COLLATE < collation_name > ]
|
||||
[ [ DEFAULT constant_expression ]
|
||||
| [ IDENTITY [ ( seed , increment ) [ NOT FOR REPLICATION ] ] ]
|
||||
]
|
||||
[ ROWGUIDCOL]
|
||||
[ < column_constraint > ] [ ...n ]
|
||||
|
||||
< column_constraint > ::= [ CONSTRAINT constraint_name ]
|
||||
{ [ NULL | NOT NULL ]
|
||||
| [ { PRIMARY KEY | UNIQUE }
|
||||
[ CLUSTERED | NONCLUSTERED ]
|
||||
[ WITH FILLFACTOR = fillfactor ]
|
||||
[ON {filegroup | DEFAULT} ] ]
|
||||
]
|
||||
| [ [ FOREIGN KEY ]
|
||||
REFERENCES ref_table [ ( ref_column ) ]
|
||||
[ ON DELETE { CASCADE | NO ACTION } ]
|
||||
[ ON UPDATE { CASCADE | NO ACTION } ]
|
||||
[ NOT FOR REPLICATION ]
|
||||
]
|
||||
| CHECK [ NOT FOR REPLICATION ]
|
||||
( logical_expression )
|
||||
}
|
||||
|
||||
< table_constraint > ::= [ CONSTRAINT constraint_name ]
|
||||
{ [ { PRIMARY KEY | UNIQUE }
|
||||
[ CLUSTERED | NONCLUSTERED ]
|
||||
{ ( column [ ASC | DESC ] [ ,...n ] ) }
|
||||
[ WITH FILLFACTOR = fillfactor ]
|
||||
[ ON { filegroup | DEFAULT } ]
|
||||
]
|
||||
| FOREIGN KEY
|
||||
[ ( column [ ,...n ] ) ]
|
||||
REFERENCES ref_table [ ( ref_column [ ,...n ] ) ]
|
||||
[ ON DELETE { CASCADE | NO ACTION } ]
|
||||
[ ON UPDATE { CASCADE | NO ACTION } ]
|
||||
[ NOT FOR REPLICATION ]
|
||||
| CHECK [ NOT FOR REPLICATION ]
|
||||
( search_conditions )
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
CREATE [ UNIQUE ] [ CLUSTERED | NONCLUSTERED ] INDEX index_name
|
||||
ON { table | view } ( column [ ASC | DESC ] [ ,...n ] )
|
||||
[ WITH < index_option > [ ,...n] ]
|
||||
[ ON filegroup ]
|
||||
< index_option > :: =
|
||||
{ PAD_INDEX |
|
||||
FILLFACTOR = fillfactor |
|
||||
IGNORE_DUP_KEY |
|
||||
DROP_EXISTING |
|
||||
STATISTICS_NORECOMPUTE |
|
||||
SORT_IN_TEMPDB
|
||||
}
|
||||
*/
|
||||
function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
|
||||
{
|
||||
$sql = array();
|
||||
|
||||
if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {
|
||||
$sql[] = sprintf ($this->dropIndex, $idxname, $tabname);
|
||||
if ( isset($idxoptions['DROP']) )
|
||||
return $sql;
|
||||
}
|
||||
|
||||
if ( empty ($flds) ) {
|
||||
return $sql;
|
||||
}
|
||||
|
||||
$unique = isset($idxoptions['UNIQUE']) ? ' UNIQUE' : '';
|
||||
$clustered = isset($idxoptions['CLUSTERED']) ? ' CLUSTERED' : '';
|
||||
|
||||
if ( is_array($flds) )
|
||||
$flds = implode(', ',$flds);
|
||||
$s = 'CREATE' . $unique . $clustered . ' INDEX ' . $idxname . ' ON ' . $tabname . ' (' . $flds . ')';
|
||||
|
||||
if ( isset($idxoptions[$this->upperName]) )
|
||||
$s .= $idxoptions[$this->upperName];
|
||||
|
||||
|
||||
$sql[] = $s;
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
|
||||
function _GetSize($ftype, $ty, $fsize, $fprec)
|
||||
{
|
||||
switch ($ftype) {
|
||||
case 'INT':
|
||||
case 'SMALLINT':
|
||||
case 'TINYINT':
|
||||
case 'BIGINT':
|
||||
return $ftype;
|
||||
}
|
||||
if ($ty == 'T') return $ftype;
|
||||
return parent::_GetSize($ftype, $ty, $fsize, $fprec);
|
||||
|
||||
}
|
||||
}
|
||||
?>
|
182
classes/adodb-hack/drivers/datadict-mysql.inc.php
Normal file
182
classes/adodb-hack/drivers/datadict-mysql.inc.php
Normal file
@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
V4.80 8 Mar 2006 (c) 2000-2006 John Lim (jlim@natsoft.com.my). All rights reserved.
|
||||
Released under both BSD license and Lesser GPL library license.
|
||||
Whenever there is any discrepancy between the two licenses,
|
||||
the BSD license will take precedence.
|
||||
|
||||
Set tabs to 4 for best viewing.
|
||||
|
||||
*/
|
||||
|
||||
// security - hide paths
|
||||
if (!defined('ADODB_DIR')) die();
|
||||
|
||||
class ADODB2_mysql extends ADODB_DataDict {
|
||||
var $databaseType = 'mysql';
|
||||
var $alterCol = ' MODIFY COLUMN';
|
||||
var $alterTableAddIndex = true;
|
||||
var $dropTable = 'DROP TABLE IF EXISTS %s'; // requires mysql 3.22 or later
|
||||
|
||||
var $dropIndex = 'DROP INDEX %s ON %s';
|
||||
var $renameColumn = 'ALTER TABLE %s CHANGE COLUMN %s %s %s'; // needs column-definition!
|
||||
var $metaColumnsSQL = "SHOW COLUMNS FROM %s";
|
||||
|
||||
function MetaType($t,$len=-1,$fieldobj=false)
|
||||
{
|
||||
if (is_object($t)) {
|
||||
$fieldobj = $t;
|
||||
$t = $fieldobj->type;
|
||||
$len = $fieldobj->max_length;
|
||||
}
|
||||
$is_serial = is_object($fieldobj) && $fieldobj->primary_key && $fieldobj->auto_increment;
|
||||
|
||||
$len = -1; // mysql max_length is not accurate
|
||||
switch (strtoupper($t)) {
|
||||
case 'STRING':
|
||||
case 'CHAR':
|
||||
case 'VARCHAR':
|
||||
case 'TINYBLOB':
|
||||
case 'TINYTEXT':
|
||||
case 'ENUM':
|
||||
case 'SET':
|
||||
if ($len <= $this->blobSize) return 'C';
|
||||
|
||||
case 'TEXT':
|
||||
case 'LONGTEXT':
|
||||
case 'MEDIUMTEXT':
|
||||
return 'X';
|
||||
|
||||
// php_mysql extension always returns 'blob' even if 'text'
|
||||
// so we have to check whether binary...
|
||||
case 'IMAGE':
|
||||
case 'LONGBLOB':
|
||||
case 'BLOB':
|
||||
case 'MEDIUMBLOB':
|
||||
return !empty($fieldobj->binary) ? 'B' : 'X';
|
||||
|
||||
case 'YEAR':
|
||||
case 'DATE': return 'D';
|
||||
|
||||
case 'TIME':
|
||||
case 'DATETIME':
|
||||
case 'TIMESTAMP': return 'T';
|
||||
|
||||
case 'FLOAT':
|
||||
case 'DOUBLE':
|
||||
return 'F';
|
||||
|
||||
case 'INT':
|
||||
case 'INTEGER': return $is_serial ? 'R' : 'I';
|
||||
case 'TINYINT': return $is_serial ? 'R' : 'I1';
|
||||
case 'SMALLINT': return $is_serial ? 'R' : 'I2';
|
||||
case 'MEDIUMINT': return $is_serial ? 'R' : 'I4';
|
||||
case 'BIGINT': return $is_serial ? 'R' : 'I8';
|
||||
default: return 'N';
|
||||
}
|
||||
}
|
||||
|
||||
function ActualType($meta)
|
||||
{
|
||||
switch(strtoupper($meta)) {
|
||||
case 'C': return 'VARCHAR';
|
||||
case 'XL':return 'LONGTEXT';
|
||||
case 'X': return 'TEXT';
|
||||
|
||||
case 'C2': return 'VARCHAR';
|
||||
case 'X2': return 'LONGTEXT';
|
||||
|
||||
case 'B': return 'LONGBLOB';
|
||||
|
||||
case 'D': return 'DATE';
|
||||
case 'T': return 'DATETIME';
|
||||
case 'L': return 'TINYINT';
|
||||
|
||||
case 'R':
|
||||
case 'I4':
|
||||
case 'I': return 'INTEGER';
|
||||
case 'I1': return 'TINYINT';
|
||||
case 'I2': return 'SMALLINT';
|
||||
case 'I8': return 'BIGINT';
|
||||
|
||||
case 'F': return 'DOUBLE';
|
||||
case 'N': return 'NUMERIC';
|
||||
default:
|
||||
return $meta;
|
||||
}
|
||||
}
|
||||
|
||||
// return string must begin with space
|
||||
function _CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned)
|
||||
{
|
||||
$suffix = '';
|
||||
if ($funsigned) $suffix .= ' UNSIGNED';
|
||||
if ($fnotnull) $suffix .= ' NOT NULL';
|
||||
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
|
||||
if ($fautoinc) $suffix .= ' AUTO_INCREMENT';
|
||||
if ($fconstraint) $suffix .= ' '.$fconstraint;
|
||||
return $suffix;
|
||||
}
|
||||
|
||||
/*
|
||||
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)]
|
||||
[table_options] [select_statement]
|
||||
create_definition:
|
||||
col_name type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT]
|
||||
[PRIMARY KEY] [reference_definition]
|
||||
or PRIMARY KEY (index_col_name,...)
|
||||
or KEY [index_name] (index_col_name,...)
|
||||
or INDEX [index_name] (index_col_name,...)
|
||||
or UNIQUE [INDEX] [index_name] (index_col_name,...)
|
||||
or FULLTEXT [INDEX] [index_name] (index_col_name,...)
|
||||
or [CONSTRAINT symbol] FOREIGN KEY [index_name] (index_col_name,...)
|
||||
[reference_definition]
|
||||
or CHECK (expr)
|
||||
*/
|
||||
|
||||
/*
|
||||
CREATE [UNIQUE|FULLTEXT] INDEX index_name
|
||||
ON tbl_name (col_name[(length)],... )
|
||||
*/
|
||||
|
||||
function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
|
||||
{
|
||||
$sql = array();
|
||||
|
||||
if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {
|
||||
if ($this->alterTableAddIndex) $sql[] = "ALTER TABLE $tabname DROP INDEX $idxname";
|
||||
else $sql[] = sprintf($this->dropIndex, $idxname, $tabname);
|
||||
|
||||
if ( isset($idxoptions['DROP']) )
|
||||
return $sql;
|
||||
}
|
||||
|
||||
if ( empty ($flds) ) {
|
||||
return $sql;
|
||||
}
|
||||
|
||||
if (isset($idxoptions['FULLTEXT'])) {
|
||||
$unique = ' FULLTEXT';
|
||||
} elseif (isset($idxoptions['UNIQUE'])) {
|
||||
$unique = ' UNIQUE';
|
||||
} else {
|
||||
$unique = '';
|
||||
}
|
||||
|
||||
if ( is_array($flds) ) $flds = implode(', ',$flds);
|
||||
|
||||
if ($this->alterTableAddIndex) $s = "ALTER TABLE $tabname ADD $unique INDEX $idxname ";
|
||||
else $s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname;
|
||||
|
||||
$s .= ' (' . $flds . ')';
|
||||
|
||||
if ( isset($idxoptions[$this->upperName]) )
|
||||
$s .= $idxoptions[$this->upperName];
|
||||
|
||||
$sql[] = $s;
|
||||
|
||||
return $sql;
|
||||
}
|
||||
}
|
||||
?>
|
282
classes/adodb-hack/drivers/datadict-oci8.inc.php
Normal file
282
classes/adodb-hack/drivers/datadict-oci8.inc.php
Normal file
@ -0,0 +1,282 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
V4.80 8 Mar 2006 (c) 2000-2006 John Lim (jlim@natsoft.com.my). All rights reserved.
|
||||
Released under both BSD license and Lesser GPL library license.
|
||||
Whenever there is any discrepancy between the two licenses,
|
||||
the BSD license will take precedence.
|
||||
|
||||
Set tabs to 4 for best viewing.
|
||||
|
||||
*/
|
||||
|
||||
// security - hide paths
|
||||
if (!defined('ADODB_DIR')) die();
|
||||
|
||||
class ADODB2_oci8 extends ADODB_DataDict {
|
||||
|
||||
var $databaseType = 'oci8';
|
||||
var $seqField = false;
|
||||
var $seqPrefix = 'SEQ_';
|
||||
var $dropTable = "DROP TABLE %s CASCADE CONSTRAINTS";
|
||||
var $trigPrefix = 'TRIG_';
|
||||
var $alterCol = ' MODIFY ';
|
||||
var $typeX = 'VARCHAR(4000)';
|
||||
var $typeXL = 'CLOB';
|
||||
|
||||
function MetaType($t,$len=-1)
|
||||
{
|
||||
if (is_object($t)) {
|
||||
$fieldobj = $t;
|
||||
$t = $fieldobj->type;
|
||||
$len = $fieldobj->max_length;
|
||||
}
|
||||
switch (strtoupper($t)) {
|
||||
case 'VARCHAR':
|
||||
case 'VARCHAR2':
|
||||
case 'CHAR':
|
||||
case 'VARBINARY':
|
||||
case 'BINARY':
|
||||
if (isset($this) && $len <= $this->blobSize) return 'C';
|
||||
return 'X';
|
||||
|
||||
case 'NCHAR':
|
||||
case 'NVARCHAR2':
|
||||
case 'NVARCHAR':
|
||||
if (isset($this) && $len <= $this->blobSize) return 'C2';
|
||||
return 'X2';
|
||||
|
||||
case 'NCLOB':
|
||||
case 'CLOB':
|
||||
return 'XL';
|
||||
|
||||
case 'LONG RAW':
|
||||
case 'LONG VARBINARY':
|
||||
case 'BLOB':
|
||||
return 'B';
|
||||
|
||||
case 'DATE':
|
||||
return 'T';
|
||||
|
||||
case 'INT':
|
||||
case 'SMALLINT':
|
||||
case 'INTEGER':
|
||||
return 'I';
|
||||
|
||||
default:
|
||||
return 'N';
|
||||
}
|
||||
}
|
||||
|
||||
function ActualType($meta)
|
||||
{
|
||||
switch($meta) {
|
||||
case 'C': return 'VARCHAR';
|
||||
case 'X': return $this->typeX;
|
||||
case 'XL': return $this->typeXL;
|
||||
|
||||
case 'C2': return 'NVARCHAR';
|
||||
case 'X2': return 'NVARCHAR(2000)';
|
||||
|
||||
case 'B': return 'BLOB';
|
||||
|
||||
case 'D':
|
||||
case 'T': return 'DATE';
|
||||
case 'L': return 'DECIMAL(1)';
|
||||
case 'I1': return 'DECIMAL(3)';
|
||||
case 'I2': return 'DECIMAL(5)';
|
||||
case 'I':
|
||||
case 'I4': return 'DECIMAL(10)';
|
||||
|
||||
case 'I8': return 'DECIMAL(20)';
|
||||
case 'F': return 'DECIMAL';
|
||||
case 'N': return 'DECIMAL';
|
||||
default:
|
||||
return $meta;
|
||||
}
|
||||
}
|
||||
|
||||
function CreateDatabase($dbname, $options=false)
|
||||
{
|
||||
$options = $this->_Options($options);
|
||||
$password = isset($options['PASSWORD']) ? $options['PASSWORD'] : 'tiger';
|
||||
$tablespace = isset($options["TABLESPACE"]) ? " DEFAULT TABLESPACE ".$options["TABLESPACE"] : '';
|
||||
$sql[] = "CREATE USER ".$dbname." IDENTIFIED BY ".$password.$tablespace;
|
||||
$sql[] = "GRANT CREATE SESSION, CREATE TABLE,UNLIMITED TABLESPACE,CREATE SEQUENCE TO $dbname";
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
function AddColumnSQL($tabname, $flds)
|
||||
{
|
||||
$f = array();
|
||||
list($lines,$pkey) = $this->_GenFields($flds);
|
||||
$s = "ALTER TABLE $tabname ADD (";
|
||||
foreach($lines as $v) {
|
||||
$f[] = "\n $v";
|
||||
}
|
||||
|
||||
$s .= implode(', ',$f).')';
|
||||
$sql[] = $s;
|
||||
return $sql;
|
||||
}
|
||||
|
||||
function AlterColumnSQL($tabname, $flds)
|
||||
{
|
||||
$f = array();
|
||||
list($lines,$pkey) = $this->_GenFields($flds);
|
||||
$s = "ALTER TABLE $tabname MODIFY(";
|
||||
foreach($lines as $v) {
|
||||
$f[] = "\n $v";
|
||||
}
|
||||
$s .= implode(', ',$f).')';
|
||||
$sql[] = $s;
|
||||
return $sql;
|
||||
}
|
||||
|
||||
function DropColumnSQL($tabname, $flds)
|
||||
{
|
||||
if (!is_array($flds)) $flds = explode(',',$flds);
|
||||
foreach ($flds as $k => $v) $flds[$k] = $this->NameQuote($v);
|
||||
|
||||
$sql = array();
|
||||
$s = "ALTER TABLE $tabname DROP(";
|
||||
$s .= implode(', ',$flds).') CASCADE CONSTRAINTS';
|
||||
$sql[] = $s;
|
||||
return $sql;
|
||||
}
|
||||
|
||||
function _DropAutoIncrement($t)
|
||||
{
|
||||
if (strpos($t,'.') !== false) {
|
||||
$tarr = explode('.',$t);
|
||||
return "drop sequence ".$tarr[0].".seq_".$tarr[1];
|
||||
}
|
||||
return "drop sequence seq_".$t;
|
||||
}
|
||||
|
||||
// return string must begin with space
|
||||
function _CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned)
|
||||
{
|
||||
$suffix = '';
|
||||
|
||||
if ($fdefault == "''" && $fnotnull) {// this is null in oracle
|
||||
$fnotnull = false;
|
||||
if ($this->debug) ADOConnection::outp("NOT NULL and DEFAULT='' illegal in Oracle");
|
||||
}
|
||||
|
||||
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
|
||||
if ($fnotnull) $suffix .= ' NOT NULL';
|
||||
|
||||
if ($fautoinc) $this->seqField = $fname;
|
||||
if ($fconstraint) $suffix .= ' '.$fconstraint;
|
||||
|
||||
return $suffix;
|
||||
}
|
||||
|
||||
/*
|
||||
CREATE or replace TRIGGER jaddress_insert
|
||||
before insert on jaddress
|
||||
for each row
|
||||
begin
|
||||
select seqaddress.nextval into :new.A_ID from dual;
|
||||
end;
|
||||
*/
|
||||
function _Triggers($tabname,$tableoptions)
|
||||
{
|
||||
if (!$this->seqField) return array();
|
||||
|
||||
if ($this->schema) {
|
||||
$t = strpos($tabname,'.');
|
||||
if ($t !== false) $tab = substr($tabname,$t+1);
|
||||
else $tab = $tabname;
|
||||
$seqname = $this->schema.'.'.$this->seqPrefix.$tab;
|
||||
$trigname = $this->schema.'.'.$this->trigPrefix.$this->seqPrefix.$tab;
|
||||
} else {
|
||||
$seqname = $this->seqPrefix.$tabname;
|
||||
$trigname = $this->trigPrefix.$seqname;
|
||||
}
|
||||
if (isset($tableoptions['REPLACE'])) $sql[] = "DROP SEQUENCE $seqname";
|
||||
$seqCache = '';
|
||||
if (isset($tableoptions['SEQUENCE_CACHE'])){$seqCache = $tableoptions['SEQUENCE_CACHE'];}
|
||||
$seqIncr = '';
|
||||
if (isset($tableoptions['SEQUENCE_INCREMENT'])){$seqIncr = ' INCREMENT BY '.$tableoptions['SEQUENCE_INCREMENT'];}
|
||||
$seqStart = '';
|
||||
if (isset($tableoptions['SEQUENCE_START'])){$seqIncr = ' START WITH '.$tableoptions['SEQUENCE_START'];}
|
||||
$sql[] = "CREATE SEQUENCE $seqname $seqStart $seqIncr $seqCache";
|
||||
$sql[] = "CREATE OR REPLACE TRIGGER $trigname BEFORE insert ON $tabname FOR EACH ROW WHEN (NEW.$this->seqField IS NULL OR NEW.$this->seqField = 0) BEGIN select $seqname.nextval into :new.$this->seqField from dual; END;";
|
||||
|
||||
$this->seqField = false;
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/*
|
||||
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)]
|
||||
[table_options] [select_statement]
|
||||
create_definition:
|
||||
col_name type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT]
|
||||
[PRIMARY KEY] [reference_definition]
|
||||
or PRIMARY KEY (index_col_name,...)
|
||||
or KEY [index_name] (index_col_name,...)
|
||||
or INDEX [index_name] (index_col_name,...)
|
||||
or UNIQUE [INDEX] [index_name] (index_col_name,...)
|
||||
or FULLTEXT [INDEX] [index_name] (index_col_name,...)
|
||||
or [CONSTRAINT symbol] FOREIGN KEY [index_name] (index_col_name,...)
|
||||
[reference_definition]
|
||||
or CHECK (expr)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
function _IndexSQL($idxname, $tabname, $flds,$idxoptions)
|
||||
{
|
||||
$sql = array();
|
||||
|
||||
if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {
|
||||
$sql[] = sprintf ($this->dropIndex, $idxname, $tabname);
|
||||
if ( isset($idxoptions['DROP']) )
|
||||
return $sql;
|
||||
}
|
||||
|
||||
if ( empty ($flds) ) {
|
||||
return $sql;
|
||||
}
|
||||
|
||||
if (isset($idxoptions['BITMAP'])) {
|
||||
$unique = ' BITMAP';
|
||||
} elseif (isset($idxoptions['UNIQUE'])) {
|
||||
$unique = ' UNIQUE';
|
||||
} else {
|
||||
$unique = '';
|
||||
}
|
||||
|
||||
if ( is_array($flds) )
|
||||
$flds = implode(', ',$flds);
|
||||
$s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname . ' (' . $flds . ')';
|
||||
|
||||
if ( isset($idxoptions[$this->upperName]) )
|
||||
$s .= $idxoptions[$this->upperName];
|
||||
|
||||
if (isset($idxoptions['oci8']))
|
||||
$s .= $idxoptions['oci8'];
|
||||
|
||||
|
||||
$sql[] = $s;
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
function GetCommentSQL($table,$col)
|
||||
{
|
||||
$table = $this->connection->qstr($table);
|
||||
$col = $this->connection->qstr($col);
|
||||
return "select comments from USER_COL_COMMENTS where TABLE_NAME=$table and COLUMN_NAME=$col";
|
||||
}
|
||||
|
||||
function SetCommentSQL($table,$col,$cmt)
|
||||
{
|
||||
$cmt = $this->connection->qstr($cmt);
|
||||
return "COMMENT ON COLUMN $table.$col IS $cmt";
|
||||
}
|
||||
}
|
||||
?>
|
371
classes/adodb-hack/drivers/datadict-pgsql.inc.php
Normal file
371
classes/adodb-hack/drivers/datadict-pgsql.inc.php
Normal file
@ -0,0 +1,371 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
V4.80 8 Mar 2006 (c) 2000-2006 John Lim (jlim@natsoft.com.my). All rights reserved.
|
||||
Released under both BSD license and Lesser GPL library license.
|
||||
Whenever there is any discrepancy between the two licenses,
|
||||
the BSD license will take precedence.
|
||||
|
||||
Set tabs to 4 for best viewing.
|
||||
|
||||
*/
|
||||
|
||||
// security - hide paths
|
||||
if (!defined('ADODB_DIR')) die();
|
||||
|
||||
class ADODB2_pgsql extends ADODB_DataDict {
|
||||
|
||||
var $databaseType = 'postgres';
|
||||
var $seqField = false;
|
||||
var $seqPrefix = 'SEQ_';
|
||||
var $addCol = ' ADD COLUMN';
|
||||
var $quote = '"';
|
||||
var $renameTable = 'ALTER TABLE %s RENAME TO %s'; // at least since 7.1
|
||||
var $dropTable = 'DROP TABLE %s CASCADE';
|
||||
|
||||
function MetaType($t,$len=-1,$fieldobj=false)
|
||||
{
|
||||
if (is_object($t)) {
|
||||
$fieldobj = $t;
|
||||
$t = $fieldobj->type;
|
||||
$len = $fieldobj->max_length;
|
||||
}
|
||||
$is_serial = is_object($fieldobj) && $fieldobj->primary_key && $fieldobj->unique &&
|
||||
$fieldobj->has_default && substr($fieldobj->default_value,0,8) == 'nextval(';
|
||||
|
||||
switch (strtoupper($t)) {
|
||||
case 'INTERVAL':
|
||||
case 'CHAR':
|
||||
case 'CHARACTER':
|
||||
case 'VARCHAR':
|
||||
case 'NAME':
|
||||
case 'BPCHAR':
|
||||
if ($len <= $this->blobSize) return 'C';
|
||||
|
||||
case 'TEXT':
|
||||
return 'X';
|
||||
|
||||
case 'IMAGE': // user defined type
|
||||
case 'BLOB': // user defined type
|
||||
case 'BIT': // This is a bit string, not a single bit, so don't return 'L'
|
||||
case 'VARBIT':
|
||||
case 'BYTEA':
|
||||
return 'B';
|
||||
|
||||
case 'BOOL':
|
||||
case 'BOOLEAN':
|
||||
return 'L';
|
||||
|
||||
case 'DATE':
|
||||
return 'D';
|
||||
|
||||
case 'TIME':
|
||||
case 'DATETIME':
|
||||
case 'TIMESTAMP':
|
||||
case 'TIMESTAMPTZ':
|
||||
return 'T';
|
||||
|
||||
case 'INTEGER': return !$is_serial ? 'I' : 'R';
|
||||
case 'SMALLINT':
|
||||
case 'INT2': return !$is_serial ? 'I2' : 'R';
|
||||
case 'INT4': return !$is_serial ? 'I4' : 'R';
|
||||
case 'BIGINT':
|
||||
case 'INT8': return !$is_serial ? 'I8' : 'R';
|
||||
|
||||
case 'OID':
|
||||
case 'SERIAL':
|
||||
return 'R';
|
||||
|
||||
case 'FLOAT4':
|
||||
case 'FLOAT8':
|
||||
case 'DOUBLE PRECISION':
|
||||
case 'REAL':
|
||||
return 'F';
|
||||
|
||||
default:
|
||||
return 'N';
|
||||
}
|
||||
}
|
||||
|
||||
function ActualType($meta)
|
||||
{
|
||||
switch($meta) {
|
||||
case 'C': return 'VARCHAR';
|
||||
case 'XL':
|
||||
case 'X': return 'TEXT';
|
||||
|
||||
case 'C2': return 'VARCHAR';
|
||||
case 'X2': return 'TEXT';
|
||||
|
||||
case 'B': return 'BYTEA';
|
||||
|
||||
case 'D': return 'DATE';
|
||||
case 'T': return 'TIMESTAMP';
|
||||
|
||||
case 'L': return 'BOOLEAN';
|
||||
case 'I': return 'INTEGER';
|
||||
case 'I1': return 'SMALLINT';
|
||||
case 'I2': return 'INT2';
|
||||
case 'I4': return 'INT4';
|
||||
case 'I8': return 'INT8';
|
||||
|
||||
case 'F': return 'FLOAT8';
|
||||
case 'N': return 'NUMERIC';
|
||||
default:
|
||||
return $meta;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adding a new Column
|
||||
*
|
||||
* reimplementation of the default function as postgres does NOT allow to set the default in the same statement
|
||||
*
|
||||
* @param string $tabname table-name
|
||||
* @param string $flds column-names and types for the changed columns
|
||||
* @return array with SQL strings
|
||||
*/
|
||||
function AddColumnSQL($tabname, $flds)
|
||||
{
|
||||
$tabname = $this->TableName ($tabname);
|
||||
$sql = array();
|
||||
list($lines,$pkey) = $this->_GenFields($flds);
|
||||
$alter = 'ALTER TABLE ' . $tabname . $this->addCol . ' ';
|
||||
foreach($lines as $v) {
|
||||
if (($not_null = preg_match('/NOT NULL/i',$v))) {
|
||||
$v = preg_replace('/NOT NULL/i','',$v);
|
||||
}
|
||||
if (preg_match('/^([^ ]+) .*DEFAULT ([^ ]+)/',$v,$matches)) {
|
||||
list(,$colname,$default) = $matches;
|
||||
$sql[] = $alter . str_replace('DEFAULT '.$default,'',$v);
|
||||
$sql[] = 'UPDATE '.$tabname.' SET '.$colname.'='.$default;
|
||||
$sql[] = 'ALTER TABLE '.$tabname.' ALTER COLUMN '.$colname.' SET DEFAULT ' . $default;
|
||||
} else {
|
||||
$sql[] = $alter . $v;
|
||||
}
|
||||
if ($not_null) {
|
||||
list($colname) = explode(' ',$v);
|
||||
$sql[] = 'ALTER TABLE '.$tabname.' ALTER COLUMN '.$colname.' SET NOT NULL';
|
||||
}
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the definition of one column
|
||||
*
|
||||
* Postgres can't do that on it's own, you need to supply the complete defintion of the new table,
|
||||
* to allow, recreating the table and copying the content over to the new table
|
||||
* @param string $tabname table-name
|
||||
* @param string $flds column-name and type for the changed column
|
||||
* @param string $tableflds complete defintion of the new table, eg. for postgres, default ''
|
||||
* @param array/ $tableoptions options for the new table see CreateTableSQL, default ''
|
||||
* @return array with SQL strings
|
||||
*/
|
||||
function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
|
||||
{
|
||||
if (!$tableflds) {
|
||||
if ($this->debug) ADOConnection::outp("AlterColumnSQL needs a complete table-definiton for PostgreSQL");
|
||||
return array();
|
||||
}
|
||||
return $this->_recreate_copy_table($tabname,False,$tableflds,$tableoptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop one column
|
||||
*
|
||||
* Postgres < 7.3 can't do that on it's own, you need to supply the complete defintion of the new table,
|
||||
* to allow, recreating the table and copying the content over to the new table
|
||||
* @param string $tabname table-name
|
||||
* @param string $flds column-name and type for the changed column
|
||||
* @param string $tableflds complete defintion of the new table, eg. for postgres, default ''
|
||||
* @param array/ $tableoptions options for the new table see CreateTableSQL, default ''
|
||||
* @return array with SQL strings
|
||||
*/
|
||||
function DropColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
|
||||
{
|
||||
$has_drop_column = 7.3 <= (float) @$this->serverInfo['version'];
|
||||
if (!$has_drop_column && !$tableflds) {
|
||||
if ($this->debug) ADOConnection::outp("DropColumnSQL needs complete table-definiton for PostgreSQL < 7.3");
|
||||
return array();
|
||||
}
|
||||
if ($has_drop_column) {
|
||||
return ADODB_DataDict::DropColumnSQL($tabname, $flds);
|
||||
}
|
||||
return $this->_recreate_copy_table($tabname,$flds,$tableflds,$tableoptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the content into a temp. table, drop and recreate the original table and copy the content back in
|
||||
*
|
||||
* We also take care to set the values of the sequenz and recreate the indexes.
|
||||
* All this is done in a transaction, to not loose the content of the table, if something went wrong!
|
||||
* @internal
|
||||
* @param string $tabname table-name
|
||||
* @param string $dropflds column-names to drop
|
||||
* @param string $tableflds complete defintion of the new table, eg. for postgres
|
||||
* @param array/string $tableoptions options for the new table see CreateTableSQL, default ''
|
||||
* @return array with SQL strings
|
||||
*/
|
||||
function _recreate_copy_table($tabname,$dropflds,$tableflds,$tableoptions='')
|
||||
{
|
||||
if ($dropflds && !is_array($dropflds)) $dropflds = explode(',',$dropflds);
|
||||
$copyflds = array();
|
||||
foreach($this->MetaColumns($tabname) as $fld) {
|
||||
if (!$dropflds || !in_array($fld->name,$dropflds)) {
|
||||
// we need to explicit convert varchar to a number to be able to do an AlterColumn of a char column to a nummeric one
|
||||
if (preg_match('/'.$fld->name.' (I|I2|I4|I8|N|F)/i',$tableflds,$matches) &&
|
||||
in_array($fld->type,array('varchar','char','text','bytea'))) {
|
||||
$copyflds[] = "to_number($fld->name,'S9999999999999D99')";
|
||||
} else {
|
||||
$copyflds[] = $fld->name;
|
||||
}
|
||||
// identify the sequence name and the fld its on
|
||||
if ($fld->primary_key && $fld->has_default &&
|
||||
preg_match("/nextval\('([^']+)'::text\)/",$fld->default_value,$matches)) {
|
||||
$seq_name = $matches[1];
|
||||
$seq_fld = $fld->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
$copyflds = implode(', ',$copyflds);
|
||||
|
||||
$tempname = $tabname.'_tmp';
|
||||
$aSql[] = 'BEGIN'; // we use a transaction, to make sure not to loose the content of the table
|
||||
$aSql[] = "SELECT * INTO TEMPORARY TABLE $tempname FROM $tabname";
|
||||
$aSql = array_merge($aSql,$this->DropTableSQL($tabname));
|
||||
$aSql = array_merge($aSql,$this->CreateTableSQL($tabname,$tableflds,$tableoptions));
|
||||
$aSql[] = "INSERT INTO $tabname SELECT $copyflds FROM $tempname";
|
||||
if ($seq_name && $seq_fld) { // if we have a sequence we need to set it again
|
||||
$seq_name = $tabname.'_'.$seq_fld.'_seq'; // has to be the name of the new implicit sequence
|
||||
$aSql[] = "SELECT setval('$seq_name',MAX($seq_fld)) FROM $tabname";
|
||||
}
|
||||
$aSql[] = "DROP TABLE $tempname";
|
||||
// recreate the indexes, if they not contain one of the droped columns
|
||||
foreach($this->MetaIndexes($tabname) as $idx_name => $idx_data)
|
||||
{
|
||||
if (substr($idx_name,-5) != '_pkey' && (!$dropflds || !count(array_intersect($dropflds,$idx_data['columns'])))) {
|
||||
$aSql = array_merge($aSql,$this->CreateIndexSQL($idx_name,$tabname,$idx_data['columns'],
|
||||
$idx_data['unique'] ? array('UNIQUE') : False));
|
||||
}
|
||||
}
|
||||
$aSql[] = 'COMMIT';
|
||||
return $aSql;
|
||||
}
|
||||
|
||||
function DropTableSQL($tabname)
|
||||
{
|
||||
$sql = ADODB_DataDict::DropTableSQL($tabname);
|
||||
|
||||
$drop_seq = $this->_DropAutoIncrement($tabname);
|
||||
if ($drop_seq) $sql[] = $drop_seq;
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
// return string must begin with space
|
||||
function _CreateSuffix($fname, &$ftype, $fnotnull,$fdefault,$fautoinc,$fconstraint)
|
||||
{
|
||||
if ($fautoinc) {
|
||||
$ftype = 'SERIAL';
|
||||
return '';
|
||||
}
|
||||
$suffix = '';
|
||||
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
|
||||
if ($fnotnull) $suffix .= ' NOT NULL';
|
||||
if ($fconstraint) $suffix .= ' '.$fconstraint;
|
||||
return $suffix;
|
||||
}
|
||||
|
||||
// search for a sequece for the given table (asumes the seqence-name contains the table-name!)
|
||||
// if yes return sql to drop it
|
||||
// this is still necessary if postgres < 7.3 or the SERIAL was created on an earlier version!!!
|
||||
function _DropAutoIncrement($tabname)
|
||||
{
|
||||
$tabname = $this->connection->quote('%'.$tabname.'%');
|
||||
|
||||
$seq = $this->connection->GetOne("SELECT relname FROM pg_class WHERE NOT relname ~ 'pg_.*' AND relname LIKE $tabname AND relkind='S'");
|
||||
|
||||
// check if a tables depends on the sequenz and it therefor cant and dont need to be droped separatly
|
||||
if (!$seq || $this->connection->GetOne("SELECT relname FROM pg_class JOIN pg_depend ON pg_class.relfilenode=pg_depend.objid WHERE relname='$seq' AND relkind='S' AND deptype='i'")) {
|
||||
return False;
|
||||
}
|
||||
return "DROP SEQUENCE ".$seq;
|
||||
}
|
||||
|
||||
/*
|
||||
CREATE [ [ LOCAL ] { TEMPORARY | TEMP } ] TABLE table_name (
|
||||
{ column_name data_type [ DEFAULT default_expr ] [ column_constraint [, ... ] ]
|
||||
| table_constraint } [, ... ]
|
||||
)
|
||||
[ INHERITS ( parent_table [, ... ] ) ]
|
||||
[ WITH OIDS | WITHOUT OIDS ]
|
||||
where column_constraint is:
|
||||
[ CONSTRAINT constraint_name ]
|
||||
{ NOT NULL | NULL | UNIQUE | PRIMARY KEY |
|
||||
CHECK (expression) |
|
||||
REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL ]
|
||||
[ ON DELETE action ] [ ON UPDATE action ] }
|
||||
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
|
||||
and table_constraint is:
|
||||
[ CONSTRAINT constraint_name ]
|
||||
{ UNIQUE ( column_name [, ... ] ) |
|
||||
PRIMARY KEY ( column_name [, ... ] ) |
|
||||
CHECK ( expression ) |
|
||||
FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ]
|
||||
[ MATCH FULL | MATCH PARTIAL ] [ ON DELETE action ] [ ON UPDATE action ] }
|
||||
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
CREATE [ UNIQUE ] INDEX index_name ON table
|
||||
[ USING acc_method ] ( column [ ops_name ] [, ...] )
|
||||
[ WHERE predicate ]
|
||||
CREATE [ UNIQUE ] INDEX index_name ON table
|
||||
[ USING acc_method ] ( func_name( column [, ... ]) [ ops_name ] )
|
||||
[ WHERE predicate ]
|
||||
*/
|
||||
function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
|
||||
{
|
||||
$sql = array();
|
||||
|
||||
if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {
|
||||
$sql[] = sprintf ($this->dropIndex, $idxname, $tabname);
|
||||
if ( isset($idxoptions['DROP']) )
|
||||
return $sql;
|
||||
}
|
||||
|
||||
if ( empty ($flds) ) {
|
||||
return $sql;
|
||||
}
|
||||
|
||||
$unique = isset($idxoptions['UNIQUE']) ? ' UNIQUE' : '';
|
||||
|
||||
$s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname . ' ';
|
||||
|
||||
if (isset($idxoptions['HASH']))
|
||||
$s .= 'USING HASH ';
|
||||
|
||||
if ( isset($idxoptions[$this->upperName]) )
|
||||
$s .= $idxoptions[$this->upperName];
|
||||
|
||||
if ( is_array($flds) )
|
||||
$flds = implode(', ',$flds);
|
||||
$s .= '(' . $flds . ')';
|
||||
$sql[] = $s;
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
function _GetSize($ftype, $ty, $fsize, $fprec)
|
||||
{
|
||||
if (strlen($fsize) && $ty != 'X' && $ty != 'B' && $ty != 'I' && strpos($ftype,'(') === false) {
|
||||
$ftype .= "(".$fsize;
|
||||
if (strlen($fprec)) $ftype .= ",".$fprec;
|
||||
$ftype .= ')';
|
||||
}
|
||||
return $ftype;
|
||||
}
|
||||
}
|
||||
?>
|
121
classes/adodb-hack/drivers/datadict-sapdb.inc.php
Normal file
121
classes/adodb-hack/drivers/datadict-sapdb.inc.php
Normal file
@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
V4.50 6 July 2004 (c) 2000-2006 John Lim (jlim@natsoft.com.my). All rights reserved.
|
||||
Released under both BSD license and Lesser GPL library license.
|
||||
Whenever there is any discrepancy between the two licenses,
|
||||
the BSD license will take precedence.
|
||||
|
||||
Set tabs to 4 for best viewing.
|
||||
|
||||
Modified from datadict-generic.inc.php for sapdb by RalfBecker-AT-outdoor-training.de
|
||||
*/
|
||||
|
||||
// security - hide paths
|
||||
if (!defined('ADODB_DIR')) die();
|
||||
|
||||
class ADODB2_sapdb extends ADODB_DataDict {
|
||||
|
||||
var $databaseType = 'sapdb';
|
||||
var $seqField = false;
|
||||
var $renameColumn = 'RENAME COLUMN %s.%s TO %s';
|
||||
|
||||
function ActualType($meta)
|
||||
{
|
||||
switch($meta) {
|
||||
case 'C': return 'VARCHAR';
|
||||
case 'XL':
|
||||
case 'X': return 'LONG';
|
||||
|
||||
case 'C2': return 'VARCHAR UNICODE';
|
||||
case 'X2': return 'LONG UNICODE';
|
||||
|
||||
case 'B': return 'LONG';
|
||||
|
||||
case 'D': return 'DATE';
|
||||
case 'T': return 'TIMESTAMP';
|
||||
|
||||
case 'L': return 'BOOLEAN';
|
||||
case 'I': return 'INTEGER';
|
||||
case 'I1': return 'FIXED(3)';
|
||||
case 'I2': return 'SMALLINT';
|
||||
case 'I4': return 'INTEGER';
|
||||
case 'I8': return 'FIXED(20)';
|
||||
|
||||
case 'F': return 'FLOAT(38)';
|
||||
case 'N': return 'FIXED';
|
||||
default:
|
||||
return $meta;
|
||||
}
|
||||
}
|
||||
|
||||
function MetaType($t,$len=-1,$fieldobj=false)
|
||||
{
|
||||
if (is_object($t)) {
|
||||
$fieldobj = $t;
|
||||
$t = $fieldobj->type;
|
||||
$len = $fieldobj->max_length;
|
||||
}
|
||||
static $maxdb_type2adodb = array(
|
||||
'VARCHAR' => 'C',
|
||||
'CHARACTER' => 'C',
|
||||
'LONG' => 'X', // no way to differ between 'X' and 'B' :-(
|
||||
'DATE' => 'D',
|
||||
'TIMESTAMP' => 'T',
|
||||
'BOOLEAN' => 'L',
|
||||
'INTEGER' => 'I4',
|
||||
'SMALLINT' => 'I2',
|
||||
'FLOAT' => 'F',
|
||||
'FIXED' => 'N',
|
||||
);
|
||||
$type = isset($maxdb_type2adodb[$t]) ? $maxdb_type2adodb[$t] : 'C';
|
||||
|
||||
// convert integer-types simulated with fixed back to integer
|
||||
if ($t == 'FIXED' && !$fieldobj->scale && ($len == 20 || $len == 3)) {
|
||||
$type = $len == 20 ? 'I8' : 'I1';
|
||||
}
|
||||
if ($fieldobj->auto_increment) $type = 'R';
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
// return string must begin with space
|
||||
function _CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned)
|
||||
{
|
||||
$suffix = '';
|
||||
if ($funsigned) $suffix .= ' UNSIGNED';
|
||||
if ($fnotnull) $suffix .= ' NOT NULL';
|
||||
if ($fautoinc) $suffix .= ' DEFAULT SERIAL';
|
||||
elseif (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
|
||||
if ($fconstraint) $suffix .= ' '.$fconstraint;
|
||||
return $suffix;
|
||||
}
|
||||
|
||||
function AddColumnSQL($tabname, $flds)
|
||||
{
|
||||
$tabname = $this->TableName ($tabname);
|
||||
$sql = array();
|
||||
list($lines,$pkey) = $this->_GenFields($flds);
|
||||
return array( 'ALTER TABLE ' . $tabname . ' ADD (' . implode(', ',$lines) . ')' );
|
||||
}
|
||||
|
||||
function AlterColumnSQL($tabname, $flds)
|
||||
{
|
||||
$tabname = $this->TableName ($tabname);
|
||||
$sql = array();
|
||||
list($lines,$pkey) = $this->_GenFields($flds);
|
||||
return array( 'ALTER TABLE ' . $tabname . ' MODIFY (' . implode(', ',$lines) . ')' );
|
||||
}
|
||||
|
||||
function DropColumnSQL($tabname, $flds)
|
||||
{
|
||||
$tabname = $this->TableName ($tabname);
|
||||
if (!is_array($flds)) $flds = explode(',',$flds);
|
||||
foreach($flds as $k => $v) {
|
||||
$flds[$k] = $this->NameQuote($v);
|
||||
}
|
||||
return array( 'ALTER TABLE ' . $tabname . ' DROP (' . implode(', ',$flds) . ')' );
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
228
classes/adodb-hack/drivers/datadict-sybase.inc.php
Normal file
228
classes/adodb-hack/drivers/datadict-sybase.inc.php
Normal file
@ -0,0 +1,228 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
V4.80 8 Mar 2006 (c) 2000-2006 John Lim (jlim@natsoft.com.my). All rights reserved.
|
||||
Released under both BSD license and Lesser GPL library license.
|
||||
Whenever there is any discrepancy between the two licenses,
|
||||
the BSD license will take precedence.
|
||||
|
||||
Set tabs to 4 for best viewing.
|
||||
|
||||
*/
|
||||
|
||||
// security - hide paths
|
||||
if (!defined('ADODB_DIR')) die();
|
||||
|
||||
class ADODB2_sybase extends ADODB_DataDict {
|
||||
var $databaseType = 'sybase';
|
||||
|
||||
var $dropIndex = 'DROP INDEX %2$s.%1$s';
|
||||
|
||||
function MetaType($t,$len=-1,$fieldobj=false)
|
||||
{
|
||||
if (is_object($t)) {
|
||||
$fieldobj = $t;
|
||||
$t = $fieldobj->type;
|
||||
$len = $fieldobj->max_length;
|
||||
}
|
||||
|
||||
$len = -1; // mysql max_length is not accurate
|
||||
switch (strtoupper($t)) {
|
||||
|
||||
case 'INT':
|
||||
case 'INTEGER': return 'I';
|
||||
case 'BIT':
|
||||
case 'TINYINT': return 'I1';
|
||||
case 'SMALLINT': return 'I2';
|
||||
case 'BIGINT': return 'I8';
|
||||
|
||||
case 'REAL':
|
||||
case 'FLOAT': return 'F';
|
||||
default: return parent::MetaType($t,$len,$fieldobj);
|
||||
}
|
||||
}
|
||||
|
||||
function ActualType($meta)
|
||||
{
|
||||
switch(strtoupper($meta)) {
|
||||
case 'C': return 'VARCHAR';
|
||||
case 'XL':
|
||||
case 'X': return 'TEXT';
|
||||
|
||||
case 'C2': return 'NVARCHAR';
|
||||
case 'X2': return 'NTEXT';
|
||||
|
||||
case 'B': return 'IMAGE';
|
||||
|
||||
case 'D': return 'DATETIME';
|
||||
case 'T': return 'DATETIME';
|
||||
case 'L': return 'BIT';
|
||||
|
||||
case 'I': return 'INT';
|
||||
case 'I1': return 'TINYINT';
|
||||
case 'I2': return 'SMALLINT';
|
||||
case 'I4': return 'INT';
|
||||
case 'I8': return 'BIGINT';
|
||||
|
||||
case 'F': return 'REAL';
|
||||
case 'N': return 'NUMERIC';
|
||||
default:
|
||||
return $meta;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function AddColumnSQL($tabname, $flds)
|
||||
{
|
||||
$tabname = $this->TableName ($tabname);
|
||||
$f = array();
|
||||
list($lines,$pkey) = $this->_GenFields($flds);
|
||||
$s = "ALTER TABLE $tabname $this->addCol";
|
||||
foreach($lines as $v) {
|
||||
$f[] = "\n $v";
|
||||
}
|
||||
$s .= implode(', ',$f);
|
||||
$sql[] = $s;
|
||||
return $sql;
|
||||
}
|
||||
|
||||
function AlterColumnSQL($tabname, $flds)
|
||||
{
|
||||
$tabname = $this->TableName ($tabname);
|
||||
$sql = array();
|
||||
list($lines,$pkey) = $this->_GenFields($flds);
|
||||
foreach($lines as $v) {
|
||||
$sql[] = "ALTER TABLE $tabname $this->alterCol $v";
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
function DropColumnSQL($tabname, $flds)
|
||||
{
|
||||
$tabname = $this->TableName($tabname);
|
||||
if (!is_array($flds)) $flds = explode(',',$flds);
|
||||
$f = array();
|
||||
$s = "ALTER TABLE $tabname";
|
||||
foreach($flds as $v) {
|
||||
$f[] = "\n$this->dropCol ".$this->NameQuote($v);
|
||||
}
|
||||
$s .= implode(', ',$f);
|
||||
$sql[] = $s;
|
||||
return $sql;
|
||||
}
|
||||
|
||||
// return string must begin with space
|
||||
function _CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint)
|
||||
{
|
||||
$suffix = '';
|
||||
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
|
||||
if ($fautoinc) $suffix .= ' DEFAULT AUTOINCREMENT';
|
||||
if ($fnotnull) $suffix .= ' NOT NULL';
|
||||
else if ($suffix == '') $suffix .= ' NULL';
|
||||
if ($fconstraint) $suffix .= ' '.$fconstraint;
|
||||
return $suffix;
|
||||
}
|
||||
|
||||
/*
|
||||
CREATE TABLE
|
||||
[ database_name.[ owner ] . | owner. ] table_name
|
||||
( { < column_definition >
|
||||
| column_name AS computed_column_expression
|
||||
| < table_constraint > ::= [ CONSTRAINT constraint_name ] }
|
||||
|
||||
| [ { PRIMARY KEY | UNIQUE } [ ,...n ]
|
||||
)
|
||||
|
||||
[ ON { filegroup | DEFAULT } ]
|
||||
[ TEXTIMAGE_ON { filegroup | DEFAULT } ]
|
||||
|
||||
< column_definition > ::= { column_name data_type }
|
||||
[ COLLATE < collation_name > ]
|
||||
[ [ DEFAULT constant_expression ]
|
||||
| [ IDENTITY [ ( seed , increment ) [ NOT FOR REPLICATION ] ] ]
|
||||
]
|
||||
[ ROWGUIDCOL]
|
||||
[ < column_constraint > ] [ ...n ]
|
||||
|
||||
< column_constraint > ::= [ CONSTRAINT constraint_name ]
|
||||
{ [ NULL | NOT NULL ]
|
||||
| [ { PRIMARY KEY | UNIQUE }
|
||||
[ CLUSTERED | NONCLUSTERED ]
|
||||
[ WITH FILLFACTOR = fillfactor ]
|
||||
[ON {filegroup | DEFAULT} ] ]
|
||||
]
|
||||
| [ [ FOREIGN KEY ]
|
||||
REFERENCES ref_table [ ( ref_column ) ]
|
||||
[ ON DELETE { CASCADE | NO ACTION } ]
|
||||
[ ON UPDATE { CASCADE | NO ACTION } ]
|
||||
[ NOT FOR REPLICATION ]
|
||||
]
|
||||
| CHECK [ NOT FOR REPLICATION ]
|
||||
( logical_expression )
|
||||
}
|
||||
|
||||
< table_constraint > ::= [ CONSTRAINT constraint_name ]
|
||||
{ [ { PRIMARY KEY | UNIQUE }
|
||||
[ CLUSTERED | NONCLUSTERED ]
|
||||
{ ( column [ ASC | DESC ] [ ,...n ] ) }
|
||||
[ WITH FILLFACTOR = fillfactor ]
|
||||
[ ON { filegroup | DEFAULT } ]
|
||||
]
|
||||
| FOREIGN KEY
|
||||
[ ( column [ ,...n ] ) ]
|
||||
REFERENCES ref_table [ ( ref_column [ ,...n ] ) ]
|
||||
[ ON DELETE { CASCADE | NO ACTION } ]
|
||||
[ ON UPDATE { CASCADE | NO ACTION } ]
|
||||
[ NOT FOR REPLICATION ]
|
||||
| CHECK [ NOT FOR REPLICATION ]
|
||||
( search_conditions )
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
CREATE [ UNIQUE ] [ CLUSTERED | NONCLUSTERED ] INDEX index_name
|
||||
ON { table | view } ( column [ ASC | DESC ] [ ,...n ] )
|
||||
[ WITH < index_option > [ ,...n] ]
|
||||
[ ON filegroup ]
|
||||
< index_option > :: =
|
||||
{ PAD_INDEX |
|
||||
FILLFACTOR = fillfactor |
|
||||
IGNORE_DUP_KEY |
|
||||
DROP_EXISTING |
|
||||
STATISTICS_NORECOMPUTE |
|
||||
SORT_IN_TEMPDB
|
||||
}
|
||||
*/
|
||||
function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
|
||||
{
|
||||
$sql = array();
|
||||
|
||||
if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {
|
||||
$sql[] = sprintf ($this->dropIndex, $idxname, $tabname);
|
||||
if ( isset($idxoptions['DROP']) )
|
||||
return $sql;
|
||||
}
|
||||
|
||||
if ( empty ($flds) ) {
|
||||
return $sql;
|
||||
}
|
||||
|
||||
$unique = isset($idxoptions['UNIQUE']) ? ' UNIQUE' : '';
|
||||
$clustered = isset($idxoptions['CLUSTERED']) ? ' CLUSTERED' : '';
|
||||
|
||||
if ( is_array($flds) )
|
||||
$flds = implode(', ',$flds);
|
||||
$s = 'CREATE' . $unique . $clustered . ' INDEX ' . $idxname . ' ON ' . $tabname . ' (' . $flds . ')';
|
||||
|
||||
if ( isset($idxoptions[$this->upperName]) )
|
||||
$s .= $idxoptions[$this->upperName];
|
||||
|
||||
$sql[] = $s;
|
||||
|
||||
return $sql;
|
||||
}
|
||||
}
|
||||
?>
|
89
classes/adodb-hack/drivers/odbc/odbc_datadict.inc
Normal file
89
classes/adodb-hack/drivers/odbc/odbc_datadict.inc
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/**
|
||||
V4.65 22 July 2005 (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
|
||||
Released under both BSD license and Lesser GPL library license.
|
||||
Whenever there is any discrepancy between the two licenses,
|
||||
the BSD license will take precedence.
|
||||
|
||||
Set tabs to 4 for best viewing.
|
||||
|
||||
Modified 28 August, 2005 for use with ADOdb Lite by Mark Dickenson
|
||||
|
||||
*/
|
||||
|
||||
// security - hide paths
|
||||
if (!defined('ADODB_DIR')) die();
|
||||
|
||||
class ADODB2_odbc extends ADODB_DataDict {
|
||||
|
||||
var $dbtype = 'odbc';
|
||||
var $seqField = false;
|
||||
|
||||
|
||||
function ActualType($meta)
|
||||
{
|
||||
switch($meta) {
|
||||
case 'C': return 'VARCHAR';
|
||||
case 'XL':
|
||||
case 'X': return 'VARCHAR(250)';
|
||||
|
||||
case 'C2': return 'VARCHAR';
|
||||
case 'X2': return 'VARCHAR(250)';
|
||||
|
||||
case 'B': return 'VARCHAR';
|
||||
|
||||
case 'D': return 'DATE';
|
||||
case 'T': return 'DATE';
|
||||
|
||||
case 'L': return 'DECIMAL(1)';
|
||||
case 'I': return 'DECIMAL(10)';
|
||||
case 'I1': return 'DECIMAL(3)';
|
||||
case 'I2': return 'DECIMAL(5)';
|
||||
case 'I4': return 'DECIMAL(10)';
|
||||
case 'I8': return 'DECIMAL(20)';
|
||||
|
||||
case 'F': return 'DECIMAL(32,8)';
|
||||
case 'N': return 'DECIMAL';
|
||||
default:
|
||||
return $meta;
|
||||
}
|
||||
}
|
||||
|
||||
function AlterColumnSQL($tabname, $flds)
|
||||
{
|
||||
if ($this->debug) $this->outp("AlterColumnSQL not supported");
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
function DropColumnSQL($tabname, $flds)
|
||||
{
|
||||
if ($this->debug) $this->outp("DropColumnSQL not supported");
|
||||
return array();
|
||||
}
|
||||
|
||||
// function MetaType($t,$len=-1,$fieldobj=false)
|
||||
// {
|
||||
// }
|
||||
|
||||
// function &MetaTables($ttype=false,$showSchema=false,$mask=false)
|
||||
// {
|
||||
// global $ADODB_FETCH_MODE;
|
||||
// }
|
||||
|
||||
// function &MetaColumns($table,$upper=true)
|
||||
// {
|
||||
// global $ADODB_FETCH_MODE;
|
||||
// }
|
||||
|
||||
// function MetaPrimaryKeys($table, $owner=false)
|
||||
// {
|
||||
// }
|
||||
|
||||
// function &MetaIndexes($table, $primary = false, $owner = false)
|
||||
// {
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
?>
|
90
classes/adodb-hack/drivers/sqlite/sqlite_datadict.inc
Normal file
90
classes/adodb-hack/drivers/sqlite/sqlite_datadict.inc
Normal file
@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/**
|
||||
V4.65 22 July 2005 (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
|
||||
Released under both BSD license and Lesser GPL library license.
|
||||
Whenever there is any discrepancy between the two licenses,
|
||||
the BSD license will take precedence.
|
||||
|
||||
Set tabs to 4 for best viewing.
|
||||
|
||||
Modified 28 August, 2005 for use with ADOdb Lite by Mark Dickenson
|
||||
|
||||
*/
|
||||
|
||||
// security - hide paths
|
||||
if (!defined('ADODB_DIR')) die();
|
||||
|
||||
class ADODB2_sqlite extends ADODB_DataDict {
|
||||
|
||||
var $dbtype = 'sqlite';
|
||||
var $seqField = false;
|
||||
|
||||
var $metaTablesSQL = "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name";
|
||||
|
||||
function ActualType($meta)
|
||||
{
|
||||
switch($meta) {
|
||||
case 'C': return 'VARCHAR';
|
||||
case 'XL':
|
||||
case 'X': return 'VARCHAR(250)';
|
||||
|
||||
case 'C2': return 'VARCHAR';
|
||||
case 'X2': return 'VARCHAR(250)';
|
||||
|
||||
case 'B': return 'VARCHAR';
|
||||
|
||||
case 'D': return 'DATE';
|
||||
case 'T': return 'DATE';
|
||||
|
||||
case 'L': return 'DECIMAL(1)';
|
||||
case 'I': return 'DECIMAL(10)';
|
||||
case 'I1': return 'DECIMAL(3)';
|
||||
case 'I2': return 'DECIMAL(5)';
|
||||
case 'I4': return 'DECIMAL(10)';
|
||||
case 'I8': return 'DECIMAL(20)';
|
||||
|
||||
case 'F': return 'DECIMAL(32,8)';
|
||||
case 'N': return 'DECIMAL';
|
||||
default:
|
||||
return $meta;
|
||||
}
|
||||
}
|
||||
|
||||
function AlterColumnSQL($tabname, $flds)
|
||||
{
|
||||
if ($this->debug) $this->outp("AlterColumnSQL not supported");
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
function DropColumnSQL($tabname, $flds)
|
||||
{
|
||||
if ($this->debug) $this->outp("DropColumnSQL not supported");
|
||||
return array();
|
||||
}
|
||||
|
||||
// function MetaType($t,$len=-1,$fieldobj=false)
|
||||
// {
|
||||
// }
|
||||
|
||||
// function &MetaTables($ttype=false,$showSchema=false,$mask=false)
|
||||
// {
|
||||
// global $ADODB_FETCH_MODE;
|
||||
// }
|
||||
|
||||
// function &MetaColumns($table,$upper=true)
|
||||
// {
|
||||
// global $ADODB_FETCH_MODE;
|
||||
// }
|
||||
|
||||
// function MetaPrimaryKeys($table, $owner=false)
|
||||
// {
|
||||
// }
|
||||
|
||||
// function &MetaIndexes($table, $primary = false, $owner = false)
|
||||
// {
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
?>
|
39
tests/AccessTestCase.class.php
Normal file
39
tests/AccessTestCase.class.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
class Doctrine_AccessTestCase extends Doctrine_UnitTestCase {
|
||||
public function testOffsetMethods() {
|
||||
$this->assertEqual($this->new["name"],null);
|
||||
|
||||
$this->new["name"] = "Jack";
|
||||
$this->assertEqual($this->new["name"],"Jack");
|
||||
|
||||
$this->assertEqual($this->old["name"],"zYne");
|
||||
|
||||
$this->old["name"] = "Jack";
|
||||
$this->assertEqual($this->old["name"],"Jack");
|
||||
}
|
||||
public function testOverload() {
|
||||
$this->assertEqual($this->new->name,null);
|
||||
|
||||
$this->new->name = "Jack";
|
||||
$this->assertEqual($this->new->name,"Jack");
|
||||
|
||||
$this->assertEqual($this->old->name,"zYne");
|
||||
|
||||
$this->old->name = "Jack";
|
||||
$this->assertEqual($this->old->name,"Jack");
|
||||
}
|
||||
public function testSet() {
|
||||
$this->assertEqual($this->new->get("name"),null);
|
||||
|
||||
$this->new->set("name","Jack");
|
||||
$this->assertEqual($this->new->get("name"),"Jack");
|
||||
|
||||
$this->assertEqual($this->old->get("name"),"zYne");
|
||||
|
||||
$this->old->set("name","Jack");
|
||||
$this->assertEqual($this->old->get("name"),"Jack");
|
||||
|
||||
$this->assertEqual($this->old->getID(),4);
|
||||
}
|
||||
}
|
||||
?>
|
15
tests/BatchIteratorTestCase.class.php
Normal file
15
tests/BatchIteratorTestCase.class.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
require_once("UnitTestCase.class.php");
|
||||
class Doctrine_BatchIteratorTestCase extends Doctrine_UnitTestCase {
|
||||
public function testIterator() {
|
||||
$graph = new Doctrine_DQL_Parser($this->session);
|
||||
$entities = $graph->query("FROM Entity");
|
||||
$i = 0;
|
||||
foreach($entities as $entity) {
|
||||
$this->assertTrue(is_string($entity->name));
|
||||
$i++;
|
||||
}
|
||||
$this->assertTrue($i == $entities->count());
|
||||
}
|
||||
}
|
||||
?>
|
56
tests/CacheFileTestCase.class.php
Normal file
56
tests/CacheFileTestCase.class.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
require_once("UnitTestCase.class.php");
|
||||
class Doctrine_Cache_FileTestCase extends Doctrine_UnitTestCase {
|
||||
|
||||
public function testStore() {
|
||||
$this->cache->store($this->old);
|
||||
$this->assertTrue($this->cache->exists(4));
|
||||
|
||||
$record = $this->cache->fetch(4);
|
||||
$this->assertTrue($record instanceof Doctrine_Record);
|
||||
$this->assertTrue($record->getID() == $this->old->getID());
|
||||
|
||||
$this->assertTrue($this->cache->getTable() == $this->objTable);
|
||||
}
|
||||
public function testGetFetched() {
|
||||
$this->assertTrue(is_array($this->cache->getFetched()));
|
||||
}
|
||||
public function testGetFileName() {
|
||||
$this->assertEqual($this->manager->getRoot().DIRECTORY_SEPARATOR."cache".DIRECTORY_SEPARATOR."entity".DIRECTORY_SEPARATOR."4.cache", $this->cache->getFileName(4));
|
||||
}
|
||||
public function testGetStats() {
|
||||
$this->assertTrue(gettype($this->cache->getStats()) == "array");
|
||||
}
|
||||
public function testDestructor() {
|
||||
$this->objTable->setAttribute(Doctrine::ATTR_CACHE_TTL,1);
|
||||
$this->objTable->setAttribute(Doctrine::ATTR_CACHE_SIZE,5);
|
||||
$this->cache->__destruct();
|
||||
$this->assertTrue($this->cache->count() == 5);
|
||||
|
||||
$this->objTable->setAttribute(Doctrine::ATTR_CACHE_TTL,1);
|
||||
$this->objTable->setAttribute(Doctrine::ATTR_CACHE_SIZE,1);
|
||||
$this->cache->__destruct();
|
||||
$this->assertTrue($this->cache->count() == 1);
|
||||
|
||||
}
|
||||
public function testDeleteMultiple() {
|
||||
$this->objTable->find(5);
|
||||
$this->objTable->find(6);
|
||||
|
||||
$deleted = $this->cache->deleteMultiple(array(5,6));
|
||||
$this->assertTrue($deleted == 2);
|
||||
}
|
||||
public function testDeleteAll() {
|
||||
$this->cache->deleteAll();
|
||||
$this->assertTrue($this->cache->count() == 0);
|
||||
}
|
||||
public function testExists() {
|
||||
$this->assertFalse($this->cache->exists(313213123));
|
||||
$this->assertTrue($this->cache->exists(4));
|
||||
}
|
||||
public function testGetFactory() {
|
||||
$this->assertTrue($this->cache->getTable() == $this->objTable);
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
7
tests/CollectionTestCase.class.php
Normal file
7
tests/CollectionTestCase.class.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
class Doctrine_CollectionTestCase extends Doctrine_UnitTestCase {
|
||||
public function testAdd() {
|
||||
|
||||
}
|
||||
}
|
||||
?>
|
3
tests/CompositePrimaryKeyTestCase.class.php
Normal file
3
tests/CompositePrimaryKeyTestCase.class.php
Normal file
@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
?>
|
74
tests/ConfigurableTestCase.class.php
Normal file
74
tests/ConfigurableTestCase.class.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
require_once("UnitTestCase.class.php");
|
||||
|
||||
class Doctrine_ConfigurableTestCase extends Doctrine_UnitTestCase {
|
||||
public function testSetAttribute() {
|
||||
$this->manager->setAttribute(Doctrine::ATTR_CACHE_TTL,100);
|
||||
$this->assertEqual($this->manager->getAttribute(Doctrine::ATTR_CACHE_TTL),100);
|
||||
|
||||
$this->manager->setAttribute(Doctrine::ATTR_CACHE_SIZE,1);
|
||||
$this->assertEqual($this->manager->getAttribute(Doctrine::ATTR_CACHE_SIZE),1);
|
||||
|
||||
$this->manager->setAttribute(Doctrine::ATTR_CACHE_DIR,"%ROOT%".DIRECTORY_SEPARATOR."cache");
|
||||
$this->assertEqual($this->manager->getAttribute(Doctrine::ATTR_CACHE_DIR),$this->manager->getRoot().DIRECTORY_SEPARATOR."cache");
|
||||
|
||||
$this->manager->setAttribute(Doctrine::ATTR_FETCHMODE,Doctrine::FETCH_LAZY);
|
||||
$this->assertEqual($this->manager->getAttribute(Doctrine::ATTR_FETCHMODE),Doctrine::FETCH_LAZY);
|
||||
|
||||
$this->manager->setAttribute(Doctrine::ATTR_BATCH_SIZE, 5);
|
||||
$this->assertEqual($this->manager->getAttribute(Doctrine::ATTR_BATCH_SIZE),5);
|
||||
|
||||
$this->manager->setAttribute(Doctrine::ATTR_LISTENER, new Doctrine_Debugger());
|
||||
$this->assertTrue($this->manager->getAttribute(Doctrine::ATTR_LISTENER) instanceof Doctrine_Debugger);
|
||||
|
||||
$this->manager->setAttribute(Doctrine::ATTR_PK_COLUMNS, array("id"));
|
||||
$this->assertEqual($this->manager->getAttribute(Doctrine::ATTR_PK_COLUMNS), array("id"));
|
||||
|
||||
$this->manager->setAttribute(Doctrine::ATTR_PK_TYPE, Doctrine::INCREMENT_KEY);
|
||||
$this->assertEqual($this->manager->getAttribute(Doctrine::ATTR_PK_TYPE), Doctrine::INCREMENT_KEY);
|
||||
|
||||
$this->manager->setAttribute(Doctrine::ATTR_LOCKMODE, Doctrine::LOCK_PESSIMISTIC);
|
||||
$this->assertEqual($this->manager->getAttribute(Doctrine::ATTR_LOCKMODE), Doctrine::LOCK_PESSIMISTIC);
|
||||
|
||||
// test invalid arguments
|
||||
try {
|
||||
$this->manager->setAttribute(Doctrine::ATTR_CACHE_TTL,-12);
|
||||
} catch(Exception $e) {
|
||||
$this->assertTrue($e instanceof Exception);
|
||||
}
|
||||
try {
|
||||
$this->manager->setAttribute(Doctrine::ATTR_CACHE_SIZE,-12);
|
||||
} catch(Exception $e) {
|
||||
$this->assertTrue($e instanceof Exception);
|
||||
}
|
||||
try {
|
||||
$this->manager->setAttribute(Doctrine::ATTR_BATCH_SIZE,-12);
|
||||
} catch(Exception $e) {
|
||||
$this->assertTrue($e instanceof Exception);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->session->beginTransaction();
|
||||
$this->manager->setAttribute(Doctrine::ATTR_LOCKMODE, Doctrine::LOCK_OPTIMISTIC);
|
||||
} catch(Exception $e) {
|
||||
$this->assertTrue($e instanceof Exception);
|
||||
$this->session->commit();
|
||||
}
|
||||
try {
|
||||
$this->session->beginTransaction();
|
||||
$this->session->setAttribute(Doctrine::ATTR_LOCKMODE, Doctrine::LOCK_PESSIMISTIC);
|
||||
} catch(Exception $e) {
|
||||
$this->assertTrue($e instanceof Exception);
|
||||
$this->session->commit();
|
||||
}
|
||||
try {
|
||||
$this->manager->setAttribute(Doctrine::ATTR_PK_TYPE,-12);
|
||||
} catch(Exception $e) {
|
||||
$this->assertTrue($e instanceof Exception);
|
||||
}
|
||||
}
|
||||
public function testGetAttributes() {
|
||||
$this->assertTrue(is_array($this->manager->getAttributes()));
|
||||
}
|
||||
}
|
||||
?>
|
194
tests/DQLParserTestCase.class.php
Normal file
194
tests/DQLParserTestCase.class.php
Normal file
@ -0,0 +1,194 @@
|
||||
<?php
|
||||
require_once("UnitTestCase.class.php");
|
||||
class Doctrine_DQL_ParserTestCase extends Doctrine_UnitTestCase {
|
||||
public function testPrepared() {
|
||||
$coll = $this->session->query("FROM User WHERE User.name = :name", array(":name" => "zYne"));
|
||||
$this->assertEqual($coll->count(), 1);
|
||||
}
|
||||
public function testQuery() {
|
||||
$graph = new Doctrine_DQL_Parser($this->session);
|
||||
|
||||
$this->graph = $graph;
|
||||
|
||||
$user = $this->objTable->find(5);
|
||||
|
||||
|
||||
$album = $this->session->create("Album");
|
||||
$album->Song[0];
|
||||
|
||||
$user->Album[0]->name = "Damage Done";
|
||||
$user->Album[1]->name = "Haven";
|
||||
|
||||
$user->Album[0]->Song[0]->title = "Damage Done";
|
||||
|
||||
|
||||
$user->Album[0]->Song[1]->title = "The Treason Wall";
|
||||
$user->Album[0]->Song[2]->title = "Monochromatic Stains";
|
||||
$this->assertEqual(count($user->Album[0]->Song), 3);
|
||||
|
||||
|
||||
$user->Album[1]->Song[0]->title = "Not Built To Last";
|
||||
$user->Album[1]->Song[1]->title = "The Wonders At Your Feet";
|
||||
$user->Album[1]->Song[2]->title = "Feast Of Burden";
|
||||
$user->Album[1]->Song[3]->title = "Fabric";
|
||||
$this->assertEqual(count($user->Album[1]->Song), 4);
|
||||
|
||||
$user->save();
|
||||
|
||||
$user = $this->objTable->find(5);
|
||||
|
||||
$this->assertEqual(count($user->Album[0]->Song), 3);
|
||||
$this->assertEqual(count($user->Album[1]->Song), 4);
|
||||
|
||||
$users = $graph->query("FROM User WHERE User.Album.name like '%Damage%'");
|
||||
|
||||
|
||||
|
||||
// DYNAMIC COLLECTION EXPANDING
|
||||
|
||||
$user = $this->objTable->find(5);
|
||||
$user->Group[1]->name = "Tough guys inc.";
|
||||
$user->Group[2]->name = "Terminators";
|
||||
$this->assertEqual($user->Group[0]->name, "Action Actors");
|
||||
$user->save();
|
||||
$this->assertEqual($user->Group[0]->name, "Action Actors");
|
||||
$this->assertEqual(count($user->Group), 3);
|
||||
|
||||
$user = $this->objTable->find(5);
|
||||
$this->assertEqual(count($user->Group), 3);
|
||||
|
||||
$users = $graph->query("FROM User, User.Group WHERE User.Group.name LIKE 'Action Actors'");
|
||||
$this->assertEqual(count($users),1);
|
||||
|
||||
//$this->assertEqual($users[0]->Group[0]->name, "Action Actors");
|
||||
//$this->assertEqual(count($users[0]->Group), 1);
|
||||
|
||||
//$this->assertEqual($users[0]->Group[1]->name, "Tough guys inc.");
|
||||
//$this->assertEqual($users[0]->Group[2]->name, "Terminators");
|
||||
//$this->assertEqual(count($users[0]->Group), 3);
|
||||
|
||||
|
||||
$this->clearCache();
|
||||
|
||||
$users = $graph->query("FROM User, User.Phonenumber-l WHERE User.Phonenumber.phonenumber LIKE '%123%'");
|
||||
$this->assertEqual(trim($graph->getQuery()),
|
||||
"SELECT entity.id AS User__id, phonenumber.id AS Phonenumber__id FROM entity LEFT JOIN phonenumber ON entity.id = phonenumber.entity_id WHERE (phonenumber.phonenumber LIKE '%123%') && (entity.type = 0)");
|
||||
|
||||
$count = $this->session->getDBH()->count();
|
||||
|
||||
$users[1]->Phonenumber[0]->phonenumber;
|
||||
$users[1]->Phonenumber[1]->phonenumber;
|
||||
$this->assertEqual($users[1]->Phonenumber[1]->getState(),Doctrine_Record::STATE_CLEAN);
|
||||
|
||||
$users[1]->Phonenumber[2]->phonenumber;
|
||||
$this->assertEqual($users[1]->Phonenumber[1]->getState(),Doctrine_Record::STATE_CLEAN);
|
||||
$count2 = $this->session->getDBH()->count();
|
||||
$this->assertEqual($count + 4,$count2);
|
||||
|
||||
|
||||
|
||||
// DYNAMIC FETCHMODES
|
||||
try {
|
||||
$users = $graph->query("FROM User-unknown");
|
||||
} catch(Exception $e) {
|
||||
}
|
||||
$this->assertTrue($e instanceof DQLException);
|
||||
|
||||
|
||||
$users = $graph->query("FROM User-i");
|
||||
$this->assertEqual(trim($graph->getQuery()),
|
||||
"SELECT entity.id AS User__id, entity.name AS User__name, entity.loginname AS User__loginname, entity.password AS User__password, entity.type AS User__type, entity.created AS User__created, entity.updated AS User__updated, entity.email_id AS User__email_id FROM entity WHERE (entity.type = 0)");
|
||||
|
||||
$count = $this->session->getDBH()->count();
|
||||
$this->assertEqual($users[0]->name, "zYne");
|
||||
|
||||
$this->assertTrue($users instanceof Doctrine_Collection_Immediate);
|
||||
$count2 = $this->session->getDBH()->count();
|
||||
$this->assertEqual($count,$count2);
|
||||
|
||||
|
||||
$users = $graph->query("FROM User-b");
|
||||
$this->assertEqual(trim($graph->getQuery()),
|
||||
"SELECT entity.id AS User__id FROM entity WHERE (entity.type = 0)");
|
||||
|
||||
$this->assertEqual($users[0]->name, "zYne");
|
||||
$this->assertTrue($users instanceof Doctrine_Collection_Batch);
|
||||
|
||||
|
||||
$users = $graph->query("FROM User-l");
|
||||
$this->assertEqual(trim($graph->getQuery()),
|
||||
"SELECT entity.id AS User__id FROM entity WHERE (entity.type = 0)");
|
||||
|
||||
$this->assertEqual($users[0]->name, "zYne");
|
||||
$this->assertTrue($users instanceof Doctrine_Collection_Lazy);
|
||||
|
||||
|
||||
//$this->clearCache();
|
||||
|
||||
$users = $graph->query("FROM User, User.Phonenumber");
|
||||
$this->assertEqual(trim($graph->getQuery()),
|
||||
"SELECT entity.id AS User__id, phonenumber.id AS Phonenumber__id FROM entity LEFT JOIN phonenumber ON entity.id = phonenumber.entity_id WHERE (entity.type = 0)");
|
||||
|
||||
$this->assertEqual($users->count(),8);
|
||||
|
||||
// EXPECTED THAT ONE NEW QUERY IS NEEDED TO GET THE FIRST USER's PHONENUMBER
|
||||
|
||||
$count = $this->session->getDBH()->count();
|
||||
$users[0]->Phonenumber[0]->phonenumber;
|
||||
$count2 = $this->session->getDBH()->count();
|
||||
$this->assertEqual($count + 1,$count2);
|
||||
|
||||
|
||||
|
||||
|
||||
$users = $graph->query("FROM User, User.Email");
|
||||
$this->assertEqual(trim($graph->getQuery()),
|
||||
"SELECT entity.id AS User__id, email.id AS Email__id FROM entity, email WHERE (entity.email_id = email.id) && (entity.type = 0)");
|
||||
|
||||
$this->assertEqual($users->count(),8);
|
||||
|
||||
$users = $graph->query("FROM Email WHERE Email.address LIKE '%@example%'");
|
||||
$this->assertEqual($graph->getQuery(),
|
||||
"SELECT email.id AS Email__id FROM email WHERE (email.address LIKE '%@example%')");
|
||||
$this->assertEqual($users->count(),8);
|
||||
|
||||
$users = $graph->query("FROM User WHERE User.name LIKE '%Jack%'");
|
||||
$this->assertTrue($graph->getQuery() == "SELECT entity.id AS User__id FROM entity WHERE (entity.name LIKE '%Jack%') && (entity.type = 0)");
|
||||
$this->assertEqual($users->count(),0);
|
||||
|
||||
|
||||
$users = $graph->query("FROM User ORDER BY User.name ASC, User.Email.address");
|
||||
$this->assertEqual(trim($graph->getQuery()),
|
||||
"SELECT entity.id AS User__id FROM entity, email WHERE (entity.email_id = email.id) && (entity.type = 0) ORDER BY entity.name ASC, email.address");
|
||||
$this->assertEqual($users->count(),8);
|
||||
$this->assertTrue($users[0]->name == "Arnold Schwarzenegger");
|
||||
|
||||
$users = $graph->query("FROM User WHERE User.Phonenumber.phonenumber REGEXP '[123]'");
|
||||
$this->assertEqual(trim($graph->getQuery()),
|
||||
"SELECT entity.id AS User__id FROM entity LEFT JOIN phonenumber ON entity.id = phonenumber.entity_id WHERE (phonenumber.phonenumber REGEXP '[123]') && (entity.type = 0)");
|
||||
$this->assertEqual($users->count(),8);
|
||||
|
||||
|
||||
$users = $graph->query("FROM User WHERE User.Group.name = 'Action Actors'");
|
||||
$this->assertEqual(trim($graph->getQuery()),
|
||||
"SELECT entity.id AS User__id FROM entity WHERE (entity.id IN (SELECT user_id FROM groupuser WHERE group_id IN (SELECT entity.id AS Group__id FROM entity WHERE (entity.name = 'Action Actors') && (entity.type = 1)))) && (entity.type = 0)");
|
||||
$this->assertTrue($users instanceof Doctrine_Collection);
|
||||
$this->assertEqual($users->count(),1);
|
||||
|
||||
|
||||
$users = $graph->query("FROM User WHERE User.Group.Phonenumber.phonenumber LIKE '123 123'");
|
||||
$this->assertEqual(trim($graph->getQuery()),
|
||||
"SELECT entity.id AS User__id FROM entity WHERE (entity.id IN (SELECT user_id FROM groupuser WHERE group_id IN (SELECT entity.id AS Group__id FROM entity, phonenumber WHERE (phonenumber.phonenumber LIKE '123 123') && (entity.type = 1)))) && (entity.type = 0)");
|
||||
$this->assertTrue($users instanceof Doctrine_Collection);
|
||||
$this->assertEqual($users->count(),1);
|
||||
|
||||
|
||||
|
||||
$values = $graph->query("SELECT COUNT(User.name) AS users, MAX(User.name) AS max FROM User");
|
||||
$this->assertEqual(trim($graph->getQuery()),"SELECT COUNT(entity.name) AS users, MAX(entity.name) AS max FROM entity WHERE (entity.type = 0)");
|
||||
$this->assertTrue(is_array($values));
|
||||
$this->assertTrue(isset($values['users']));
|
||||
$this->assertTrue(isset($values['max']));
|
||||
}
|
||||
}
|
||||
?>
|
13
tests/EventListenerTestCase.class.php
Normal file
13
tests/EventListenerTestCase.class.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
require_once("UnitTestCase.class.php");
|
||||
|
||||
class Doctrine_EventListenerTestCase extends Doctrine_UnitTestCase {
|
||||
public function testEvents() {
|
||||
$session = $this->manager->openSession(Doctrine_DB::getConnection());
|
||||
$debug = $this->listener->getMessages();
|
||||
$last = end($debug);
|
||||
$this->assertTrue($last->getObject() instanceof Doctrine_Session);
|
||||
$this->assertTrue($last->getCode() == Doctrine_Debugger::EVENT_OPEN);
|
||||
}
|
||||
}
|
||||
?>
|
7
tests/FormBuilderTestCase.class.php
Normal file
7
tests/FormBuilderTestCase.class.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
class Doctrine_FormBuilderTestCase extends Doctrine_UnitTestCase {
|
||||
public function testBuildForm() {
|
||||
|
||||
}
|
||||
}
|
||||
?>
|
23
tests/ManagerTestCase.class.php
Normal file
23
tests/ManagerTestCase.class.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
require_once("UnitTestCase.class.php");
|
||||
class Doctrine_ManagerTestCase extends Doctrine_UnitTestCase {
|
||||
public function testGetInstance() {
|
||||
$this->assertTrue(Doctrine_Manager::getInstance() instanceOf Doctrine_Manager);
|
||||
}
|
||||
public function testOpenSession() {
|
||||
$this->assertTrue($this->session instanceOf Doctrine_Session);
|
||||
}
|
||||
public function testGetIterator() {
|
||||
$this->assertTrue($this->manager->getIterator() instanceof ArrayIterator);
|
||||
}
|
||||
public function testCount() {
|
||||
$this->assertEqual(count($this->manager),1);
|
||||
}
|
||||
public function testGetCurrentSession() {
|
||||
$this->assertEqual($this->manager->getCurrentSession(), $this->session);
|
||||
}
|
||||
public function testGetSessions() {
|
||||
$this->assertEqual(count($this->manager->getSessions()),1);
|
||||
}
|
||||
}
|
||||
?>
|
440
tests/RecordTestCase.class.php
Normal file
440
tests/RecordTestCase.class.php
Normal file
@ -0,0 +1,440 @@
|
||||
<?php
|
||||
require_once("UnitTestCase.class.php");
|
||||
|
||||
class Doctrine_RecordTestCase extends Doctrine_UnitTestCase {
|
||||
public function testGet() {
|
||||
$user = new User();
|
||||
$user->name = "Jack Daniels";
|
||||
$this->assertEqual($user->name, "Jack Daniels");
|
||||
$this->assertEqual($user->created, null);
|
||||
$this->assertEqual($user->updated, null);
|
||||
$user->save();
|
||||
$id = $user->getID();
|
||||
$user = $user->getTable()->find($id);
|
||||
$this->assertEqual($user->name, "Jack Daniels");
|
||||
$this->assertEqual($user->created, null);
|
||||
$this->assertEqual($user->updated, null);
|
||||
|
||||
}
|
||||
public function testNewOperator() {
|
||||
$user = new User();
|
||||
$this->assertTrue($user->getState() == Doctrine_Record::STATE_TCLEAN);
|
||||
$user->name = "John Locke";
|
||||
|
||||
$this->assertTrue($user->name,"John Locke");
|
||||
$this->assertTrue($user->getState() == Doctrine_Record::STATE_TDIRTY);
|
||||
$user->save();
|
||||
$this->assertTrue($user->getState() == Doctrine_Record::STATE_CLEAN);
|
||||
$this->assertTrue($user->name,"John Locke");
|
||||
}
|
||||
public function testTreeStructure() {
|
||||
$e = new Element();
|
||||
$e->name = "parent";
|
||||
$e->Element[0]->name = "child 1";
|
||||
$e->Element[1]->name = "child 2";
|
||||
$e->Element[1]->Element[0]->name = "child 1's child 1";
|
||||
$e->Element[1]->Element[1]->name = "child 1's child 1";
|
||||
|
||||
$this->assertEqual($e->name,"parent");
|
||||
$this->assertEqual($e->Element[0]->name,"child 1");
|
||||
$this->assertEqual($e->Element[1]->name,"child 2");
|
||||
$this->assertEqual($e->Element[1]->Element[0]->name,"child 1's child 1");
|
||||
$this->assertEqual($e->Element[1]->Element[1]->name,"child 1's child 1");
|
||||
|
||||
$this->session->flush();
|
||||
|
||||
$e = $e->getTable()->find($e->getID());
|
||||
$this->assertEqual($e->name,"parent");
|
||||
$this->assertEqual($e->Element[0]->name,"child 1");
|
||||
$this->assertEqual($e->Element[1]->name,"child 2");
|
||||
$this->assertEqual($e->Element[1]->Element[0]->name,"child 1's child 1");
|
||||
$this->assertEqual($e->Element[1]->Element[1]->name,"child 1's child 1");
|
||||
}
|
||||
public function testUniqueKeyComponent() {
|
||||
$e = new Error();
|
||||
$e->message = "user error";
|
||||
$e->file_md5 = md5(0);
|
||||
$e->code = 1;
|
||||
|
||||
/**
|
||||
* ADDING NEW RECORD
|
||||
*/
|
||||
|
||||
$this->assertEqual($e->code,1);
|
||||
$this->assertEqual($e->file_md5, md5(0));
|
||||
$this->assertEqual($e->message, "user error");
|
||||
|
||||
$e2 = new Error();
|
||||
$e2->message = "user error2";
|
||||
$e2->file_md5 = md5(1);
|
||||
$e2->code = 2;
|
||||
|
||||
$this->assertEqual($e2->code,2);
|
||||
$this->assertEqual($e2->file_md5, md5(1));
|
||||
$this->assertEqual($e2->message, "user error2");
|
||||
|
||||
|
||||
$fk = $e->getTable()->getForeignKey("Description");
|
||||
$this->assertTrue($fk instanceof Doctrine_ForeignKey);
|
||||
$this->assertEqual($fk->getLocal(),"file_md5");
|
||||
$this->assertEqual($fk->getForeign(),"file_md5");
|
||||
$this->assertTrue($fk->getTable() instanceof Doctrine_Table);
|
||||
|
||||
$e->Description[0]->description = "This is the 1st description";
|
||||
$e->Description[1]->description = "This is the 2nd description";
|
||||
$this->assertEqual($e->Description[0]->description, "This is the 1st description");
|
||||
$this->assertEqual($e->Description[1]->description, "This is the 2nd description");
|
||||
$this->assertEqual($e->Description[0]->file_md5, $e->file_md5);
|
||||
$this->assertEqual($e->Description[1]->file_md5, $e->file_md5);
|
||||
|
||||
$this->assertEqual($e2->Description[0]->description, null);
|
||||
$this->assertEqual($e2->Description[1]->description, null);
|
||||
$this->assertEqual($e2->Description[0]->file_md5, $e2->file_md5);
|
||||
$this->assertEqual($e2->Description[1]->file_md5, $e2->file_md5);
|
||||
|
||||
$e->save();
|
||||
|
||||
$coll = $this->session->query("FROM Error-I");
|
||||
$e = $coll[0];
|
||||
|
||||
|
||||
$this->assertEqual($e->code,1);
|
||||
$this->assertEqual($e->file_md5, md5(0));
|
||||
$this->assertEqual($e->message, "user error");
|
||||
|
||||
$this->assertTrue($e->Description instanceof Doctrine_Collection);
|
||||
$this->assertTrue($e->Description[0] instanceof Description);
|
||||
$this->assertTrue($e->Description[1] instanceof Description);
|
||||
|
||||
$this->assertEqual($e->Description[0]->description, "This is the 1st description");
|
||||
$this->assertEqual($e->Description[1]->description, "This is the 2nd description");
|
||||
|
||||
/**
|
||||
* UPDATING
|
||||
*/
|
||||
|
||||
$e->code = 2;
|
||||
$e->message = "changed message";
|
||||
$e->Description[0]->description = "1st changed description";
|
||||
$e->Description[1]->description = "2nd changed description";
|
||||
|
||||
|
||||
$this->assertEqual($e->code,2);
|
||||
$this->assertEqual($e->message,"changed message");
|
||||
$this->assertEqual($e->Description[0]->description, "1st changed description");
|
||||
$this->assertEqual($e->Description[1]->description, "2nd changed description");
|
||||
|
||||
$e->save();
|
||||
$this->assertEqual($e->code,2);
|
||||
$this->assertEqual($e->message,"changed message");
|
||||
$this->assertEqual($e->Description[0]->description, "1st changed description");
|
||||
$this->assertEqual($e->Description[1]->description, "2nd changed description");
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function testInsert() {
|
||||
$this->new->name = "John Locke";
|
||||
$this->new->save();
|
||||
|
||||
$this->assertTrue($this->new->getModified() == array());
|
||||
$this->assertTrue($this->new->getState() == Doctrine_Record::STATE_CLEAN);
|
||||
|
||||
$debug = $this->listener->getMessages();
|
||||
$p = array_pop($debug);
|
||||
$this->assertTrue($p->getObject() instanceof Doctrine_Session);
|
||||
$this->assertTrue($p->getCode() == Doctrine_Debugger::EVENT_COMMIT);
|
||||
|
||||
$p = array_pop($debug);
|
||||
|
||||
$this->assertTrue($p->getObject() instanceof Doctrine_Record);
|
||||
$this->assertTrue($p->getCode() == Doctrine_Debugger::EVENT_SLEEP);
|
||||
|
||||
$p = array_pop($debug);
|
||||
$this->assertTrue($p->getObject() instanceof Doctrine_Record);
|
||||
$this->assertTrue($p->getCode() == Doctrine_Debugger::EVENT_SAVE);
|
||||
|
||||
$p = array_pop($debug);
|
||||
$this->assertTrue($p->getObject() instanceof Doctrine_Record);
|
||||
$this->assertTrue($p->getCode() == Doctrine_Debugger::EVENT_INSERT);
|
||||
|
||||
|
||||
$p = array_pop($debug);
|
||||
$this->assertTrue($p->getObject() instanceof Doctrine_Record);
|
||||
$this->assertTrue($p->getCode() == Doctrine_Debugger::EVENT_PREINSERT);
|
||||
|
||||
$this->new->delete();
|
||||
$this->assertTrue($this->new->getState() == Doctrine_Record::STATE_TCLEAN);
|
||||
}
|
||||
|
||||
public function testUpdate() {
|
||||
$this->old->set("name","Jack Daniels",true);
|
||||
|
||||
|
||||
$this->old->save(true);
|
||||
//print $this->old->name;
|
||||
|
||||
$this->assertEqual($this->old->getModified(), array());
|
||||
$this->assertEqual($this->old->name, "Jack Daniels");
|
||||
|
||||
$debug = $this->listener->getMessages();
|
||||
$p = array_pop($debug);
|
||||
$this->assertTrue($p->getObject() instanceof Doctrine_Session);
|
||||
$this->assertTrue($p->getCode() == Doctrine_Debugger::EVENT_COMMIT);
|
||||
|
||||
$p = array_pop($debug);
|
||||
$this->assertTrue($p->getObject() instanceof Doctrine_Record);
|
||||
$this->assertTrue($p->getCode() == Doctrine_Debugger::EVENT_SAVE);
|
||||
|
||||
$p = array_pop($debug);
|
||||
$this->assertTrue($p->getObject() instanceof Doctrine_Record);
|
||||
$this->assertTrue($p->getCode() == Doctrine_Debugger::EVENT_UPDATE);
|
||||
|
||||
|
||||
}
|
||||
public function testCopy() {
|
||||
$new = $this->old->copy();
|
||||
$this->assertTrue($new instanceof Doctrine_Record);
|
||||
$this->assertTrue($new->getState() == Doctrine_Record::STATE_TDIRTY);
|
||||
}
|
||||
|
||||
public function testReferences() {
|
||||
|
||||
$user = $this->objTable->find(5);
|
||||
|
||||
$pf = $this->session->getTable("Phonenumber");
|
||||
|
||||
$this->assertTrue($user->Phonenumber instanceof Doctrine_Collection);
|
||||
$this->assertTrue($user->Phonenumber->count() == 3);
|
||||
|
||||
$coll = new Doctrine_Collection($pf);
|
||||
|
||||
$user->Phonenumber = $coll;
|
||||
$this->assertTrue($user->Phonenumber->count() == 0);
|
||||
$user->save();
|
||||
unset($user);
|
||||
$user = $this->objTable->find(5);
|
||||
|
||||
$this->assertEqual($user->Phonenumber->count(), 0);
|
||||
|
||||
// ADDING REFERENCES
|
||||
|
||||
$user->Phonenumber[0]->phonenumber = "123 123";
|
||||
$this->assertEqual(gettype($user->Phonenumber[0]->entity_id),"integer");
|
||||
|
||||
$user->Phonenumber[1]->phonenumber = "123 123";
|
||||
$user->save();
|
||||
|
||||
|
||||
$this->assertTrue($user->Phonenumber->count() == 2);
|
||||
|
||||
unset($user);
|
||||
$user = $this->objTable->find(5);
|
||||
$this->assertEqual($user->Phonenumber->count(), 2);
|
||||
|
||||
$user->Phonenumber[3]->phonenumber = "123 123";
|
||||
$user->save();
|
||||
|
||||
$this->assertTrue($user->Phonenumber->count() == 3);
|
||||
unset($user);
|
||||
$user = $this->objTable->find(5);
|
||||
$this->assertTrue($user->Phonenumber->count() == 3);
|
||||
|
||||
// DELETING REFERENCES
|
||||
|
||||
$user->Phonenumber->delete();
|
||||
|
||||
$this->assertTrue($user->Phonenumber->count() == 0);
|
||||
unset($user);
|
||||
$user = $this->objTable->find(5);
|
||||
$this->assertTrue($user->Phonenumber->count() == 0);
|
||||
|
||||
// ADDING REFERENCES WITH STRING KEYS
|
||||
|
||||
$user->Phonenumber["home"]->phonenumber = "123 123";
|
||||
$user->Phonenumber["work"]->phonenumber = "444 444";
|
||||
$user->save();
|
||||
|
||||
$this->assertTrue($user->Phonenumber->count() == 2);
|
||||
unset($user);
|
||||
$user = $this->objTable->find(5);
|
||||
$this->assertTrue($user->Phonenumber->count() == 2);
|
||||
|
||||
// REPLACING ONE-TO-MANY REFERENCE
|
||||
unset($coll);
|
||||
$coll = new Doctrine_Collection($pf);
|
||||
$coll[0]->phonenumber = "123 123";
|
||||
$coll["home"]->phonenumber = "444 444";
|
||||
$coll["work"]->phonenumber = "444 444";
|
||||
|
||||
$user->Phonenumber = $coll;
|
||||
$user->save();
|
||||
$this->assertEqual($user->Phonenumber->count(), 3);
|
||||
$user = $this->objTable->find(5);
|
||||
$this->assertEqual($user->Phonenumber->count(), 3);
|
||||
|
||||
|
||||
// ONE-TO-ONE REFERENCES
|
||||
|
||||
$user->Email->address = "drinker@drinkmore.info";
|
||||
$this->assertTrue($user->Email instanceof Email);
|
||||
$user->save();
|
||||
$this->assertTrue($user->Email instanceof Email);
|
||||
$user = $this->objTable->find(5);
|
||||
$this->assertEqual($user->Email->address, "drinker@drinkmore.info");
|
||||
$id = $user->Email->getID();
|
||||
|
||||
// REPLACING ONE-TO-ONE REFERENCES
|
||||
|
||||
$email = $this->session->create("Email");
|
||||
$email->address = "absolutist@nottodrink.com";
|
||||
$user->Email = $email;
|
||||
|
||||
$this->assertTrue($user->Email instanceof Email);
|
||||
$this->assertEqual($user->Email->address, "absolutist@nottodrink.com");
|
||||
$user->save();
|
||||
unset($user);
|
||||
|
||||
$user = $this->objTable->find(5);
|
||||
$this->assertTrue($user->Email instanceof Email);
|
||||
$this->assertEqual($user->Email->address, "absolutist@nottodrink.com");
|
||||
|
||||
$emails = $this->session->query("FROM Email WHERE Email.id = $id");
|
||||
$this->assertEqual(count($emails),0);
|
||||
}
|
||||
|
||||
public function testDeleteReference() {
|
||||
$user = $this->objTable->find(5);
|
||||
$int = $user->Phonenumber->delete();
|
||||
|
||||
$this->assertTrue($user->Phonenumber->count() == 0);
|
||||
}
|
||||
|
||||
public function testSaveAssociations() {
|
||||
$user = $this->objTable->find(5);
|
||||
|
||||
$gf = $this->session->getTable("Group");
|
||||
|
||||
$this->assertTrue($user->Group instanceof Doctrine_Collection);
|
||||
|
||||
|
||||
// ADDING ASSOCIATED REFERENCES
|
||||
|
||||
|
||||
$record = $gf->find(1);
|
||||
$record2 = $gf->find(2);
|
||||
$user->Group[0] = $record;
|
||||
$user->Group[1] = $record2;
|
||||
|
||||
$this->assertTrue($user->Group->count() == 2);
|
||||
|
||||
$user->save();
|
||||
|
||||
|
||||
// UNSETTING ASSOCIATED REFERENCES
|
||||
|
||||
|
||||
unset($user);
|
||||
$user = $this->objTable->find(5);
|
||||
$this->assertTrue($user->Group->count() == 2);
|
||||
|
||||
unset($user->Group[0]);
|
||||
$this->assertTrue($user->Group->count() == 1);
|
||||
|
||||
unset($user->Group[1]);
|
||||
$this->assertTrue($user->Group->count() == 0);
|
||||
|
||||
$user->save();
|
||||
$this->assertTrue($user->Group->count() == 0);
|
||||
unset($user);
|
||||
|
||||
|
||||
// CHECKING THE PERSISTENCE OF UNSET ASSOCIATED REFERENCES
|
||||
|
||||
|
||||
$user = $this->objTable->find(5);
|
||||
$this->assertTrue($user->Group->count() == 0);
|
||||
|
||||
|
||||
// REPLACING OLD ASSOCIATED REFERENCE
|
||||
|
||||
|
||||
$user->Group[0] = $record;
|
||||
$user->save();
|
||||
|
||||
$user->Group[0] = $record2;
|
||||
$user->save();
|
||||
|
||||
$this->assertEqual($user->Group->count(), 1);
|
||||
$this->assertEqual($user->Group[0]->getID(), $record2->getID());
|
||||
$this->assertFalse($user->Group[0]->getID() == $record->getID());
|
||||
|
||||
|
||||
$user->Group[0] = $record;
|
||||
$user->Group[1] = $gf->find(3);
|
||||
|
||||
$user->save();
|
||||
$this->assertEqual($user->Group->count(), 2);
|
||||
$user = $this->objTable->find(5);
|
||||
$this->assertEqual($user->Group->count(), 2);
|
||||
|
||||
|
||||
|
||||
$user->Group = new Doctrine_Collection($gf);
|
||||
$user->save();
|
||||
$this->assertEqual($user->Group->count(), 0);
|
||||
$user = $this->objTable->find(5);
|
||||
$this->assertEqual($user->Group->count(), 0);
|
||||
|
||||
|
||||
// ACCESSING ASSOCIATION OBJECT PROPERTIES
|
||||
|
||||
$user = new User();
|
||||
$this->assertTrue($user->getTable()->getForeignKey("Groupuser") instanceof Doctrine_ForeignKey);
|
||||
$this->assertTrue($user->Groupuser instanceof Doctrine_Collection);
|
||||
$this->assertTrue($user->Groupuser[0] instanceof Groupuser);
|
||||
|
||||
$user->name = "Jack Daniels";
|
||||
$user->Group[0]->name = "Group #1";
|
||||
$user->Group[1]->name = "Group #2";
|
||||
$t1 = time();
|
||||
$t2 = time();
|
||||
$user->Groupuser[0]->added = $t1;
|
||||
$user->Groupuser[1]->added = $t2;
|
||||
|
||||
$this->assertEqual($user->Groupuser[0]->added, $t1);
|
||||
$this->assertEqual($user->Groupuser[1]->added, $t2);
|
||||
|
||||
$user->save();
|
||||
|
||||
$user->refresh();
|
||||
$this->assertEqual($user->Groupuser[0]->added, $t1);
|
||||
$this->assertEqual($user->Groupuser[1]->added, $t2);
|
||||
}
|
||||
|
||||
public function testCount() {
|
||||
$this->assertTrue(is_integer($this->old->count()));
|
||||
}
|
||||
|
||||
public function testGetReference() {
|
||||
$this->assertTrue($this->old->Email instanceof Doctrine_Record);
|
||||
$this->assertTrue($this->old->Phonenumber instanceof Doctrine_Collection);
|
||||
$this->assertTrue($this->old->Group instanceof Doctrine_Collection);
|
||||
|
||||
$this->assertTrue($this->old->Phonenumber->count() == 1);
|
||||
}
|
||||
|
||||
public function testSerialize() {
|
||||
$old = $this->old;
|
||||
$old = serialize($old);
|
||||
|
||||
$this->assertEqual(unserialize($old)->getID(),$this->old->getID());
|
||||
}
|
||||
|
||||
public function testGetIterator() {
|
||||
$this->assertTrue($this->old->getIterator() instanceof ArrayIterator);
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
7
tests/RepositoryTestCase.class.php
Normal file
7
tests/RepositoryTestCase.class.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
class Doctrine_RepositoryTestCase extends Doctrine_UnitTestCase {
|
||||
public function testAdd() {
|
||||
|
||||
}
|
||||
}
|
||||
?>
|
263
tests/SessionTestCase.class.php
Normal file
263
tests/SessionTestCase.class.php
Normal file
@ -0,0 +1,263 @@
|
||||
<?php
|
||||
require_once("UnitTestCase.class.php");
|
||||
class Doctrine_SessionTestCase extends Doctrine_UnitTestCase {
|
||||
public function testGetFactory() {
|
||||
$objTable = $this->session->getTable("User");
|
||||
$this->assertTrue($objTable instanceOf Doctrine_Table);
|
||||
}
|
||||
public function testFlush() {
|
||||
|
||||
$this->assertEqual(gettype($this->old->Phonenumber[0]->entity_id), "integer");
|
||||
|
||||
$user = $this->session->create("Email");
|
||||
$user = $this->session->create("User");
|
||||
$record = $this->session->create("Phonenumber");
|
||||
|
||||
$user->Email->address = "example@drinkmore.info";
|
||||
$this->assertTrue($user->email_id instanceof Email);
|
||||
|
||||
$user->name = "Example user";
|
||||
$user->Group[0]->name = "Example group 1";
|
||||
$user->Group[1]->name = "Example group 2";
|
||||
|
||||
$user->Phonenumber[0]->phonenumber = "123 123";
|
||||
|
||||
$user->Phonenumber[1]->phonenumber = "321 2132";
|
||||
$user->Phonenumber[2]->phonenumber = "123 123";
|
||||
$user->Phonenumber[3]->phonenumber = "321 2132";
|
||||
|
||||
|
||||
|
||||
$this->assertTrue($user->Phonenumber[0]->entity_id instanceof User);
|
||||
$this->assertTrue($user->Phonenumber[2]->entity_id instanceof User);
|
||||
|
||||
$this->session->flush();
|
||||
|
||||
$this->assertTrue(gettype($user->getID()) == "integer");
|
||||
|
||||
$this->assertTrue(gettype($user->email_id) == "integer");
|
||||
$this->assertTrue(gettype($user->Phonenumber[0]->entity_id) == "integer");
|
||||
|
||||
$this->assertEqual(count($user->Group), 2);
|
||||
|
||||
$user = $this->objTable->find(12);
|
||||
|
||||
$this->assertEqual($user->getID(), 12);
|
||||
|
||||
$this->assertTrue(gettype($user->getID()) == "integer");
|
||||
$this->assertTrue(gettype($user->email_id) == "integer");
|
||||
|
||||
$this->assertEqual(gettype($user->Phonenumber[0]->entity_id), "integer");
|
||||
$this->assertTrue($user->Phonenumber->count(), 4);
|
||||
$this->assertEqual($user->Group->count(), 2);
|
||||
|
||||
$user = $this->objTable->find(5);
|
||||
|
||||
$pf = $this->session->getTable("Phonenumber");
|
||||
|
||||
$this->assertTrue($user->Phonenumber instanceof Doctrine_Collection);
|
||||
$this->assertTrue($user->Phonenumber->count() == 3);
|
||||
|
||||
$coll = new Doctrine_Collection($pf);
|
||||
|
||||
$user->Phonenumber = $coll;
|
||||
$this->assertTrue($user->Phonenumber->count() == 0);
|
||||
|
||||
$this->session->flush();
|
||||
unset($user);
|
||||
$user = $this->objTable->find(5);
|
||||
|
||||
$this->assertEqual($user->Phonenumber->count(), 0);
|
||||
|
||||
// ADDING REFERENCES
|
||||
|
||||
$user->Phonenumber[0]->phonenumber = "123 123";
|
||||
$this->assertEqual(gettype($user->Phonenumber[0]->entity_id),"integer");
|
||||
|
||||
$user->Phonenumber[1]->phonenumber = "123 123";
|
||||
$this->session->flush();
|
||||
|
||||
|
||||
$this->assertTrue($user->Phonenumber->count() == 2);
|
||||
|
||||
unset($user);
|
||||
$user = $this->objTable->find(5);
|
||||
$this->assertEqual($user->Phonenumber->count(), 2);
|
||||
|
||||
$user->Phonenumber[3]->phonenumber = "123 123";
|
||||
$this->session->flush();
|
||||
|
||||
$this->assertTrue($user->Phonenumber->count() == 3);
|
||||
unset($user);
|
||||
$user = $this->objTable->find(5);
|
||||
$this->assertTrue($user->Phonenumber->count() == 3);
|
||||
|
||||
// DELETING REFERENCES
|
||||
|
||||
$user->Phonenumber->delete();
|
||||
|
||||
$this->assertTrue($user->Phonenumber->count() == 0);
|
||||
unset($user);
|
||||
$user = $this->objTable->find(5);
|
||||
$this->assertTrue($user->Phonenumber->count() == 0);
|
||||
|
||||
// ADDING REFERENCES WITH STRING KEYS
|
||||
|
||||
$user->Phonenumber["home"]->phonenumber = "123 123";
|
||||
$user->Phonenumber["work"]->phonenumber = "444 444";
|
||||
|
||||
$this->assertEqual($user->Phonenumber->count(), 2);
|
||||
$this->session->flush();
|
||||
|
||||
$this->assertTrue($user->Phonenumber->count() == 2);
|
||||
unset($user);
|
||||
$user = $this->objTable->find(5);
|
||||
$this->assertTrue($user->Phonenumber->count() == 2);
|
||||
|
||||
// REPLACING ONE-TO-MANY REFERENCE
|
||||
|
||||
unset($coll);
|
||||
$coll = new Doctrine_Collection($pf);
|
||||
$coll[0]->phonenumber = "123 123";
|
||||
$coll["home"]->phonenumber = "444 444";
|
||||
$coll["work"]->phonenumber = "444 444";
|
||||
|
||||
|
||||
|
||||
|
||||
$user->Phonenumber = $coll;
|
||||
$this->session->flush();
|
||||
$this->assertEqual($user->Phonenumber->count(), 3);
|
||||
$user = $this->objTable->find(5);
|
||||
$this->assertEqual($user->Phonenumber->count(), 3);
|
||||
|
||||
|
||||
// ONE-TO-ONE REFERENCES
|
||||
|
||||
$user->Email->address = "drinker@drinkmore.info";
|
||||
$this->assertTrue($user->Email instanceof Email);
|
||||
$this->session->flush();
|
||||
$this->assertTrue($user->Email instanceof Email);
|
||||
$user = $this->objTable->find(5);
|
||||
$this->assertEqual($user->Email->address, "drinker@drinkmore.info");
|
||||
$id = $user->Email->getID();
|
||||
|
||||
// REPLACING ONE-TO-ONE REFERENCES
|
||||
|
||||
$email = $this->session->create("Email");
|
||||
$email->address = "absolutist@nottodrink.com";
|
||||
$user->Email = $email;
|
||||
|
||||
$this->assertTrue($user->Email instanceof Email);
|
||||
$this->assertEqual($user->Email->address, "absolutist@nottodrink.com");
|
||||
$this->session->flush();
|
||||
unset($user);
|
||||
|
||||
$user = $this->objTable->find(5);
|
||||
$this->assertTrue($user->Email instanceof Email);
|
||||
$this->assertEqual($user->Email->address, "absolutist@nottodrink.com");
|
||||
|
||||
$emails = $this->session->query("FROM Email WHERE Email.id = $id");
|
||||
$this->assertEqual(count($emails),0);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function testGetManager() {
|
||||
$this->assertEqual($this->session->getManager(),$this->manager);
|
||||
}
|
||||
public function testQuery() {
|
||||
$this->assertTrue($this->session->query("FROM User") instanceof Doctrine_Collection);
|
||||
}
|
||||
|
||||
public function testDelete() {
|
||||
$user = $this->session->create("User");
|
||||
$this->session->delete($user);
|
||||
$this->assertEqual($user->getState(),Doctrine_Record::STATE_TCLEAN);
|
||||
}
|
||||
public function testGetTable() {
|
||||
$table = $this->session->getTable("Group");
|
||||
$this->assertTrue($table instanceof Doctrine_Table);
|
||||
try {
|
||||
$table = $this->session->getTable("Unknown");
|
||||
$f = false;
|
||||
} catch(Doctrine_Exception $e) {
|
||||
$f = true;
|
||||
}
|
||||
$this->assertTrue($f);
|
||||
|
||||
$table = $this->session->getTable("User");
|
||||
$this->assertTrue($table instanceof UserTable);
|
||||
|
||||
}
|
||||
public function testCreate() {
|
||||
$email = $this->session->create("Email");
|
||||
$this->assertTrue($email instanceof Email);
|
||||
}
|
||||
public function testGetDBH() {
|
||||
$this->assertTrue($this->session->getDBH() instanceof PDO);
|
||||
}
|
||||
public function testCount() {
|
||||
$this->assertTrue(is_integer(count($this->session)));
|
||||
}
|
||||
public function testGetIterator() {
|
||||
$this->assertTrue($this->session->getIterator() instanceof ArrayIterator);
|
||||
}
|
||||
public function testGetState() {
|
||||
$this->assertEqual($this->session->getState(),Doctrine_Session::STATE_OPEN);
|
||||
$this->assertEqual(Doctrine_Lib::getSessionStateAsString($this->session->getState()), "open");
|
||||
}
|
||||
public function testGetTables() {
|
||||
$this->assertTrue(is_array($this->session->getTables()));
|
||||
}
|
||||
|
||||
public function testTransactions() {
|
||||
|
||||
$this->session->beginTransaction();
|
||||
$this->assertEqual($this->session->getState(),Doctrine_Session::STATE_ACTIVE);
|
||||
$this->session->commit();
|
||||
$this->assertEqual($this->session->getState(),Doctrine_Session::STATE_OPEN);
|
||||
|
||||
$this->session->beginTransaction();
|
||||
|
||||
$user = $this->objTable->find(6);
|
||||
|
||||
$user->name = "Jack Daniels";
|
||||
$this->session->flush();
|
||||
$this->session->commit();
|
||||
|
||||
$user = $this->objTable->find(6);
|
||||
$this->assertEqual($user->name, "Jack Daniels");
|
||||
|
||||
}
|
||||
|
||||
public function testRollback() {
|
||||
$this->session->beginTransaction();
|
||||
$this->assertEqual($this->session->getTransactionLevel(),1);
|
||||
$this->assertEqual($this->session->getState(),Doctrine_Session::STATE_ACTIVE);
|
||||
$this->session->rollback();
|
||||
$this->assertEqual($this->session->getState(),Doctrine_Session::STATE_OPEN);
|
||||
$this->assertEqual($this->session->getTransactionLevel(),0);
|
||||
}
|
||||
public function testNestedTransactions() {
|
||||
$this->assertEqual($this->session->getTransactionLevel(),0);
|
||||
$this->session->beginTransaction();
|
||||
$this->assertEqual($this->session->getTransactionLevel(),1);
|
||||
$this->assertEqual($this->session->getState(),Doctrine_Session::STATE_ACTIVE);
|
||||
$this->session->beginTransaction();
|
||||
$this->assertEqual($this->session->getState(),Doctrine_Session::STATE_BUSY);
|
||||
$this->assertEqual($this->session->getTransactionLevel(),2);
|
||||
$this->session->commit();
|
||||
$this->assertEqual($this->session->getState(),Doctrine_Session::STATE_ACTIVE);
|
||||
$this->assertEqual($this->session->getTransactionLevel(),1);
|
||||
$this->session->commit();
|
||||
$this->assertEqual($this->session->getState(),Doctrine_Session::STATE_OPEN);
|
||||
$this->assertEqual($this->session->getTransactionLevel(),0);
|
||||
}
|
||||
public function testClear() {
|
||||
$this->session->clear();
|
||||
$this->assertEqual($this->session->getTables(), array());
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
94
tests/TableTestCase.class.php
Normal file
94
tests/TableTestCase.class.php
Normal file
@ -0,0 +1,94 @@
|
||||
<?php
|
||||
require_once("UnitTestCase.class.php");
|
||||
class Doctrine_TableTestCase extends Doctrine_UnitTestCase {
|
||||
public function testGetForeignKey() {
|
||||
$fk = $this->objTable->getForeignKey("Group");
|
||||
$this->assertTrue($fk instanceof Doctrine_Association);
|
||||
$this->assertTrue($fk->getTable() instanceof Doctrine_Table);
|
||||
$this->assertTrue($fk->getType() == Doctrine_Table::MANY_AGGREGATE);
|
||||
$this->assertTrue($fk->getLocal() == "user_id");
|
||||
$this->assertTrue($fk->getForeign() == "group_id");
|
||||
|
||||
$fk = $this->objTable->getForeignKey("Email");
|
||||
$this->assertTrue($fk instanceof Doctrine_LocalKey);
|
||||
$this->assertTrue($fk->getTable() instanceof Doctrine_Table);
|
||||
$this->assertTrue($fk->getType() == Doctrine_Table::ONE_COMPOSITE);
|
||||
$this->assertTrue($fk->getLocal() == "email_id");
|
||||
$this->assertTrue($fk->getForeign() == "id");
|
||||
|
||||
|
||||
$fk = $this->objTable->getForeignKey("Phonenumber");
|
||||
$this->assertTrue($fk instanceof Doctrine_ForeignKey);
|
||||
$this->assertTrue($fk->getTable() instanceof Doctrine_Table);
|
||||
$this->assertTrue($fk->getType() == Doctrine_Table::MANY_COMPOSITE);
|
||||
$this->assertTrue($fk->getLocal() == "id");
|
||||
$this->assertTrue($fk->getForeign() == "entity_id");
|
||||
}
|
||||
public function testGetComponentName() {
|
||||
$this->assertTrue($this->objTable->getComponentName() == "User");
|
||||
}
|
||||
public function testGetTableName() {
|
||||
$this->assertTrue($this->objTable->getTableName() == "entity");
|
||||
}
|
||||
public function testGetSession() {
|
||||
$this->assertTrue($this->objTable->getSession() instanceof Doctrine_Session);
|
||||
}
|
||||
public function testGetCache() {
|
||||
$this->assertTrue($this->objTable->getCache() instanceof Doctrine_Cache_File);
|
||||
}
|
||||
public function testGetData() {
|
||||
$this->assertTrue($this->objTable->getData() == array());
|
||||
}
|
||||
public function testSetSequenceName() {
|
||||
$this->objTable->setSequenceName("test-seq");
|
||||
$this->assertEqual($this->objTable->getSequenceName(),"test-seq");
|
||||
$this->objTable->setSequenceName(null);
|
||||
}
|
||||
public function testCreate() {
|
||||
$record = $this->objTable->create();
|
||||
$this->assertTrue($record instanceof Doctrine_Record);
|
||||
$this->assertTrue($record->getState() == Doctrine_Record::STATE_TCLEAN);
|
||||
}
|
||||
public function testFind() {
|
||||
$record = $this->objTable->find(4);
|
||||
$this->assertTrue($record instanceof Doctrine_Record);
|
||||
|
||||
try {
|
||||
$record = $this->objTable->find(123);
|
||||
} catch(Exception $e) {
|
||||
$this->assertTrue($e instanceOf Doctrine_Find_Exception);
|
||||
}
|
||||
}
|
||||
public function testFindAll() {
|
||||
$users = $this->objTable->findAll();
|
||||
$this->assertEqual($users->count(), 8);
|
||||
$this->assertTrue($users instanceof Doctrine_Collection_Batch);
|
||||
}
|
||||
public function testFindBySql() {
|
||||
$users = $this->objTable->findBySql("name LIKE '%Arnold%'");
|
||||
$this->assertEqual($users->count(), 1);
|
||||
$this->assertTrue($users instanceof Doctrine_Collection_Batch);
|
||||
}
|
||||
public function testGetProxy() {
|
||||
$user = $this->objTable->getProxy(4);
|
||||
$this->assertTrue($user instanceof Doctrine_Record);
|
||||
|
||||
try {
|
||||
$record = $this->objTable->find(123);
|
||||
} catch(Exception $e) {
|
||||
$this->assertTrue($e instanceOf Doctrine_Find_Exception);
|
||||
}
|
||||
}
|
||||
public function testGetColumns() {
|
||||
$columns = $this->objTable->getColumns();
|
||||
$this->assertTrue(is_array($columns));
|
||||
|
||||
}
|
||||
public function testIsNewEntry() {
|
||||
$this->assertFalse($this->objTable->isNewEntry());
|
||||
}
|
||||
public function testApplyInheritance() {
|
||||
$this->assertEqual($this->objTable->applyInheritance("id = 3"), "id = 3 && type = ?");
|
||||
}
|
||||
}
|
||||
?>
|
146
tests/UnitTestCase.class.php
Normal file
146
tests/UnitTestCase.class.php
Normal file
@ -0,0 +1,146 @@
|
||||
<?php
|
||||
require_once("../classes/Doctrine.class.php");
|
||||
|
||||
/**
|
||||
function __autoload($class) {
|
||||
Doctrine::autoload($class);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
Doctrine::loadAll();
|
||||
|
||||
require_once("classes.php");
|
||||
|
||||
ini_set('include_path',ucwords($_SERVER["DOCUMENT_ROOT"]));
|
||||
require_once("simpletest/unit_tester.php");
|
||||
require_once("simpletest/reporter.php");
|
||||
|
||||
|
||||
class Doctrine_UnitTestCase extends UnitTestCase {
|
||||
protected $manager;
|
||||
protected $session;
|
||||
protected $objTable;
|
||||
protected $repository;
|
||||
protected $new;
|
||||
protected $old;
|
||||
protected $dbh;
|
||||
protected $listener;
|
||||
protected $cache;
|
||||
protected $users;
|
||||
protected $tables;
|
||||
|
||||
private static $instances;
|
||||
private $init = false;
|
||||
|
||||
public function init() {
|
||||
$name = get_class($this);
|
||||
if( ! isset($instances[$name]))
|
||||
$instances[$name] = $this;
|
||||
|
||||
$this->manager = Doctrine_Manager::getInstance();
|
||||
|
||||
|
||||
if($this->manager->count() > 0) {
|
||||
$this->session = $this->manager->getSession(0);
|
||||
$this->session->clear();
|
||||
$this->dbh = $this->session->getDBH();
|
||||
$this->listener = $this->manager->getAttribute(Doctrine::ATTR_LISTENER);
|
||||
} else {
|
||||
$this->dbh = Doctrine_DB::getConnection();
|
||||
$this->session = $this->manager->openSession($this->dbh);
|
||||
$this->listener = new Doctrine_Debugger();
|
||||
$this->manager->setAttribute(Doctrine::ATTR_LISTENER, $this->listener);
|
||||
}
|
||||
|
||||
$this->tables = array("entity","email","phonenumber","groupuser","album","song","element","error","description");
|
||||
$tables = $this->tables;
|
||||
foreach($tables as $name) {
|
||||
$this->dbh->query("DROP TABLE IF EXISTS $name");
|
||||
}
|
||||
|
||||
foreach($tables as $name) {
|
||||
$table = $this->session->getTable($name);
|
||||
$table->getCache()->deleteAll();
|
||||
}
|
||||
|
||||
|
||||
$this->objTable = $this->session->getTable("User");
|
||||
$this->repository = $this->objTable->getRepository();
|
||||
$this->cache = $this->objTable->getCache();
|
||||
|
||||
$this->prepareData();
|
||||
}
|
||||
public function prepareData() {
|
||||
$groups = new Doctrine_Collection($this->session->getTable("Group"));
|
||||
|
||||
$groups[0]->name = "Drama Actors";
|
||||
$groups[0]->save();
|
||||
|
||||
$groups[1]->name = "Quality Actors";
|
||||
$groups[1]->save();
|
||||
|
||||
$groups[2]->name = "Action Actors";
|
||||
$groups[2]["Phonenumber"][0]->phonenumber = "123 123";
|
||||
$groups[2]->save();
|
||||
|
||||
$users = new Doctrine_Collection($this->session->getTable("User"));
|
||||
|
||||
|
||||
$users[0]->name = "zYne";
|
||||
$users[0]["Email"]->address = "zYne@example.com";
|
||||
$users[0]["Phonenumber"][0]->phonenumber = "123 123";
|
||||
|
||||
$users[1]->name = "Arnold Schwarzenegger";
|
||||
$users[1]->Email->address = "arnold@example.com";
|
||||
$users[1]["Phonenumber"][0]->phonenumber = "123 123";
|
||||
$users[1]["Phonenumber"][1]->phonenumber = "456 456";
|
||||
$users[1]->Phonenumber[2]->phonenumber = "789 789";
|
||||
$users[1]->Group[0] = $groups[2];
|
||||
|
||||
$users[2]->name = "Michael Caine";
|
||||
$users[2]->Email->address = "caine@example.com";
|
||||
$users[2]->Phonenumber[0]->phonenumber = "123 123";
|
||||
|
||||
$users[3]->name = "Takeshi Kitano";
|
||||
$users[3]->Email->address = "kitano@example.com";
|
||||
$users[3]->Phonenumber[0]->phonenumber = "111 222 333";
|
||||
|
||||
$users[4]->name = "Sylvester Stallone";
|
||||
$users[4]->Email->address = "stallone@example.com";
|
||||
$users[4]->Phonenumber[0]->phonenumber = "111 555 333";
|
||||
$users[4]["Phonenumber"][1]->phonenumber = "123 213";
|
||||
$users[4]["Phonenumber"][2]->phonenumber = "444 555";
|
||||
|
||||
$users[5]->name = "Kurt Russell";
|
||||
$users[5]->Email->address = "russell@example.com";
|
||||
$users[5]->Phonenumber[0]->phonenumber = "111 222 333";
|
||||
|
||||
$users[6]->name = "Jean Reno";
|
||||
$users[6]->Email->address = "reno@example.com";
|
||||
$users[6]->Phonenumber[0]->phonenumber = "111 222 333";
|
||||
$users[6]["Phonenumber"][1]->phonenumber = "222 123";
|
||||
$users[6]["Phonenumber"][2]->phonenumber = "123 456";
|
||||
|
||||
$users[7]->name = "Edward Furlong";
|
||||
$users[7]->Email->address = "furlong@example.com";
|
||||
$users[7]->Phonenumber[0]->phonenumber = "111 567 333";
|
||||
|
||||
$this->users = $users;
|
||||
$this->session->flush();
|
||||
}
|
||||
public function clearCache() {
|
||||
foreach($this->tables as $name) {
|
||||
$table = $this->session->getTable($name);
|
||||
$table->getCache()->deleteAll();
|
||||
}
|
||||
}
|
||||
public function setUp() {
|
||||
if( ! $this->init) $this->init();
|
||||
|
||||
$this->init = true;
|
||||
$this->new = $this->objTable->create();
|
||||
$this->old = $this->objTable->find(4);
|
||||
}
|
||||
}
|
||||
?>
|
73
tests/ValidatorTestCase.class.php
Normal file
73
tests/ValidatorTestCase.class.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
class Doctrine_ValidatorTestCase extends Doctrine_UnitTestCase {
|
||||
public function testValidate() {
|
||||
|
||||
$set = array("password" => "this is an example of too long password",
|
||||
"loginname" => "this is an example of too long loginname",
|
||||
"name" => "valid name",
|
||||
"created" => "invalid");
|
||||
$this->old->setArray($set);
|
||||
$email = $this->old->Email;
|
||||
$email->address = "zYne@invalid";
|
||||
|
||||
$this->assertTrue($this->old->isLoaded());
|
||||
$this->assertTrue($this->old->getModified() == $set);
|
||||
|
||||
$validator = new Doctrine_Validator();
|
||||
$validator->validateRecord($this->old);
|
||||
$validator->validateRecord($email);
|
||||
|
||||
$stack = $validator->getErrorStack();
|
||||
|
||||
$this->assertTrue(is_array($stack));
|
||||
$this->assertEqual($stack["User"][0]["loginname"], Doctrine_Validator::ERR_LENGTH);
|
||||
$this->assertEqual($stack["User"][0]["password"], Doctrine_Validator::ERR_LENGTH);
|
||||
$this->assertEqual($stack["User"][0]["created"], Doctrine_Validator::ERR_TYPE);
|
||||
|
||||
$this->assertEqual($stack["Email"][0]["address"], Doctrine_Validator::ERR_VALID);
|
||||
$email->address = "arnold@example.com";
|
||||
|
||||
$validator->validateRecord($email);
|
||||
$stack = $validator->getErrorStack();
|
||||
$this->assertEqual($stack["Email"][1]["address"], Doctrine_Validator::ERR_UNIQUE);
|
||||
|
||||
}
|
||||
public function testIsValidEmail() {
|
||||
|
||||
$validator = new Doctrine_Validator_Email();
|
||||
|
||||
$email = $this->session->create("Email");
|
||||
$this->assertFalse($validator->validate($email,"address","example@example"));
|
||||
$this->assertFalse($validator->validate($email,"address","example@@example"));
|
||||
$this->assertFalse($validator->validate($email,"address","example@example."));
|
||||
$this->assertFalse($validator->validate($email,"address","example@e.."));
|
||||
|
||||
$this->assertFalse($validator->validate($email,"address","example@e.."));
|
||||
$this->assertTrue($validator->validate($email,"address","example@e.e.e.e.e"));
|
||||
|
||||
}
|
||||
public function testSave() {
|
||||
$this->manager->setAttribute(Doctrine::ATTR_VLD, true);
|
||||
|
||||
try {
|
||||
$this->old->name = "this is an example of too long name not very good example but an example nevertheless";
|
||||
$this->old->save();
|
||||
} catch(Doctrine_Validator_Exception $e) {
|
||||
$this->assertEqual($e->getErrorStack(),array("User" => array(array("name" => 0))));
|
||||
}
|
||||
|
||||
try {
|
||||
$user = $this->session->create("User");
|
||||
$user->Email->address = "jackdaniels@drinkmore.info...";
|
||||
$user->name = "this is an example of too long user name not very good example but an example nevertheles";
|
||||
$user->save();
|
||||
} catch(Doctrine_Validator_Exception $e) {
|
||||
$a = $e->getErrorStack();
|
||||
}
|
||||
$this->assertTrue(is_array($a));
|
||||
$this->assertEqual($a["Email"][0]["address"], Doctrine_Validator::ERR_VALID);
|
||||
$this->assertEqual($a["User"][0]["name"], Doctrine_Validator::ERR_LENGTH);
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
103
tests/classes.php
Normal file
103
tests/classes.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
class Entity extends Doctrine_Record {
|
||||
public function setUp() {
|
||||
$this->ownsOne("Email","Entity.email_id");
|
||||
$this->ownsMany("Phonenumber","Phonenumber.entity_id");
|
||||
$this->setAttribute(Doctrine::ATTR_FETCHMODE,Doctrine::FETCH_BATCH);
|
||||
}
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("name","string",50);
|
||||
$this->hasColumn("loginname","string",20);
|
||||
$this->hasColumn("password","string",16);
|
||||
$this->hasColumn("type","integer",1);
|
||||
$this->hasColumn("created","integer",11);
|
||||
$this->hasColumn("updated","integer",11);
|
||||
$this->hasColumn("email_id","integer");
|
||||
}
|
||||
}
|
||||
|
||||
// grouptable doesn't extend Doctrine_Table -> Doctrine_Session
|
||||
// won't initialize grouptable when Doctrine_Session->getTable("Group") is called
|
||||
|
||||
class GroupTable { }
|
||||
class Group extends Entity {
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->hasMany("User","Groupuser.user_id");
|
||||
$this->setInheritanceMap(array("type"=>1));
|
||||
|
||||
}
|
||||
}
|
||||
class Error extends Doctrine_Record {
|
||||
public function setUp() {
|
||||
$this->ownsMany("Description","Description.file_md5","file_md5");
|
||||
}
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("message","string",200);
|
||||
$this->hasColumn("code","integer",11);
|
||||
$this->hasColumn("file_md5","string",32,"primary");
|
||||
}
|
||||
}
|
||||
class Description extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("description","string",3000);
|
||||
$this->hasColumn("file_md5","string",32);
|
||||
}
|
||||
}
|
||||
class UserTable extends Doctrine_Table { }
|
||||
class User extends Entity {
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->ownsMany("Album","Album.user_id");
|
||||
$this->hasMany("Group","Groupuser.group_id");
|
||||
$this->setInheritanceMap(array("type"=>0));
|
||||
}
|
||||
}
|
||||
class Groupuser extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("added","integer");
|
||||
$this->hasColumn("group_id","integer");
|
||||
$this->hasColumn("user_id","integer");
|
||||
}
|
||||
}
|
||||
|
||||
class Phonenumber extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("phonenumber","string",20);
|
||||
$this->hasColumn("entity_id","integer");
|
||||
}
|
||||
}
|
||||
class Element extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("name", "string", 100);
|
||||
$this->hasColumn("parent_id", "integer");
|
||||
}
|
||||
public function setUp() {
|
||||
$this->hasMany("Element","Element.parent_id");
|
||||
}
|
||||
}
|
||||
class Email extends Doctrine_Record {
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("address","string",150,"email|unique");
|
||||
}
|
||||
}
|
||||
class Album extends Doctrine_Record {
|
||||
public function setUp() {
|
||||
$this->ownsMany("Song","Song.album_id");
|
||||
}
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("user_id","integer");
|
||||
$this->hasColumn("name","string",20);
|
||||
}
|
||||
}
|
||||
class Song extends Doctrine_Record {
|
||||
public function setUp() {
|
||||
$this->hasColumn("genre","string","30");
|
||||
}
|
||||
public function setTableDefinition() {
|
||||
$this->hasColumn("album_id","integer");
|
||||
$this->hasColumn("genre","string",20);
|
||||
$this->hasColumn("title","string",30);
|
||||
}
|
||||
}
|
||||
?>
|
55
tests/run.php
Normal file
55
tests/run.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
require_once("ConfigurableTestCase.class.php");
|
||||
require_once("ManagerTestCase.class.php");
|
||||
require_once("SessionTestCase.class.php");
|
||||
require_once("TableTestCase.class.php");
|
||||
require_once("EventListenerTestCase.class.php");
|
||||
require_once("BatchIteratorTestCase.class.php");
|
||||
require_once("CacheFileTestCase.class.php");
|
||||
require_once("RecordTestCase.class.php");
|
||||
require_once("DQLParserTestCase.class.php");
|
||||
require_once("AccessTestCase.class.php");
|
||||
require_once("ValidatorTestCase.class.php");
|
||||
print "<pre>";
|
||||
error_reporting(E_ALL);
|
||||
|
||||
$test = new GroupTest("Doctrine Framework Unit Tests");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$test->addTestCase(new Doctrine_RecordTestCase());
|
||||
/**
|
||||
$test->addTestCase(new Doctrine_SessionTestCase());
|
||||
$test->addTestCase(new Doctrine_ValidatorTestCase());
|
||||
|
||||
$test->addTestCase(new Doctrine_ManagerTestCase());
|
||||
$test->addTestCase(new Doctrine_TableTestCase());
|
||||
|
||||
$test->addTestCase(new Doctrine_AccessTestCase());
|
||||
$test->addTestCase(new Doctrine_ConfigurableTestCase());
|
||||
|
||||
|
||||
$test->addTestCase(new Doctrine_EventListenerTestCase());
|
||||
$test->addTestCase(new Doctrine_BatchIteratorTestCase());
|
||||
$test->addTestCase(new Doctrine_Cache_FileTestCase());
|
||||
|
||||
|
||||
|
||||
|
||||
$test->addTestCase(new Doctrine_DQL_ParserTestCase());
|
||||
*/
|
||||
|
||||
|
||||
|
||||
$test->run(new HtmlReporter());
|
||||
|
||||
$a = Doctrine_Manager::getInstance()->getCurrentSession()->getDBH()->getQueries();
|
||||
print "Executed queries: ".count($a)."\n";
|
||||
|
||||
foreach($a as $query) {
|
||||
$e = explode(" ",$query);
|
||||
print $query."\n";
|
||||
}
|
||||
?>
|
Loading…
Reference in New Issue
Block a user