diff --git a/data/stats.cache b/data/stats.cache deleted file mode 100644 index e69de29bb..000000000 diff --git a/draft/DB.php b/draft/DB.php deleted file mode 100644 index 9174680c6..000000000 --- a/draft/DB.php +++ /dev/null @@ -1,556 +0,0 @@ -. - */ - -/** - * Doctrine_Db - * A thin layer on top of PDO - * - * @author Konsta Vesterinen - * @license LGPL - * @package Doctrine - */ -class Doctrine_Db2 implements Countable, IteratorAggregate, Doctrine_Adapter_Interface { - /** - * error constants - */ - const ERR = -1; - const ERR_SYNTAX = -2; - const ERR_CONSTRAINT = -3; - const ERR_NOT_FOUND = -4; - const ERR_ALREADY_EXISTS = -5; - const ERR_UNSUPPORTED = -6; - const ERR_MISMATCH = -7; - const ERR_INVALID = -8; - const ERR_NOT_CAPABLE = -9; - const ERR_TRUNCATED = -10; - const ERR_INVALID_NUMBER = -11; - const ERR_INVALID_DATE = -12; - const ERR_DIVZERO = -13; - const ERR_NODBSELECTED = -14; - const ERR_CANNOT_CREATE = -15; - const ERR_CANNOT_DELETE = -16; - const ERR_CANNOT_DROP = -17; - const ERR_NOSUCHTABLE = -18; - const ERR_NOSUCHFIELD = -19; - const ERR_NEED_MORE_DATA = -20; - const ERR_NOT_LOCKED = -21; - const ERR_VALUE_COUNT_ON_ROW = -22; - const ERR_INVALID_DSN = -23; - const ERR_CONNECT_FAILED = -24; - const ERR_EXTENSION_NOT_FOUND = -25; - const ERR_NOSUCHDB = -26; - const ERR_ACCESS_VIOLATION = -27; - const ERR_CANNOT_REPLACE = -28; - const ERR_CONSTRAINT_NOT_NULL = -29; - const ERR_DEADLOCK = -30; - const ERR_CANNOT_ALTER = -31; - const ERR_MANAGER = -32; - const ERR_MANAGER_PARSE = -33; - const ERR_LOADMODULE = -34; - const ERR_INSUFFICIENT_DATA = -35; - - /** - * @var array $instances all the instances of this class - */ - protected static $instances = array(); - - /** - * @var array $isConnected whether or not a connection has been established - */ - protected $isConnected = false; - - /** - * @var PDO $dbh the database handler - */ - protected $dbh; - - /** - * @var array $options - */ - protected $options = array('dsn' => null, - 'username' => null, - 'password' => null, - ); - - /** - * @var Doctrine_Db_EventListener_Interface|Doctrine_Overloadable $listener - * listener for listening events - */ - protected $listener; - - /** - * @var integer $querySequence - */ - protected $querySequence = 0; - - private static $driverMap = array('oracle' => 'oci8', - 'postgres' => 'pgsql', - 'oci' => 'oci8', - 'sqlite2' => 'sqlite', - 'sqlite3' => 'sqlite'); - - - /** - * constructor - * - * @param string $dsn data source name - * @param string $user database username - * @param string $pass database password - */ - public function __construct($dsn, $user, $pass) { - if( ! isset($user)) { - $a = self::parseDSN($dsn); - - extract($a); - } - $this->options['dsn'] = $dsn; - $this->options['username'] = $user; - $this->options['password'] = $pass; - $this->listener = new Doctrine_Db_EventListener(); - } - - - public function nextQuerySequence() { - return ++$this->querySequence; - } - - /** - * getQuerySequence - */ - public function getQuerySequence() { - return $this->querySequence; - } - - /** - * getDBH - */ - public function getDBH() { - return $this->dbh; - } - public function getOption($name) { - if( ! array_key_exists($name, $this->options)) - throw new Doctrine_Db_Exception('Unknown option ' . $name); - - return $this->options[$name]; - } - - /** - * addListener - * - * @param Doctrine_Db_EventListener_Interface|Doctrine_Overloadable $listener - * @return Doctrine_Db - */ - public function addListener($listener, $name = null) { - if( ! ($this->listener instanceof Doctrine_Db_EventListener_Chain)) - $this->listener = new Doctrine_Db_EventListener_Chain(); - - $this->listener->add($listener, $name); - - return $this; - } - - /** - * getListener - * - * @return Doctrine_Db_EventListener_Interface|Doctrine_Overloadable - */ - public function getListener() { - return $this->listener; - } - - /** - * setListener - * - * @param Doctrine_Db_EventListener_Interface|Doctrine_Overloadable $listener - * @return Doctrine_Db - */ - public function setListener($listener) { - if( ! ($listener instanceof Doctrine_Db_EventListener_Interface) && - ! ($listener instanceof Doctrine_Overloadable)) - throw new Doctrine_Db_Exception("Couldn't set eventlistener for database handler. EventListeners should implement either Doctrine_Db_EventListener_Interface or Doctrine_Overloadable"); - - $this->listener = $listener; - - return $this; - } - - /** - * connect - * connects into database - * - * @return boolean - */ - public function connect() { - if($this->isConnected) - return false; - - $this->dbh = new PDO($this->options['dsn'], $this->options['username'], $this->options['password']); - $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - $this->dbh->setAttribute(PDO::ATTR_STATEMENT_CLASS, array("Doctrine_Db_Statement", array($this))); - $this->isConnected = true; - return true; - } - - /** - * getConnection - * - * @param string $dsn PEAR::DB like DSN or PDO like DSN - * format for PEAR::DB like DSN: schema://user:password@address/dbname - * - * @return - */ - public static function getConnection($dsn = null, $username = null, $password = null) { - return new self($dsn, $username, $password); - } - - /** - * driverName - * converts a driver name like (oracle) to appropriate PDO - * driver name (oci8 in the case of oracle) - * - * @param string $name - * @return string - */ - public static function driverName($name) { - if(isset(self::$driverMap[$name])) - return self::$driverMap[$name]; - - return $name; - } - - /** - * parseDSN - * - * @param string $dsn - * @return array Parsed contents of DSN - */ - function parseDSN($dsn) { - // silence any warnings - $parts = @parse_url($dsn); - - $names = array('scheme', 'host', 'port', 'user', 'pass', 'path', 'query', 'fragment'); - - foreach($names as $name) { - if( ! isset($parts[$name])) - $parts[$name] = null; - } - - if(count($parts) == 0 || ! isset($parts['scheme'])) - throw new Doctrine_Db_Exception('Empty data source name'); - - $drivers = self::getAvailableDrivers(); - - $parts['scheme'] = self::driverName($parts['scheme']); - - if( ! in_array($parts['scheme'], $drivers)) - throw new Doctrine_Db_Exception('Driver '.$parts['scheme'].' not availible or extension not loaded'); - - switch($parts['scheme']) { - case 'sqlite': - if(isset($parts['host']) && $parts['host'] == ':memory') { - $parts['database'] = ':memory:'; - $parts['dsn'] = 'sqlite::memory:'; - } - - break; - case 'mysql': - case 'informix': - case 'oci8': - case 'mssql': - case 'firebird': - case 'pgsql': - case 'odbc': - if( ! isset($parts['path']) || $parts['path'] == '/') - throw new Doctrine_Db_Exception('No database availible in data source name'); - - if(isset($parts['path'])) - $parts['database'] = substr($parts['path'], 1); - - if( ! isset($parts['host'])) - throw new Doctrine_Db_Exception('No hostname set in data source name'); - - $parts['dsn'] = $parts["scheme"].":host=".$parts["host"].";dbname=".$parts["database"]; - break; - default: - throw new Doctrine_Db_Exception('Unknown driver '.$parts['scheme']); - } - - return $parts; - } - /** - * clear - * clears all instances from the memory - * - * @return void - */ - public static function clear() { - self::$instances = array(); - } - - /** - * errorCode - * Fetch the SQLSTATE associated with the last operation on the database handle - * - * @return integer - */ - public function errorCode() { - return $this->dbh->errorCode(); - } - - /** - * errorInfo - * Fetch extended error information associated with the last operation on the database handle - * - * @return array - */ - public function errorInfo() { - return $this->dbh->errorInfo(); - } - - /** - * prepare - * - * @param string $statement - */ - public function prepare($statement) { - $this->connect(); - - $event = new Doctrine_Db_Event($this, Doctrine_Db_Event::PREPARE, $statement); - - $this->listener->onPrePrepare($event); - - $stmt = $this->dbh->prepare($statement); - - $this->listener->onPrepare($event); - - $this->querySequence++; - - return $stmt; - } - - /** - * query - * - * @param string $statement - * @param array $params - * @return Doctrine_Db_Statement|boolean - */ - public function query($statement, array $params = array()) { - $this->connect(); - - $event = new Doctrine_Db_Event($this, Doctrine_Db_Event::QUERY, $statement); - - $this->listener->onPreQuery($event); - - if( ! empty($params)) - $stmt = $this->dbh->query($statement)->execute($params); - else - $stmt = $this->dbh->query($statement); - - $this->listener->onQuery($event); - - $this->querySequence++; - - return $stmt; - } - - /** - * quote - * quotes a string for use in a query - * - * @param string $input - * @return string - */ - public function quote($input) { - $this->connect(); - - return $this->dbh->quote($input); - } - - /** - * exec - * executes an SQL statement and returns the number of affected rows - * - * @param string $statement - * @return integer - */ - public function exec($statement) { - $this->connect(); - - $args = func_get_args(); - - $event = new Doctrine_Db_Event($this, Doctrine_Db_Event::EXEC, $statement); - - $this->listener->onPreExec($event); - - $rows = $this->dbh->exec($statement); - - $this->listener->onExec($event); - - return $rows; - } - - /** - * fetchAll - * - * @return array - */ - public function fetchAll($statement, array $params = array()) { - return $this->query($statement, $params)->fetchAll(PDO::FETCH_ASSOC); - } - - public function fetchOne($statement, array $params = array()) { - return current($this->query($statement, $params)->fetch(PDO::FETCH_NUM)); - } - - public function fetchRow($statement, array $params = array()) { - return $this->query($statement, $params)->fetch(PDO::FETCH_ASSOC); - } - - public function fetchArray($statement, array $params = array()) { - return $this->query($statement, $params)->fetch(PDO::FETCH_NUM); - } - public function fetchColumn($statement, array $params = array()) { - return $this->query($statement, $params)->fetchAll(PDO::FETCH_COLUMN); - } - public function fetchAssoc($statement, array $params = array()) { - return $this->query($statement, $params)->fetchAll(PDO::FETCH_ASSOC); - } - public function fetchBoth($statement, array $params = array()) { - return $this->query($statement, $params)->fetchAll(PDO::FETCH_BOTH); - } - - /** - * lastInsertId - * - * @return integer - */ - public function lastInsertId() { - $this->connect(); - - return $this->dbh->lastInsertId(); - } - - /** - * begins a transaction - * - * @return boolean - */ - public function beginTransaction() { - $event = new Doctrine_Db_Event($this, Doctrine_Db_Event::BEGIN); - - $this->listener->onPreBeginTransaction($event); - - $return = $this->dbh->beginTransaction(); - - $this->listener->onBeginTransaction($event); - - return $return; - } - - /** - * commits a transaction - * - * @return boolean - */ - public function commit() { - $event = new Doctrine_Db_Event($this, Doctrine_Db_Event::COMMIT); - - $this->listener->onPreCommit($event); - - $return = $this->dbh->commit(); - - $this->listener->onCommit($event); - - return $return; - } - - /** - * rollBack - * - * @return boolean - */ - public function rollBack() { - $this->connect(); - - $event = new Doctrine_Db_Event($this, Doctrine_Db_Event::ROLLBACK); - - $this->listener->onPreRollback($event); - - $this->dbh->rollBack(); - - $this->listener->onRollback($event); - } - - /** - * getAttribute - * retrieves a database connection attribute - * - * @param integer $attribute - * @return mixed - */ - public function getAttribute($attribute) { - $this->connect(); - - return $this->dbh->getAttribute($attribute); - } - - /** - * returns an array of available PDO drivers - */ - public static function getAvailableDrivers() { - return PDO::getAvailableDrivers(); - } - - /** - * setAttribute - * sets an attribute - * - * @param integer $attribute - * @param mixed $value - * @return boolean - */ - public function setAttribute($attribute, $value) { - $this->connect(); - - $this->dbh->setAttribute($attribute, $value); - } - - /** - * getIterator - * - * @return ArrayIterator - */ - public function getIterator() { - if($this->listener instanceof Doctrine_Db_Profiler) - return $this->listener; - } - - /** - * count - * returns the number of executed queries - * - * @return integer - */ - public function count() { - return $this->querySequence; - } -} diff --git a/draft/Query/Set.php b/draft/Query/Set.php deleted file mode 100644 index 5d98bb293..000000000 --- a/draft/Query/Set.php +++ /dev/null @@ -1,57 +0,0 @@ -. - */ -Doctrine::autoload('Doctrine_Query_Part'); -/** - * Doctrine_Query - * - * @package Doctrine - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @category Object Relational Mapping - * @link www.phpdoctrine.com - * @since 1.0 - * @version $Revision$ - * @author Konsta Vesterinen - */ -class Doctrine_Query_Set extends Doctrine_Query_Part -{ - public function parse($dql) - { - $parts = Doctrine_Query::sqlExplode($dql, ','); - - $result = array(); - foreach ($parts as $part) { - $set = Doctrine_Query::sqlExplode($part, '='); - - $e = explode('.', trim($set[0])); - $field = array_pop($e); - - $reference = implode('.', $e); - - $alias = $this->query->getTableAlias($reference); - - $fieldname = $alias ? $alias . '.' . $field : $field; - $result[] = $fieldname . ' = ' . $set[1]; - } - - return implode(', ', $result); - } -} - diff --git a/draft/Query/Where.php b/draft/Query/Where.php deleted file mode 100644 index 7fe9313c6..000000000 --- a/draft/Query/Where.php +++ /dev/null @@ -1,226 +0,0 @@ -. - */ -Doctrine::autoload('Doctrine_Query_Condition'); -/** - * Doctrine_Query_Where - * - * @package Doctrine - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @category Object Relational Mapping - * @link www.phpdoctrine.com - * @since 1.0 - * @version $Revision$ - * @author Konsta Vesterinen - */ -class Doctrine_Query_Where extends Doctrine_Query_Condition -{ - /** - * load - * returns the parsed query part - * - * @param string $where - * @return string - */ - public function load($where) - { - $where = trim($where); - - $e = Doctrine_Query::sqlExplode($where); - - if (count($e) > 1) { - $tmp = $e[0] . ' ' . $e[1]; - - if (substr($tmp, 0, 6) == 'EXISTS') { - return $this->parseExists($where, true); - } elseif (substr($where, 0, 10) == 'NOT EXISTS') { - return $this->parseExists($where, false); - } - } - - if (count($e) < 3) { - $e = Doctrine_Query::sqlExplode($where, array('=', '<', '>', '!=')); - } - $r = array_shift($e); - - $a = explode('.', $r); - - if (count($a) > 1) { - $field = array_pop($a); - $count = count($e); - $slice = array_slice($e, -1, 1); - $value = implode('', $slice); - $operator = trim(substr($where, strlen($r), -strlen($value))); - - $reference = implode('.', $a); - $count = count($a); - - $pos = strpos($field, '('); - - if ($pos !== false) { - $func = substr($field, 0, $pos); - $value = trim(substr($field, ($pos + 1), -1)); - - $values = Doctrine_Query::sqlExplode($value, ','); - - $field = array_pop($a); - $reference = implode('.', $a); - $table = $this->query->load($reference, false); - array_pop($a); - $reference2 = implode('.', $a); - $alias = $this->query->getTableAlias($reference2); - - $stack = $this->query->getRelationStack(); - $relation = end($stack); - - $stack = $this->query->getTableStack(); - - switch ($func) { - case 'contains': - case 'regexp': - case 'like': - $operator = $this->getOperator($func); - - if (empty($relation)) { - throw new Doctrine_Query_Exception('DQL functions contains/regexp/like can only be used for fields of related components'); - } - $where = array(); - foreach ($values as $value) { - $where[] = $alias.'.'.$relation->getLocal(). - ' IN (SELECT '.$relation->getForeign(). - ' FROM '.$relation->getTable()->getTableName().' WHERE '.$field.$operator.$value.')'; - } - $where = implode(' AND ', $where); - break; - default: - throw new Doctrine_Query_Exception('Unknown DQL function: '.$func); - } - } else { - $table = $this->query->load($reference, false); - $alias = $this->query->getTableAlias($reference); - $table = $this->query->getTable($alias); - // check if value is enumerated value - $enumIndex = $table->enumIndex($field, trim($value, "'")); - - if (substr($value, 0, 1) == '(') { - // trim brackets - $trimmed = Doctrine_Query::bracketTrim($value); - - if (substr($trimmed, 0, 4) == 'FROM' || substr($trimmed, 0, 6) == 'SELECT') { - // subquery found - $q = new Doctrine_Query(); - $value = '(' . $q->parseQuery($trimmed)->getQuery() . ')'; - } elseif (substr($trimmed, 0, 4) == 'SQL:') { - $value = '(' . substr($trimmed, 4) . ')'; - } else { - // simple in expression found - $e = Doctrine_Query::sqlExplode($trimmed, ','); - - $value = array(); - foreach ($e as $part) { - $index = $table->enumIndex($field, trim($part, "'")); - if ($index !== false) { - $value[] = $index; - } else { - $value[] = $this->parseLiteralValue($part); - } - } - $value = '(' . implode(', ', $value) . ')'; - } - } else { - if ($enumIndex !== false) { - $value = $enumIndex; - } else { - $value = $this->parseLiteralValue($value); - } - } - - switch ($operator) { - case '<': - case '>': - case '=': - case '!=': - if ($enumIndex !== false) { - $value = $enumIndex; - } - default: - $fieldname = $alias ? $alias . '.' . $field : $field; - $where = $fieldname . ' ' - . $operator . ' ' . $value; - } - } - } - return $where; - } - - /** - * parses an EXISTS expression - * - * @param string $where query where part to be parsed - * @param boolean $negation whether or not to use the NOT keyword - * @return string - */ - public function parseExists($where, $negation) - { - $operator = ($negation) ? 'EXISTS' : 'NOT EXISTS'; - - $pos = strpos($where, '('); - - if ($pos == false) - throw new Doctrine_Query_Exception("Unknown expression, expected '('"); - - $sub = Doctrine_Query::bracketTrim(substr($where, $pos)); - - return $operator . ' ('.$this->query->createSubquery()->parseQuery($sub, false)->getQuery() . ')'; - } - - /** - * getOperator - * - * @param string $func - * @return string - */ - public function getOperator($func) - { - switch ($func) { - case 'contains': - $operator = ' = '; - break; - case 'regexp': - $operator = $this->query->getConnection()->getRegexpOperator(); - break; - case 'like': - $operator = ' LIKE '; - break; - } - return $operator; - } - - /** - * __toString - * return string representation of this object - * - * @return string - */ - public function __toString() - { - return ( ! empty($this->parts))?implode(' AND ', $this->parts):''; - } -} diff --git a/draft/Table.php b/draft/Table.php deleted file mode 100644 index e6df5ec1a..000000000 --- a/draft/Table.php +++ /dev/null @@ -1,1298 +0,0 @@ -. - */ - -/** - * Doctrine_Table represents a database table - * each Doctrine_Table holds the information of foreignKeys and associations - * - * - * @author Konsta Vesterinen - * @package Doctrine - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @version $Revision$ - * @category Object Relational Mapping - * @link www.phpdoctrine.com - * @since 1.0 - */ -class Doctrine_Table extends Doctrine_Configurable implements Countable { - /** - * @var array $data temporary data which is then loaded into Doctrine_Record::$data - */ - private $data = array(); - - /** - * @var array $relations an array containing all the Doctrine_Relation objects for this table - */ - private $relations = array(); - - /** - * @var array $primaryKeys an array containing all primary key column names - */ - private $primaryKeys = array(); - - /** - * @var mixed $identifier - */ - private $identifier; - - /** - * @see Doctrine_Identifier constants - * @var integer $identifierType the type of identifier this table uses - */ - private $identifierType; - - /** - * @var string $query cached simple query - */ - private $query; - - /** - * @var Doctrine_Connection $conn Doctrine_Connection object that created this table - */ - private $conn; - - /** - * @var string $name - */ - private $name; - - /** - * @var array $identityMap first level cache - */ - private $identityMap = array(); - - /** - * @var Doctrine_Table_Repository $repository record repository - */ - private $repository; - - /** - * @var array $columns an array of column definitions, - * keys as column names and values as column definitions - * - * the value array has three values: - * - * the column type, eg. 'integer' - * the column length, eg. 11 - * the column options/constraints/validators. eg array('notnull' => true) - * - * so the full columns array might look something like the following: - * array( - * 'name' => array('string', 20, array('notnull' => true, 'default' => 'someone')), - * 'age' => array('integer', 11, array('notnull' => true)) - * ) - */ - protected $columns = array(); - - /** - * @var array $bound bound relations - */ - private $bound = array(); - - /** - * @var array $boundAliases bound relation aliases - */ - private $boundAliases = array(); - - /** - * @var integer $columnCount cached column count, Doctrine_Record uses this column count in when - * determining its state - */ - private $columnCount; - - /** - * @var array $parents the parent classes of this component - */ - private $parents = array(); - - /** - * @var boolean $hasDefaultValues whether or not this table has default values - */ - private $hasDefaultValues; - - /** - * @var array $options an array containing all options - * - * -- name name of the component, for example component name of the GroupTable is 'Group' - * - * -- 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 - * - * -- sequenceName Some databases need sequences instead of auto incrementation primary keys, - * you can set specific sequence for your table by calling setOption('sequenceName', $seqName) - * where $seqName is the name of the desired sequence - * - * -- enumMap enum value arrays - * - * -- inheritanceMap inheritanceMap is used for inheritance mapping, keys representing columns and values - * the column values that should correspond to child classes - */ - protected $options = array('name' => null, - 'tableName' => null, - 'sequenceName' => null, - 'inheritanceMap' => array(), - 'enumMap' => array(), - ); - - - - - /** - * the constructor - * @throws Doctrine_Connection_Exception if there are no opened connections - * @throws Doctrine_Table_Exception if there is already an instance of this table - * @return void - */ - public function __construct($name, Doctrine_Connection $conn) { - $this->conn = $conn; - - $this->setParent($this->conn); - - $this->options['name'] = $name; - - if( ! class_exists($name) || empty($name)) - throw new Doctrine_Exception("Couldn't find class $name"); - - $record = new $name($this); - - $names = array(); - - $class = $name; - - // get parent classes - - do { - if($class == "Doctrine_Record") - break; - - $name = $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(); - - $this->columnCount = count($this->columns); - - if(isset($this->columns)) { - - // get the declaring class of setTableDefinition method - $method = new ReflectionMethod($this->options['name'], 'setTableDefinition'); - $class = $method->getDeclaringClass(); - - if( ! isset($this->options['tableName'])) - $this->options['tableName'] = Doctrine::tableize($class->getName()); - - switch(count($this->primaryKeys)): - case 0: - $this->columns = array_merge(array('id' => - array('integer', - 20, - array('autoincrement' => true, - 'primary' => true - ) - ) - ), $this->columns); - - $this->primaryKeys[] = 'id'; - $this->identifier = 'id'; - $this->identifierType = Doctrine_Identifier::AUTO_INCREMENT; - $this->columnCount++; - break; - default: - if(count($this->primaryKeys) > 1) { - $this->identifier = $this->primaryKeys; - $this->identifierType = Doctrine_Identifier::COMPOSITE; - - } else { - foreach($this->primaryKeys as $pk) { - $e = $this->columns[$pk][2]; - - $found = false; - - foreach($e as $option => $value) { - if($found) - break; - - $e2 = explode(":",$option); - - switch(strtolower($e2[0])): - case "autoincrement": - $this->identifierType = Doctrine_Identifier::AUTO_INCREMENT; - $found = true; - break; - case "seq": - $this->identifierType = Doctrine_Identifier::SEQUENCE; - $found = true; - break; - endswitch; - } - if( ! isset($this->identifierType)) - $this->identifierType = Doctrine_Identifier::NORMAL; - - $this->identifier = $pk; - } - } - endswitch; - - if($this->getAttribute(Doctrine::ATTR_CREATE_TABLES)) { - if(Doctrine::isValidClassname($class->getName())) { - //$dict = new Doctrine_DataDict($this->getConnection()->getDBH()); - try { - $columns = array(); - foreach($this->columns as $name => $column) { - $definition = $column[2]; - $definition['type'] = $column[0]; - $definition['length'] = $column[1]; - - if($definition['type'] == 'enum' && isset($definition['default'])) - $definition['default'] = $this->enumIndex($name, $definition['default']); - - if($definition['type'] == 'boolean' && isset($definition['default'])) - $definition['default'] = (int) $definition['default']; - - $columns[$name] = $definition; - } - $this->conn->export->createTable($this->options['tableName'], $columns); - } catch(Exception $e) { - - } - } - } - - } - } else { - throw new Doctrine_Table_Exception("Class '$name' has no table definition."); - } - - // perform tree setup - if($this->isTree()) - $this->getTree()->setUp(); - - $record->setUp(); - - // 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->conn->addTable($this)) - throw new Doctrine_Table_Exception(); - - $this->repository = new Doctrine_Table_Repository($this); - } - - /** - * createQuery - * creates a new Doctrine_Query object and adds the component name - * of this table as the query 'from' part - * - * @return Doctrine_Query - */ - public function createQuery() { - return Doctrine_Query::create()->from($this->getComponentName()); - } - - /** - * getRepository - * - * @return Doctrine_Table_Repository - */ - public function getRepository() { - return $this->repository; - } - - public function setOption($name, $value) { - switch($name) { - case 'name': - case 'tableName': - break; - case 'enumMap': - case 'inheritanceMap': - if( ! is_array($value)) - throw new Doctrine_Table_Exception($name.' should be an array.'); - break; - } - $this->options[$name] = $value; - } - - public function usesInheritanceMap() { - return ( ! empty($this->options['inheritanceMap'])); - } - public function getOption($name) { - if(isset($this->options[$name])) - return $this->options[$name]; - - return null; - } - - /** - * setColumn - * @param string $name - * @param string $type - * @param integer $length - * @param mixed $options - * @return void - */ - final public function setColumn($name, $type, $length, $options = array()) { - if(is_string($options)) - $options = explode('|', $options); - - foreach($options as $k => $option) { - if(is_numeric($k)) { - if( ! empty($option)) - $options[$option] = true; - - unset($options[$k]); - } - } - $name = strtolower($name); - $this->columns[$name] = array($type,$length,$options); - - if(isset($options['primary'])) { - $this->primaryKeys[] = $name; - } - if(isset($options['default'])) { - $this->hasDefaultValues = true; - } - } - - /** - * hasDefaultValues - * returns true if this table has default values, otherwise false - * - * @return boolean - */ - public function hasDefaultValues() { - return $this->hasDefaultValues; - } - - /** - * getDefaultValueOf - * returns the default value(if any) for given column - * - * @param string $column - * @return mixed - */ - public function getDefaultValueOf($column) { - $column = strtolower($column); - if( ! isset($this->columns[$column])) - throw new Doctrine_Table_Exception("Couldn't get default value. Column ".$column." doesn't exist."); - - if(isset($this->columns[$column][2]['default'])) { - - return $this->columns[$column][2]['default']; - } else - return null; - } - - /** - * @return mixed - */ - final public function getIdentifier() { - return $this->identifier; - } - - /** - * @return integer - */ - final public function getIdentifierType() { - return $this->identifierType; - } - - /** - * hasColumn - * @return boolean - */ - final public function hasColumn($name) { - return isset($this->columns[$name]); - } - - /** - * @param mixed $key - * @return void - */ - final public function setPrimaryKey($key) { - switch(gettype($key)): - case "array": - $this->primaryKeys = array_values($key); - break; - case "string": - $this->primaryKeys[] = $key; - break; - endswitch; - } - - /** - * 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->options['sequenceName'] = $sequence; - } - - /** - * @return string sequence name - */ - final public function getSequenceName() { - return $this->options['sequenceName']; - } - - /** - * getParents - */ - final public function getParents() { - return $this->parents; - } - - /** - * @return boolean - */ - final public function hasInheritanceMap() { - return (empty($this->options['inheritanceMap'])); - } - - /** - * @return array inheritance map (array keys as fields) - */ - final public function getInheritanceMap() { - return $this->options['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->getRelation($k); - switch($fk->getType()): - case Doctrine_Relation::ONE_COMPOSITE: - case Doctrine_Relation::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(Doctrine_Table_Exception $e) { - - } - } - return $array; - } - - /** - * returns all bound relations - * - * @return array - */ - public function getBounds() { - return $this->bound; - } - - /** - * returns a bound relation array - * - * @param string $name - * @return array - */ - public function getBound($name) { - if( ! isset($this->bound[$name])) - throw new Doctrine_Table_Exception('Unknown bound '.$name); - - return $this->bound[$name]; - } - - /** - * returns a bound relation array - * - * @param string $name - * @return array - */ - public function getBoundForName($name, $component) { - - foreach($this->bound as $k => $bound) { - $e = explode('.', $bound[0]); - - if($bound[3] == $name && $e[0] == $component) { - return $this->bound[$k]; - } - } - throw new Doctrine_Table_Exception('Unknown bound '.$name); - } - - /** - * returns the alias for given component name - * - * @param string $name - * @return string - */ - public function getAlias($name) { - if(isset($this->boundAliases[$name])) - return $this->boundAliases[$name]; - - return $name; - } - - /** - * returns component name for given alias - * - * @param string $alias - * @return string - */ - public function getAliasName($alias) { - if($name = array_search($alias, $this->boundAliases)) - return $name; - - return $alias; - } - - /** - * unbinds all relations - * - * @return void - */ - public function unbindAll() { - $this->bound = array(); - $this->relations = array(); - $this->boundAliases = array(); - } - - /** - * unbinds a relation - * returns true on success, false on failure - * - * @param $name - * @return boolean - */ - public function unbind($name) { - if( ! isset($this->bound[$name])) - return false; - - unset($this->bound[$name]); - - if(isset($this->relations[$name])) - unset($this->relations[$name]); - - if(isset($this->boundAliases[$name])) - unset($this->boundAliases[$name]); - - return true; - } - - /** - * binds a relation - * - * @param string $name - * @param string $field - * @return void - */ - public function bind($name, $field, $type, $localKey) { - if(isset($this->relations[$name])) - unset($this->relations[$name]); - - $e = explode(" as ",$name); - $name = $e[0]; - - if(isset($e[1])) { - $alias = $e[1]; - $this->boundAliases[$name] = $alias; - } else - $alias = $name; - - - $this->bound[$alias] = array($field, $type, $localKey, $name); - } - - /** - * getComponentName - * @return string the component name - */ - public function getComponentName() { - return $this->options['name']; - } - - /** - * @return Doctrine_Connection - */ - public function getConnection() { - return $this->conn; - } - - /** - * hasRelatedComponent - * @return boolean - */ - final public function hasRelatedComponent($name, $component) { - return (strpos($this->bound[$name][0], $component.'.') !== false); - } - - /** - * @param string $name component name of which a foreign key object is bound - * @return boolean - */ - final public function hasRelation($name) { - if(isset($this->bound[$name])) - return true; - - foreach($this->bound as $k=>$v) - { - if($this->hasRelatedComponent($k, $name)) - return true; - } - return false; - } - - /** - * getRelation - * - * @param string $name component name of which a foreign key object is bound - * @return Doctrine_Relation - */ - final public function getRelation($name, $recursive = true) { - $original = $name; - - if(isset($this->relations[$name])) - return $this->relations[$name]; - - if(isset($this->bound[$name])) { - $type = $this->bound[$name][1]; - $local = $this->bound[$name][2]; - list($component, $foreign) = explode(".",$this->bound[$name][0]); - $alias = $name; - $name = $this->bound[$alias][3]; - - $table = $this->conn->getTable($name); - - if($component == $this->options['name'] || in_array($component, $this->parents)) { - - // ONE-TO-ONE - if($type == Doctrine_Relation::ONE_COMPOSITE || - $type == Doctrine_Relation::ONE_AGGREGATE) { - if( ! isset($local)) - $local = $table->getIdentifier(); - - $relation = new Doctrine_Relation_LocalKey($table, $foreign, $local, $type, $alias); - } else - $relation = new Doctrine_Relation_ForeignKey($table, $foreign, $local, $type, $alias); - - - } elseif($component == $name || - ($component == $alias)) { // && ($name == $this->options['name'] || in_array($name,$this->parents)) - - if( ! isset($local)) - $local = $this->identifier; - - // ONE-TO-MANY or ONE-TO-ONE - $relation = new Doctrine_Relation_ForeignKey($table, $local, $foreign, $type, $alias); - - } else { - // MANY-TO-MANY - // only aggregate relations allowed - - if($type != Doctrine_Relation::MANY_AGGREGATE) - throw new Doctrine_Table_Exception("Only aggregate relations are allowed for many-to-many relations"); - - $classes = array_merge($this->parents, array($this->options['name'])); - - foreach(array_reverse($classes) as $class) { - try { - $bound = $table->getBoundForName($class, $component); - break; - } catch(Doctrine_Table_Exception $exc) { } - } - if( ! isset($bound)) - throw new Doctrine_Table_Exception("Couldn't map many-to-many relation for " - . $this->options['name'] . " and $name. Components use different join tables."); - - - if( ! isset($local)) - $local = $this->identifier; - - $e2 = explode('.', $bound[0]); - $fields = explode('-', $e2[1]); - - if($e2[0] != $component) - throw new Doctrine_Table_Exception($e2[0] . ' doesn\'t match ' . $component); - - $associationTable = $this->conn->getTable($e2[0]); - - if(count($fields) > 1) { - // SELF-REFERENCING THROUGH JOIN TABLE - $this->relations[$e2[0]] = new Doctrine_Relation_ForeignKey($associationTable, $local, $fields[0],Doctrine_Relation::MANY_COMPOSITE, $e2[0]); - - $relation = new Doctrine_Relation_Association_Self($table, $associationTable, $fields[0], $fields[1], $type, $alias); - } else { - - // auto initialize a new one-to-one relationship for association table - $associationTable->bind($this->getComponentName(), $associationTable->getComponentName(). '.' .$e2[1], Doctrine_Relation::ONE_AGGREGATE, $this->getIdentifier()); - $associationTable->bind($table->getComponentName(), $associationTable->getComponentName(). '.' .$foreign, Doctrine_Relation::ONE_AGGREGATE, $table->getIdentifier()); - - // NORMAL MANY-TO-MANY RELATIONSHIP - $this->relations[$e2[0]] = new Doctrine_Relation_ForeignKey($associationTable, $local, $e2[1], Doctrine_Relation::MANY_COMPOSITE, $e2[0]); - - $relation = new Doctrine_Relation_Association($table, $associationTable, $e2[1], $foreign, $type, $alias); - } - - } - - $this->relations[$alias] = $relation; - return $this->relations[$alias]; - } - - // load all relations - $this->getRelations(); - - if($recursive) { - return $this->getRelation($original, false); - } else { - throw new Doctrine_Table_Exception($this->options['name'] . " doesn't have a relation to " . $original); - } - } - - /** - * returns an array containing all foreign key objects - * - * @return array - */ - final public function getRelations() { - $a = array(); - foreach($this->bound as $k=>$v) { - $this->getRelation($k); - } - - return $this->relations; - } - - /** - * sets the database table name - * - * @param string $name database table name - * @return void - */ - final public function setTableName($name) { - $this->options['tableName'] = $name; - } - - /** - * returns the database table name - * - * @return string - */ - final public function getTableName() { - return $this->options['tableName']; - } - - /** - * create - * creates a new record - * - * @param $array an array where keys are field names and values representing field values - * @return Doctrine_Record - */ - public function create(array $array = array()) { - $this->data = $array; - $record = new $this->options['name']($this, true); - $this->data = array(); - return $record; - } - - /** - * finds a record by its identifier - * - * @param $id database row id - * @return Doctrine_Record|false a record for given database identifier - */ - public function find($id) { - if($id !== null) { - if( ! is_array($id)) - $id = array($id); - else - $id = array_values($id); - - $query = $this->query." WHERE ".implode(" = ? AND ",$this->primaryKeys)." = ?"; - $query = $this->applyInheritance($query); - - - $params = array_merge($id, array_values($this->options['inheritanceMap'])); - - $stmt = $this->conn->execute($query,$params); - - $this->data = $stmt->fetch(PDO::FETCH_ASSOC); - - if($this->data === false) - return false; - - return $this->getRecord(); - } - return false; - } - - /** - * applyInheritance - * @param $where query where part to be modified - * @return string query where part with column aggregation inheritance added - */ - final public function applyInheritance($where) { - if( ! empty($this->options['inheritanceMap'])) { - $a = array(); - foreach($this->options['inheritanceMap'] as $field => $value) { - $a[] = $field." = ?"; - } - $i = implode(" AND ",$a); - $where .= " AND $i"; - } - return $where; - } - - /** - * findAll - * returns a collection of records - * - * @return Doctrine_Collection - */ - public function findAll() { - $graph = new Doctrine_Query($this->conn); - $users = $graph->query("FROM ".$this->options['name']); - return $users; - } - - /** - * findByDql - * finds records with given DQL where clause - * returns a collection of records - * - * @param string $dql DQL after WHERE clause - * @param array $params query parameters - * @return Doctrine_Collection - */ - public function findBySql($dql, array $params = array()) { - $q = new Doctrine_Query($this->conn); - $users = $q->query("FROM ".$this->options['name']." WHERE ".$dql, $params); - return $users; - } - - public function findByDql($dql, array $params = array()) { - return $this->findBySql($dql, $params); - } - - /** - * clear - * clears the first level cache (identityMap) - * - * @return void - */ - public function clear() { - $this->identityMap = array(); - } - - /** - * getRecord - * first checks if record exists in identityMap, if not - * returns a new record - * - * @return Doctrine_Record - */ - public function getRecord() { - $this->data = array_change_key_case($this->data, CASE_LOWER); - - $key = $this->getIdentifier(); - - if( ! is_array($key)) - $key = array($key); - - foreach($key as $k) { - if( ! isset($this->data[$k])) - throw new Doctrine_Exception("Primary key value for $k wasn't found"); - - $id[] = $this->data[$k]; - } - - $id = implode(' ', $id); - - if(isset($this->identityMap[$id])) - $record = $this->identityMap[$id]; - else { - $record = new $this->options['name']($this); - $this->identityMap[$id] = $record; - } - $this->data = array(); - - return $record; - } - - /** - * @param $id database row id - * @throws Doctrine_Find_Exception - */ - final public function getProxy($id = null) { - if($id !== null) { - $query = "SELECT ".implode(", ",$this->primaryKeys)." FROM ".$this->getTableName()." WHERE ".implode(" = ? && ",$this->primaryKeys)." = ?"; - $query = $this->applyInheritance($query); - - $params = array_merge(array($id), array_values($this->options['inheritanceMap'])); - - $this->data = $this->conn->execute($query,$params)->fetch(PDO::FETCH_ASSOC); - - if($this->data === false) - return false; - } - return $this->getRecord(); - } - - /** - * count - * - * @return integer - */ - public function count() { - $a = $this->conn->getDBH()->query("SELECT COUNT(1) FROM ".$this->options['tableName'])->fetch(PDO::FETCH_NUM); - return current($a); - } - - /** - * @return Doctrine_Query a Doctrine_Query object - */ - public function getQueryObject() { - $graph = new Doctrine_Query($this->getConnection()); - $graph->load($this->getComponentName()); - return $graph; - } - - /** - * execute - * @param string $query - * @param array $array - * @param integer $limit - * @param integer $offset - */ - public function execute($query, array $array = array(), $limit = null, $offset = null) { - $coll = new Doctrine_Collection($this); - $query = $this->conn->modifyLimitQuery($query,$limit,$offset); - if( ! empty($array)) { - $stmt = $this->conn->getDBH()->prepare($query); - $stmt->execute($array); - } else { - $stmt = $this->conn->getDBH()->query($query); - } - $data = $stmt->fetchAll(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - foreach($data as $row) { - $this->data = $row; - $record = $this->getRecord(); - $coll->add($record); - } - return $coll; - } - - /** - * sets enumerated value array for given field - * - * @param string $field - * @param array $values - * @return void - */ - final public function setEnumValues($field, array $values) { - $this->options['enumMap'][strtolower($field)] = $values; - } - - /** - * @param string $field - * @return array - */ - final public function getEnumValues($field) { - if(isset($this->options['enumMap'][$field])) - return $this->options['enumMap'][$field]; - else - return array(); - } - - /** - * enumValue - * - * @param string $field - * @param integer $index - * @return mixed - */ - final public function enumValue($field, $index) { - if ($index instanceof Doctrine_Null) - return $index; - - return isset($this->options['enumMap'][$field][$index]) ? $this->options['enumMap'][$field][$index] : $index; - } - - /** - * invokeSet - * - * @param mixed $value - */ - public function invokeSet(Doctrine_Record $record, $name, $value) { - if( ! ($this->getAttribute(Doctrine::ATTR_ACCESSORS) & Doctrine::ACCESSOR_SET)) - return $value; - - $prefix = $this->getAttribute(Doctrine::ATTR_ACCESSOR_PREFIX_SET); - if ( ! $prefix) - $prefix = 'set'; - - $method = $prefix . $name; - - if(method_exists($record, $method)) { - return $record->$method($value); - } - - return $value; - } - - /** - * invokeGet - * - * @param mixed $value - */ - public function invokeGet(Doctrine_Record $record, $name, $value) { - if( ! ($this->getAttribute(Doctrine::ATTR_ACCESSORS) & Doctrine::ACCESSOR_GET)) - return $value; - - $prefix = $this->getAttribute(Doctrine::ATTR_ACCESSOR_PREFIX_GET); - if ( ! $prefix) - $prefix = 'get'; - - $method = $prefix . $name; - - if(method_exists($record, $method)) { - return $record->$method($value); - } - - return $value; - } - - /** - * enumIndex - * - * @param string $field - * @param mixed $value - * @return mixed - */ - final public function enumIndex($field, $value) { - if( ! isset($this->options['enumMap'][$field])) - $values = array(); - else - $values = $this->options['enumMap'][$field]; - - return array_search($value, $values); - } - - /** - * getDefinitionOf - * - * @return string ValueWrapper class name on success, false on failure - */ - public function getValueWrapperOf($column) { - if(isset($this->columns[$column][2]['wrapper'])) - return $this->columns[$column][2]['wrapper']; - - return false; - } - - /** - * getColumnCount - * - * @return integer the number of columns in this table - */ - final public function getColumnCount() { - return $this->columnCount; - } - - /** - * returns all columns and their definitions - * - * @return array - */ - final public function getColumns() { - return $this->columns; - } - - /** - * returns an array containing all the column names - * - * @return array - */ - public function getColumnNames() { - return array_keys($this->columns); - } - - /** - * getDefinitionOf - * - * @return mixed array on success, false on failure - */ - public function getDefinitionOf($column) { - if(isset($this->columns[$column])) - return $this->columns[$column]; - - return false; - } - - /** - * getTypeOf - * - * @return mixed string on success, false on failure - */ - public function getTypeOf($column) { - if(isset($this->columns[$column])) - return $this->columns[$column][0]; - - return false; - } - - /** - * setData - * doctrine uses this function internally - * users are strongly discouraged to use this function - * - * @param array $data internal data - * @return void - */ - public function setData(array $data) { - $this->data = $data; - } - - /** - * returns the maximum primary key value - * - * @return integer - */ - final public function getMaxIdentifier() { - $sql = "SELECT MAX(".$this->getIdentifier().") FROM ".$this->getTableName(); - $stmt = $this->conn->getDBH()->query($sql); - $data = $stmt->fetch(PDO::FETCH_NUM); - return isset($data[0])?$data[0]:1; - } - - /** - * returns simple cached query - * - * @return string - */ - final public function getQuery() { - return $this->query; - } - - /** - * returns internal data, used by Doctrine_Record instances - * when retrieving data from database - * - * @return array - */ - final public function getData() { - return $this->data; - } - - /** - * returns a string representation of this object - * - * @return string - */ - public function __toString() { - return Doctrine_Lib::getTableAsString($this); - } - - /** - * returns a string representation of this object - * - * @return string - */ - public function setTree($implName, $options) { - $this->_treeImplName = $implName; - $this->_treeOptions = $options; - - $this->_tree = Doctrine_Tree::factory($this, $this->_treeImplName, $this->_treeOptions); - - // set the table definition for the given tree implementation - $this->_tree->setTableDefinition(); - } - - /** - * getter for associated tree - * - * @return mixed if tree return instance of Doctrine_Tree, otherwise returns false - */ - public function getTree() { - return isset($this->_treeImplName) ? $this->_tree : false; - } - - /** - * determine if table acts as tree - * - * @return mixed if tree return instance of Doctrine_Tree, otherwise returns false - */ - public function isTree() { - return !is_null($this->_treeImplName) ? true : false; - } - - /** - * getter for tree implementation name - * - * @return string tree implementation name (NestedSet | AdjacencyList | MaterializedPath) - */ - public function getTreeImplName() { - return $this->_treeImplName; - } - - /** - * getter for tree options - * - * @return array tree options - */ - public function getTreeOptions() { - return $this->_treeOptions; - } -} - diff --git a/draft/new-core/Connection.php b/draft/new-core/Connection.php deleted file mode 100644 index d0989fd17..000000000 --- a/draft/new-core/Connection.php +++ /dev/null @@ -1,1099 +0,0 @@ -. - */ -Doctrine::autoload('Doctrine_Configurable'); -/** - * Doctrine_Connection - * - * @package Doctrine - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @category Object Relational Mapping - * @link www.phpdoctrine.com - * @since 1.0 - * @version $Revision: 1270 $ - * @author Konsta Vesterinen - * @author Lukas Smith (MDB2 library) - */ -abstract class Doctrine_Connection extends Doctrine_Configurable implements Countable, IteratorAggregate -{ - /** - * @var $dbh the database handler - */ - protected $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 - */ - protected $tables = array(); - - /** - * @var array $exported - */ - protected $exported = array(); - - /** - * @var string $driverName the name of this connection driver - */ - protected $driverName; - - /** - * @var array $supported an array containing all features this driver supports, - * keys representing feature names and values as - * one of the following (true, false, 'emulated') - */ - protected $supported = array(); - - /** - * @var array $modules an array containing all modules - * transaction Doctrine_Transaction driver, handles savepoint and transaction isolation abstraction - * - * expression Doctrine_Expression driver, handles expression abstraction - * - * dataDict Doctrine_DataDict driver, handles datatype abstraction - * - * export Doctrine_Export driver, handles db structure modification abstraction (contains - * methods such as alterTable, createConstraint etc.) - * import Doctrine_Import driver, handles db schema reading - * - * sequence Doctrine_Sequence driver, handles sequential id generation and retrieval - * - * @see Doctrine_Connection::__get() - * @see Doctrine_DataDict - * @see Doctrine_Expression - * @see Doctrine_Export - * @see Doctrine_Transaction - * @see Doctrine_Sequence - */ - private $modules = array('transaction' => false, - 'expression' => false, - 'dataDict' => false, - 'export' => false, - 'import' => false, - 'sequence' => false, - 'unitOfWork' => false, - ); - - /** - * @var array $properties an array of connection properties - */ - protected $properties = array('sql_comments' => array(array('start' => '--', 'end' => "\n", 'escape' => false), - array('start' => '/*', 'end' => '*/', 'escape' => false) - ), - 'identifier_quoting' => array('start' => '"', - 'end' => '"', - 'escape' => '"' - ), - 'string_quoting' => array('start' => "'", - 'end' => "'", - 'escape' => false, - 'escape_pattern' => false - ), - 'wildcards' => array('%', '_'), - 'varchar_max_length' => 255, - ); - - /** - * @var array $serverInfo - */ - protected $serverInfo = array(); - - /** - * @var array $availableDrivers an array containing all availible drivers - */ - private static $availableDrivers = array( - 'Mysql', - 'Pgsql', - 'Oracle', - 'Informix', - 'Mssql', - 'Sqlite', - 'Firebird' - ); - - /** - * the constructor - * - * @param Doctrine_Manager $manager the manager object - * @param PDO|Doctrine_Adapter_Interface $adapter database driver - */ - public function __construct(Doctrine_Manager $manager, $adapter) - { - if ( ! ($adapter instanceof PDO) && ! in_array('Doctrine_Adapter_Interface', class_implements($adapter))) { - throw new Doctrine_Connection_Exception("First argument should be an instance of PDO or implement Doctrine_Adapter_Interface"); - } - $this->dbh = $adapter; - - //$this->modules['transaction'] = new Doctrine_Connection_Transaction($this); - $this->modules['unitOfWork'] = new Doctrine_Connection_UnitOfWork($this); - - $this->setParent($manager); - - $this->dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL); - $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - - $this->getAttribute(Doctrine::ATTR_LISTENER)->onOpen($this); - } - - /** - * getName - * returns the name of this driver - * - * @return string the name of this driver - */ - public function getName() - { - return $this->driverName; - } - - /** - * __get - * lazy loads given module and returns it - * - * @see Doctrine_DataDict - * @see Doctrine_Expression - * @see Doctrine_Export - * @see Doctrine_Transaction - * @see Doctrine_Connection::$modules all availible modules - * @param string $name the name of the module to get - * @throws Doctrine_Connection_Exception if trying to get an unknown module - * @return Doctrine_Connection_Module connection module - */ - public function __get($name) - { - if (isset($this->properties[$name])) - return $this->properties[$name]; - - if ( ! isset($this->modules[$name])) { - throw new Doctrine_Connection_Exception('Unknown module / property ' . $name); - } - if ($this->modules[$name] === false) { - switch ($name) { - case 'unitOfWork': - $this->modules[$name] = new Doctrine_Connection_UnitOfWork($this); - break; - default: - $class = 'Doctrine_' . ucwords($name) . '_' . $this->getName(); - $this->modules[$name] = new $class($this); - } - } - - return $this->modules[$name]; - } - - /** - * Quotes pattern (% and _) characters in a string) - * - * EXPERIMENTAL - * - * WARNING: this function is experimental and may change signature at - * any time until labelled as non-experimental - * - * @param string the input string to quote - * - * @return string quoted string - */ - public function escapePattern($text) - { - if ($this->string_quoting['escape_pattern']) { - $text = str_replace($this->string_quoting['escape_pattern'], $this->string_quoting['escape_pattern'] . $this->string_quoting['escape_pattern'], $text); - foreach ($this->wildcards as $wildcard) { - $text = str_replace($wildcard, $this->string_quoting['escape_pattern'] . $wildcard, $text); - } - } - return $text; - } - - /** - * convertBoolean - * some drivers need the boolean values to be converted into integers - * when using DQL API - * - * This method takes care of that conversion - * - * @param array $item - * @return void - */ - public function convertBooleans($item) - { - if (is_array($item)) { - foreach ($item as $k => $value) { - if (is_bool($item)) { - $item[$k] = (int) $value; - } - } - } else { - $item = (int) $item; - } - return $item; - } - - /** - * Quote a string so it can be safely used as a table or column name - * - * Delimiting style depends on which database driver is being used. - * - * NOTE: just because you CAN use delimited identifiers doesn't mean - * you SHOULD use them. In general, they end up causing way more - * problems than they solve. - * - * Portability is broken by using the following characters inside - * delimited identifiers: - * + backtick (`) -- due to MySQL - * + double quote (") -- due to Oracle - * + brackets ([ or ]) -- due to Access - * - * Delimited identifiers are known to generally work correctly under - * the following drivers: - * + mssql - * + mysql - * + mysqli - * + oci8 - * + pgsql - * + sqlite - * - * InterBase doesn't seem to be able to use delimited identifiers - * via PHP 4. They work fine under PHP 5. - * - * @param string $str identifier name to be quoted - * @param bool $checkOption check the 'quote_identifier' option - * - * @return string quoted identifier string - */ - public function quoteIdentifier($str, $checkOption = true) - { - if ($checkOption && ! $this->getAttribute(Doctrine::ATTR_QUOTE_IDENTIFIER)) { - return $str; - } - $str = str_replace($this->properties['identifier_quoting']['end'], - $this->properties['identifier_quoting']['escape'] . - $this->properties['identifier_quoting']['end'], $str); - - return $this->properties['identifier_quoting']['start'] - . $str . $this->properties['identifier_quoting']['end']; - } - - /** - * returns the manager that created this connection - * - * @return Doctrine_Manager - */ - public function getManager() - { - return $this->getParent(); - } - - /** - * returns the database handler of which this connection uses - * - * @return PDO the database handler - */ - public function getDbh() - { - return $this->dbh; - } - - /** - * converts given driver name - * - * @param - */ - public function driverName($name) - { - } - - /** - * supports - * - * @param string $feature the name of the feature - * @return boolean whether or not this drivers supports given feature - */ - public function supports($feature) - { - return (isset($this->supported[$feature]) - && ($this->supported[$feature] === 'emulated' - || $this->supported[$feature] - ) - ); - } - - /** - * quote - * quotes given input parameter - * - * @param mixed $input parameter to be quoted - * @param string $type - * @return mixed - */ - public function quote($input, $type = null) - { - if ($type == null) { - $type = gettype($input); - } - switch ($type) { - case 'integer': - case 'enum': - case 'boolean': - case 'double': - case 'float': - case 'bool': - case 'int': - return $input; - case 'array': - case 'object': - $input = serialize($input); - case 'string': - case 'char': - case 'varchar': - case 'text': - case 'gzip': - case 'blob': - case 'clob': - return $this->dbh->quote($input); - } - } - - /** - * Removes any formatting in an sequence name using the 'seqname_format' option - * - * @param string $sqn string that containts name of a potential sequence - * @return string name of the sequence with possible formatting removed - */ - public function fixSequenceName($sqn) - { - $seqPattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $this->getAttribute(Doctrine::ATTR_SEQNAME_FORMAT)).'$/i'; - $seqName = preg_replace($seqPattern, '\\1', $sqn); - - if ($seqName && ! strcasecmp($sqn, $this->getSequenceName($seqName))) { - return $seqName; - } - return $sqn; - } - - /** - * Removes any formatting in an index name using the 'idxname_format' option - * - * @param string $idx string that containts name of anl index - * @return string name of the index with possible formatting removed - */ - public function fixIndexName($idx) - { - $indexPattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $this->getAttribute(Doctrine::ATTR_IDXNAME_FORMAT)).'$/i'; - $indexName = preg_replace($indexPattern, '\\1', $idx); - if ($indexName && ! strcasecmp($idx, $this->getIndexName($indexName))) { - return $indexName; - } - return $idx; - } - - /** - * adds sequence name formatting to a sequence name - * - * @param string name of the sequence - * @return string formatted sequence name - */ - public function getSequenceName($sqn) - { - return sprintf($this->getAttribute(Doctrine::ATTR_SEQNAME_FORMAT), - preg_replace('/[^a-z0-9_\$.]/i', '_', $sqn)); - } - - /** - * adds index name formatting to a index name - * - * @param string name of the index - * @return string formatted index name - */ - public function getIndexName($idx) - { - return sprintf($this->getAttribute(Doctrine::ATTR_IDXNAME_FORMAT), - preg_replace('/[^a-z0-9_\$]/i', '_', $idx)); - } - - /** - * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT - * query, except that if there is already a row in the table with the same - * key field values, the REPLACE query just updates its values instead of - * inserting a new row. - * - * The REPLACE type of query does not make part of the SQL standards. Since - * practically only MySQL and SQLIte implement it natively, this type of - * query isemulated through this method for other DBMS using standard types - * of queries inside a transaction to assure the atomicity of the operation. - * - * @param string name of the table on which the REPLACE query will - * be executed. - * - * @param array an associative array that describes the fields and the - * values that will be inserted or updated in the specified table. The - * indexes of the array are the names of all the fields of the table. - * - * The values of the array are values to be assigned to the specified field. - * - * @param array $keys an array containing all key fields (primary key fields - * or unique index fields) for this table - * - * the uniqueness of a row will be determined according to - * the provided key fields - * - * this method will fail if no key fields are specified - * - * @throws Doctrine_Connection_Exception if this driver doesn't support replace - * @throws Doctrine_Connection_Exception if some of the key values was null - * @throws Doctrine_Connection_Exception if there were no key fields - * @throws PDOException if something fails at PDO level - * @return integer number of rows affected - */ - public function replace($table, array $fields, array $keys) - { - //if ( ! $this->supports('replace')) - // throw new Doctrine_Connection_Exception('replace query is not supported'); - - if (empty($keys)) { - throw new Doctrine_Connection_Exception('Not specified which fields are keys'); - } - $condition = $values = array(); - - foreach ($fields as $name => $value) { - $values[$name] = $value; - - if (in_array($name, $keys)) { - if ($value === null) - throw new Doctrine_Connection_Exception('key value '.$name.' may not be null'); - - $condition[] = $name . ' = ?'; - $conditionValues[] = $value; - } - } - - $query = 'DELETE FROM ' . $this->quoteIdentifier($table) . ' WHERE ' . implode(' AND ', $condition); - $affectedRows = $this->exec($query); - - $this->insert($table, $values); - - $affectedRows++; - - - return $affectedRows; - } - - /** - * Inserts a table row with specified data. - * - * @param string $table The table to insert data into. - * @param array $values An associateve array containing column-value pairs. - * @return boolean - */ - public function insert($table, array $values = array()) { - if (empty($values)) { - return false; - } - // column names are specified as array keys - $cols = array_keys($values); - - // build the statement - $query = 'INSERT INTO ' . $this->quoteIdentifier($table) - . '(' . implode(', ', $cols) . ') ' - . 'VALUES (' . substr(str_repeat('?, ', count($values)), 0, -2) . ')'; - - // prepare and execute the statement - $this->execute($query, array_values($values)); - - return true; - } - - /** - * Set the charset on the current connection - * - * @param string charset - * - * @return void - */ - public function setCharset($charset) - { - - } - - /** - * Set the date/time format for the current connection - * - * @param string time format - * - * @return void - */ - public function setDateFormat($format = null) - { - } - - /** - * fetchAll - * - * @param string $statement sql query to be executed - * @param array $params prepared statement params - * @return array - */ - public function fetchAll($statement, array $params = array()) - { - return $this->execute($statement, $params)->fetchAll(PDO::FETCH_ASSOC); - } - - /** - * fetchOne - * - * @param string $statement sql query to be executed - * @param array $params prepared statement params - * @param int $colnum 0-indexed column number to retrieve - * @return mixed - */ - public function fetchOne($statement, array $params = array(), $colnum = 0) - { - return $this->execute($statement, $params)->fetchColumn($colnum); - } - - /** - * fetchRow - * - * @param string $statement sql query to be executed - * @param array $params prepared statement params - * @return array - */ - public function fetchRow($statement, array $params = array()) - { - return $this->execute($statement, $params)->fetch(PDO::FETCH_ASSOC); - } - - /** - * fetchArray - * - * @param string $statement sql query to be executed - * @param array $params prepared statement params - * @return array - */ - public function fetchArray($statement, array $params = array()) - { - return $this->execute($statement, $params)->fetch(PDO::FETCH_NUM); - } - - /** - * fetchColumn - * - * @param string $statement sql query to be executed - * @param array $params prepared statement params - * @param int $colnum 0-indexed column number to retrieve - * @return array - */ - public function fetchColumn($statement, array $params = array(), $colnum = 0) - { - return $this->execute($statement, $params)->fetchAll(PDO::FETCH_COLUMN, $colnum); - } - - /** - * fetchAssoc - * - * @param string $statement sql query to be executed - * @param array $params prepared statement params - * @return array - */ - public function fetchAssoc($statement, array $params = array()) - { - return $this->execute($statement, $params)->fetchAll(PDO::FETCH_ASSOC); - } - - /** - * fetchBoth - * - * @param string $statement sql query to be executed - * @param array $params prepared statement params - * @return array - */ - public function fetchBoth($statement, array $params = array()) - { - return $this->execute($statement, $params)->fetchAll(PDO::FETCH_BOTH); - } - - /** - * query - * queries the database using Doctrine Query Language - * returns a collection of Doctrine_Record objects - * - * - * $users = $conn->query('SELECT u.* FROM User u'); - * - * $users = $conn->query('SELECT u.* FROM User u WHERE u.name LIKE ?', array('someone')); - * - * - * @param string $query DQL query - * @param array $params query parameters - * @see Doctrine_Query - * @return Doctrine_Collection Collection of Doctrine_Record objects - */ - public function query($query, array $params = array()) - { - $parser = new Doctrine_Query($this); - - return $parser->query($query, $params); - } - - /** - * query - * queries the database using Doctrine Query Language and returns - * the first record found - * - * - * $user = $conn->queryOne('SELECT u.* FROM User u WHERE u.id = ?', array(1)); - * - * $user = $conn->queryOne('SELECT u.* FROM User u WHERE u.name LIKE ? AND u.password = ?', - * array('someone', 'password') - * ); - * - * - * @param string $query DQL query - * @param array $params query parameters - * @see Doctrine_Query - * @return Doctrine_Record|false Doctrine_Record object on success, - * boolean false on failure - */ - public function queryOne($query, array $params = array()) - { - $parser = new Doctrine_Query($this); - - $coll = $parser->query($query, $params); - if ( ! $coll->contains(0)) { - return false; - } - return $coll[0]; - } - - /** - * 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); - } - - /** - * standaloneQuery - * - * @param string $query sql query - * @param array $params query parameters - * - * @return PDOStatement|Doctrine_Adapter_Statement - */ - public function standaloneQuery($query, $params = array()) - { - return $this->execute($query, $params); - } - - /** - * execute - * @param string $query sql query - * @param array $params query parameters - * - * @return PDOStatement|Doctrine_Adapter_Statement - */ - public function execute($query, array $params = array()) - { - try { - if ( ! empty($params)) { - $stmt = $this->dbh->prepare($query); - $stmt->execute($params); - return $stmt; - } else { - return $this->dbh->query($query); - } - } catch(Doctrine_Adapter_Exception $e) { - } catch(PDOException $e) { } - - $this->rethrowException($e); - } - - /** - * exec - * @param string $query sql query - * @param array $params query parameters - * - * @return PDOStatement|Doctrine_Adapter_Statement - */ - public function exec($query, array $params = array()) { - try { - if ( ! empty($params)) { - $stmt = $this->dbh->prepare($query); - $stmt->execute($params); - return $stmt->rowCount(); - } else { - return $this->dbh->exec($query); - } - } catch(Doctrine_Adapter_Exception $e) { - } catch(PDOException $e) { } - - $this->rethrowException($e); - } - - /** - * rethrowException - * - * @throws Doctrine_Connection_Exception - */ - private function rethrowException(Exception $e) - { - $name = 'Doctrine_Connection_' . $this->driverName . '_Exception'; - - $exc = new $name($e->getMessage(), (int) $e->getCode()); - if ( ! is_array($e->errorInfo)) { - $e->errorInfo = array(null, null, null, null); - } - $exc->processErrorInfo($e->errorInfo); - - throw $exc; - } - - /** - * hasTable - * whether or not this connection has table $name initialized - * - * @param mixed $name - * @return boolean - */ - public function hasTable($name) - { - return isset($this->tables[$name]); - } - - /** - * returns a table object for given component name - * - * @param string $name component name - * @return object Doctrine_Table - */ - public function getTable($name, $allowExport = true) - { - if (isset($this->tables[$name])) { - return $this->tables[$name]; - } - $class = $name . 'Table'; - - if (class_exists($class) && in_array('Doctrine_Table', class_parents($class))) { - $table = new $class($name, $this); - } else { - $table = new Doctrine_Table($name, $this); - } - - $this->tables[$name] = $table; - - if ($allowExport) { - - // the following is an algorithm for loading all - // the related tables for all loaded tables - - $next = count($this->tables); - $prev = count($this->exported); - $stack = $this->exported; - while ($prev < $next) { - $prev = count($this->tables); - - foreach($this->tables as $name => $tableObject) { - if (isset($stack[$name])) { - continue; - } else { - $stack[$name] = true; - } - - $tableObject->getRelations(); - - //$this->getTable('RelationTestChild')->getRelation('Children'); - } - $next = count($this->tables); - } - - - // when all the tables are loaded we build the array in which the order of the tables is - // relationally correct so that then those can be created in the given order) - - $names = array_keys($this->tables); - - $names = $this->unitOfWork->buildFlushTree($names); - - foreach($names as $name) { - $tableObject = $this->tables[$name]; - - if (isset($this->exported[$name])) { - continue; - } - - if ($tableObject->getAttribute(Doctrine::ATTR_EXPORT) & Doctrine::EXPORT_TABLES) { - - $tableObject->export(); - } - $this->exported[$name] = true; - } - } - - return $table; - } - - /** - * returns an array of all initialized tables - * - * @return array - */ - public function getTables() - { - return $this->tables; - } - - /** - * returns an iterator that iterators through all - * initialized table objects - * - * - * foreach ($conn as $index => $table) { - * print $table; // get a string representation of each table object - * } - * - * - * @return ArrayIterator SPL ArrayIterator object - */ - public function getIterator() - { - return new ArrayIterator($this->tables); - } - - /** - * returns the count of initialized table objects - * - * @return integer - */ - public function count() - { - return count($this->tables); - } - - /** - * addTable - * adds a Doctrine_Table object into connection registry - * - * @param $objTable a Doctrine_Table object to be added into 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 - * - * create creates a record - * @param string $name component name - * @return Doctrine_Record Doctrine_Record object - */ - public function create($name) - { - return $this->getTable($name)->create(); - } - - /** - * flush - * saves all the records from all tables - * this operation is isolated using a transaction - * - * @throws PDOException if something went wrong at database level - * @return void - */ - public function flush() - { - $this->beginTransaction(); - $this->unitOfWork->saveAll(); - $this->commit(); - } - - /** - * clear - * clears all repositories - * - * @return void - */ - public function clear() - { - foreach ($this->tables as $k => $table) { - $table->getRepository()->evictAll(); - $table->clear(); - } - } - - /** - * evictTables - * evicts all tables - * - * @return void - */ - public function evictTables() - { - $this->tables = array(); - $this->exported = array(); - } - - /** - * close - * closes the connection - * - * @return void - */ - public function close() - { - $this->getAttribute(Doctrine::ATTR_LISTENER)->onPreClose($this); - - $this->clear(); - - $this->getAttribute(Doctrine::ATTR_LISTENER)->onClose($this); - } - - /** - * get the current transaction nesting level - * - * @return integer - */ - public function getTransactionLevel() - { - return $this->transaction->getTransactionLevel(); - } - - /** - * beginTransaction - * starts a new transaction - * - * this method can be listened by onPreBeginTransaction and onBeginTransaction - * listener methods - * - * @return void - */ - public function beginTransaction() - { - $this->transaction->beginTransaction(); - } - - /** - * commits the current transaction - * if lockmode is optimistic this method starts a transaction - * and commits it instantly - * - * @return void - */ - public function commit() - { - $this->transaction->commit(); - } - - /** - * rollback - * rolls back all transactions - * - * this method also listens to onPreTransactionRollback and onTransactionRollback - * eventlisteners - * - * @return void - */ - public function rollback() - { - $this->transaction->rollback(); - } - - /** - * saves the given record - * - * @param Doctrine_Record $record - * @return void - */ - public function save(Doctrine_Record $record) - { - $record->getTable()->getAttribute(Doctrine::ATTR_LISTENER)->onPreSave($record); - - switch ($record->state()) { - case Doctrine_Record::STATE_TDIRTY: - $this->unitOfWork->insert($record); - break; - case Doctrine_Record::STATE_DIRTY: - case Doctrine_Record::STATE_PROXY: - $this->unitOfWork->update($record); - break; - case Doctrine_Record::STATE_CLEAN: - case Doctrine_Record::STATE_TCLEAN: - // do nothing - break; - }; - - $record->getTable()->getAttribute(Doctrine::ATTR_LISTENER)->onSave($record); - } - - /** - * 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 - */ - public function delete(Doctrine_Record $record) - { - if ( ! $record->exists()) { - return false; - } - $this->beginTransaction(); - - $record->getTable()->getListener()->onPreDelete($record); - - $this->unitOfWork->deleteComposites($record); - - $this->transaction->addDelete($record); - - $record->getTable()->getListener()->onDelete($record); - - $this->commit(); - - return true; - } - - /** - * returns a string representation of this object - * @return string - */ - public function __toString() - { - return Doctrine_Lib::getConnectionAsString($this); - } -} - diff --git a/draft/new-core/Hydrate.php b/draft/new-core/Hydrate.php deleted file mode 100644 index 65e198a5b..000000000 --- a/draft/new-core/Hydrate.php +++ /dev/null @@ -1,1054 +0,0 @@ -. - */ - -/** - * Doctrine_Hydrate is a base class for Doctrine_RawSql and Doctrine_Query. - * Its purpose is to populate object graphs. - * - * - * @package Doctrine - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @category Object Relational Mapping - * @link www.phpdoctrine.com - * @since 1.0 - * @version $Revision: 1564 $ - * @author Konsta Vesterinen - */ -class Doctrine_Hydrate implements Serializable -{ - /** - * QUERY TYPE CONSTANTS - */ - - /** - * constant for SELECT queries - */ - const SELECT = 0; - - /** - * constant for DELETE queries - */ - const DELETE = 1; - - /** - * constant for UPDATE queries - */ - const UPDATE = 2; - - /** - * constant for INSERT queries - */ - const INSERT = 3; - - /** - * constant for CREATE queries - */ - const CREATE = 4; - - /** - * @var array $params query input parameters - */ - protected $_params = array(); - - /** - * @var Doctrine_Connection $conn Doctrine_Connection object - */ - protected $_conn; - - /** - * @var Doctrine_View $_view Doctrine_View object, when set this object will use the - * the query given by the view object for object population - */ - protected $_view; - - /** - * @var array $_aliasMap two dimensional array containing the map for query aliases - * Main keys are component aliases - * - * table table object associated with given alias - * - * relation the relation object owned by the parent - * - * parent the alias of the parent - * - * agg the aggregates of this component - */ - protected $_aliasMap = array(); - - /** - * - */ - protected $pendingAggregates = array(); - - /** - * @var array $aggregateMap an array containing all aggregate aliases, keys as dql aliases - * and values as sql aliases - */ - protected $aggregateMap = array(); - - /** - * @var array $_options an array of options - */ - protected $_options = array( - 'fetchMode' => Doctrine::FETCH_RECORD, - 'parserCache' => false, - 'resultSetCache' => false, - ); - - /** - * @var array $parts SQL query string parts - */ - protected $parts = array( - 'select' => array(), - 'distinct' => false, - 'forUpdate' => false, - 'from' => array(), - 'set' => array(), - 'join' => array(), - 'where' => array(), - 'groupby' => array(), - 'having' => array(), - 'orderby' => array(), - 'limit' => false, - 'offset' => false, - ); - - /** - * @var integer $type the query type - * - * @see Doctrine_Query::* constants - */ - protected $type = self::SELECT; - - protected $_cache; - - protected $_tableAliases = array(); - - /** - * @var array $_tableAliasSeeds A simple array keys representing table aliases and values - * as table alias seeds. The seeds are used for generating short table - * aliases. - */ - protected $_tableAliasSeeds = array(); - - /** - * constructor - * - * @param Doctrine_Connection|null $connection - */ - public function __construct($connection = null) - { - if ( ! ($connection instanceof Doctrine_Connection)) { - $connection = Doctrine_Manager::getInstance()->getCurrentConnection(); - } - $this->_conn = $connection; - } - - public function getSql() - { - return $this->getQuery(); - } - public function setCache(Doctrine_Cache_Interface $cache) - { - $this->_cache = $cache; - } - public function getCache() - { - return $this->_cache; - } - - /** - * serialize - * this method is automatically called when this Doctrine_Hydrate is serialized - * - * @return array an array of serialized properties - */ - public function serialize() - { - $vars = get_object_vars($this); - - } - - /** - * unseralize - * this method is automatically called everytime a Doctrine_Hydrate object is unserialized - * - * @param string $serialized Doctrine_Record as serialized string - * @return void - */ - public function unserialize($serialized) - { - - } - - /** - * generateNewTableAlias - * generates a new alias from given table alias - * - * @param string $tableAlias table alias from which to generate the new alias from - * @return string the created table alias - */ - public function generateNewTableAlias($tableAlias) - { - if (isset($this->_tableAliases[$tableAlias])) { - // generate a new alias - $name = substr($tableAlias, 0, 1); - $i = ((int) substr($tableAlias, 1)); - - if ($i == 0) { - $i = 1; - } - - $newIndex = ($this->_tableAliasSeeds[$name] + $i); - - return $name . $newIndex; - } - - return $alias; - } - - /** - * hasTableAlias - * whether or not this object has given tableAlias - * - * @param string $tableAlias the table alias to be checked - * @return boolean true if this object has given alias, otherwise false - */ - public function hasTableAlias($tableAlias) - { - return (isset($this->_tableAliases[$tableAlias])); - } - - /** - * getComponentAlias - * get component alias associated with given table alias - * - * @param string $tableAlias the table alias that identifies the component alias - * @return string component alias - */ - public function getComponentAlias($tableAlias) - { - if ( ! isset($this->_tableAliases[$tableAlias])) { - throw new Doctrine_Hydrate_Exception('Unknown table alias ' . $tableAlias); - } - return $this->_tableAliases[$tableAlias]; - } - - /** - * getTableAliasSeed - * returns the alias seed for given table alias - * - * @param string $tableAlias table alias that identifies the alias seed - * @return integer table alias seed - */ - public function getTableAliasSeed($tableAlias) - { - if ( ! isset($this->_tableAliasSeeds[$tableAlias])) { - return 0; - } - return $this->_tableAliasSeeds[$tableAlias]; - } - - /** - * generateTableAlias - * generates a table alias from given table name and associates - * it with given component alias - * - * @param string $componentAlias the component alias to be associated with generated table alias - * @param string $tableName the table name from which to generate the table alias - * @return string the generated table alias - */ - public function generateTableAlias($componentAlias, $tableName) - { - $char = strtolower(substr($tableName, 0, 1)); - - $alias = $char; - - if ( ! isset($this->_tableAliasSeeds[$alias])) { - $this->_tableAliasSeeds[$alias] = 1; - } - while (isset($this->_tableAliases[$alias])) { - $alias = $char . ++$this->_tableAliasSeeds[$alias]; - } - - $this->_tableAliases[$alias] = $componentAlias; - - return $alias; - } - - /** - * getTableAliases - * returns all table aliases - * - * @return array table aliases as an array - */ - public function getTableAliases() - { - return $this->_tableAliases; - } - - /** - * addTableAlias - * adds an alias for table and associates it with given component alias - * - * @param string $componentAlias the alias for the query component associated with given tableAlias - * @param string $tableAlias the table alias to be added - * @return Doctrine_Hydrate - */ - public function addTableAlias($tableAlias, $componentAlias) - { - $this->_tableAliases[$tableAlias] = $componentAlias; - - return $this; - } - - /** - * getTableAlias - * some database such as Oracle need the identifier lengths to be < ~30 chars - * hence Doctrine creates as short identifier aliases as possible - * - * this method is used for the creation of short table aliases, its also - * smart enough to check if an alias already exists for given component (componentAlias) - * - * @param string $componentAlias the alias for the query component to search table alias for - * @param string $tableName the table name from which the table alias is being created - * @return string the generated / fetched short alias - */ - public function getTableAlias($componentAlias, $tableName = null) - { - $alias = array_search($componentAlias, $this->_tableAliases); - - if ($alias !== false) { - return $alias; - } - - if ($tableName === null) { - throw new Doctrine_Hydrate_Exception("Couldn't get short alias for " . $componentAlias); - } - - return $this->generateTableAlias($componentAlias, $tableName); - } - - /** - * addQueryPart - * adds a query part in the query part array - * - * @param string $name the name of the query part to be added - * @param string $part query part string - * @throws Doctrine_Hydrate_Exception if trying to add unknown query part - * @return Doctrine_Hydrate this object - */ - public function addQueryPart($name, $part) - { - if ( ! isset($this->parts[$name])) { - throw new Doctrine_Hydrate_Exception('Unknown query part ' . $name); - } - $this->parts[$name][] = $part; - - return $this; - } - - /** - * setQueryPart - * sets a query part in the query part array - * - * @param string $name the name of the query part to be set - * @param string $part query part string - * @throws Doctrine_Hydrate_Exception if trying to set unknown query part - * @return Doctrine_Hydrate this object - */ - public function getQueryPart($part) - { - if ( ! isset($this->parts[$part])) { - throw new Doctrine_Hydrate_Exception('Unknown query part ' . $part); - } - - return $this->parts[$part]; - } - - /** - * removeQueryPart - * removes a query part from the query part array - * - * @param string $name the name of the query part to be removed - * @throws Doctrine_Hydrate_Exception if trying to remove unknown query part - * @return Doctrine_Hydrate this object - */ - public function removeQueryPart($name) - { - if (isset($this->parts[$name])) { - if ($name == 'limit' || $name == 'offset') { - $this->parts[$name] = false; - } else { - $this->parts[$name] = array(); - } - } else { - throw new Doctrine_Hydrate_Exception('Unknown query part ' . $part); - } - return $this; - } - - /** - * setQueryPart - * sets a query part in the query part array - * - * @param string $name the name of the query part to be set - * @param string $part query part string - * @throws Doctrine_Hydrate_Exception if trying to set unknown query part - * @return Doctrine_Hydrate this object - */ - public function setQueryPart($name, $part) - { - if ( ! isset($this->parts[$name])) { - throw new Doctrine_Hydrate_Exception('Unknown query part ' . $name); - } - - if ($name !== 'limit' && $name !== 'offset') { - $this->parts[$name] = array($part); - } else { - $this->parts[$name] = $part; - } - - return $this; - } - - /** - * getAliasDeclaration - * get the declaration for given component alias - * - * @param string $componentAlias the component alias the retrieve the declaration from - * @return array the alias declaration - */ - public function getAliasDeclaration($componentAlias) - { - if ( ! isset($this->_aliasMap[$componentAlias])) { - throw new Doctrine_Hydrate_Exception('Unknown component alias ' . $componentAlias); - } - - return $this->_aliasMap[$componentAlias]; - } - - /** - * copyAliases - * copy aliases from another Hydrate object - * - * this method is needed by DQL subqueries which need the aliases - * of the parent query - * - * @param Doctrine_Hydrate $query the query object from which the - * aliases are copied from - * @return Doctrine_Hydrate this object - */ - public function copyAliases(Doctrine_Hydrate $query) - { - $this->_tableAliases = $query->_tableAliases; - - return $this; - } - - /** - * createSubquery - * creates a subquery - * - * @return Doctrine_Hydrate - */ - public function createSubquery() - { - $class = get_class($this); - $obj = new $class(); - - // copy the aliases to the subquery - $obj->copyAliases($this); - - // this prevents the 'id' being selected, re ticket #307 - $obj->isSubquery(true); - - return $obj; - } - - /** - * limitSubqueryUsed - * whether or not limit subquery was used - * - * @return boolean - */ - public function isLimitSubqueryUsed() - { - return false; - } - - /** - * clear - * resets all the variables - * - * @return void - */ - protected function clear() - { - $this->parts = array( - 'select' => array(), - 'distinct' => false, - 'forUpdate' => false, - 'from' => array(), - 'set' => array(), - 'join' => array(), - 'where' => array(), - 'groupby' => array(), - 'having' => array(), - 'orderby' => array(), - 'limit' => false, - 'offset' => false, - ); - $this->inheritanceApplied = false; - } - - /** - * getConnection - * - * @return Doctrine_Connection - */ - public function getConnection() - { - return $this->_conn; - } - - /** - * setView - * sets a database view this query object uses - * this method should only be called internally by doctrine - * - * @param Doctrine_View $view database view - * @return void - */ - public function setView(Doctrine_View $view) - { - $this->_view = $view; - } - - /** - * getView - * returns the view associated with this query object (if any) - * - * @return Doctrine_View the view associated with this query object - */ - public function getView() - { - return $this->_view; - } - - /** - * getParams - * - * @return array - */ - public function getParams() - { - return $this->_params; - } - - /** - * setParams - * - * @param array $params - */ - public function setParams(array $params = array()) { - $this->_params = $params; - } - public function convertEnums($params) - { - return $params; - } - - /** - * setAliasMap - * sets the whole component alias map - * - * @param array $map alias map - * @return Doctrine_Hydrate this object - */ - public function setAliasMap(array $map) - { - $this->_aliasMap = $map; - - return $this; - } - - /** - * getAliasMap - * returns the component alias map - * - * @return array component alias map - */ - public function getAliasMap() - { - return $this->_aliasMap; - } - - /** - * mapAggregateValues - * map the aggregate values of given dataset row to a given record - * - * @param Doctrine_Record $record - * @param array $row - * @return Doctrine_Record - */ - public function mapAggregateValues($record, array $row, $alias) - { - $found = false; - // aggregate values have numeric keys - if (isset($row[0])) { - // map each aggregate value - foreach ($row as $index => $value) { - $agg = false; - - - if (isset($this->_aliasMap[$alias]['agg'][$index])) { - $agg = $this->_aliasMap[$alias]['agg'][$index]; - } - - if (is_array($record)) { - $record[$agg] = $value; - } else { - $record->mapValue($agg, $value); - } - $found = true; - } - } - return $found; - } - public function getCachedForm(array $resultSet) - { - $map = ''; - - foreach ($this->getAliasMap() as $k => $v) { - if ( ! isset($v['parent'])) { - $map[$k][] = $v['table']->getComponentName(); - } else { - $map[$k][] = $v['parent'] . '.' . $v['relation']->getAlias(); - } - if (isset($v['agg'])) { - $map[$k][] = $v['agg']; - } - } - - return serialize(array($resultSet, $map, $this->getTableAliases())); - } - public function _execute($params, $return = Doctrine::FETCH_RECORD) - { - $params = $this->_conn->convertBooleans(array_merge($this->_params, $params)); - $params = $this->convertEnums($params); - - if ( ! $this->_view) { - $query = $this->getQuery($params); - } else { - $query = $this->_view->getSelectSql(); - } - - if ($this->isLimitSubqueryUsed() && - $this->_conn->getDBH()->getAttribute(Doctrine::ATTR_DRIVER_NAME) !== 'mysql') { - - $params = array_merge($params, $params); - } - - if ($this->type !== self::SELECT) { - return $this->_conn->exec($query, $params); - } - - $stmt = $this->_conn->execute($query, $params); - return $stmt; - } - - /** - * execute - * executes the query and populates the data set - * - * @param string $params - * @return Doctrine_Collection the root collection - */ - public function execute($params = array(), $return = Doctrine::FETCH_RECORD) - { - if ($this->_cache) { - $dql = $this->getDql(); - // calculate hash for dql query - $hash = strlen($dql) . md5($dql . var_export($params, true)); - - $cached = $this->_cache->fetch($hash); - - if ($cached === null) { - // cache miss - $stmt = $this->_execute($params, $return); - $array = $this->parseData2($stmt); - - $cached = $this->getCachedForm($array); - - $this->_cache->save($hash, $cached); - } else { - $cached = unserialize($cached); - $this->_tableAliases = $cached[2]; - $array = $cached[0]; - - $map = array(); - foreach ($cached[1] as $k => $v) { - $e = explode('.', $v[0]); - if (count($e) === 1) { - $map[$k]['table'] = $this->_conn->getTable($e[0]); - } else { - $map[$k]['parent'] = $e[0]; - $map[$k]['relation'] = $map[$e[0]]['table']->getRelation($e[1]); - $map[$k]['table'] = $map[$k]['relation']->getTable(); - } - if (isset($v[1])) { - $map[$k]['agg'] = $v[1]; - } - } - $this->_aliasMap = $map; - } - } else { - $stmt = $this->_execute($params, $return); - - $array = $this->parseData2($stmt, $return); - } - return $array; - } - - /** - * getType - * - * returns the type of this query object - * by default the type is Doctrine_Hydrate::SELECT but if update() or delete() - * are being called the type is Doctrine_Hydrate::UPDATE and Doctrine_Hydrate::DELETE, - * respectively - * - * @see Doctrine_Hydrate::SELECT - * @see Doctrine_Hydrate::UPDATE - * @see Doctrine_Hydrate::DELETE - * - * @return integer return the query type - */ - public function getType() - { - return $this->type; - } - - /** - * applyInheritance - * applies column aggregation inheritance to DQL / SQL query - * - * @return string - */ - public function applyInheritance() - { - // get the inheritance maps - $array = array(); - - foreach ($this->_aliasMap as $componentAlias => $data) { - $tableAlias = $this->getTableAlias($componentAlias); - $array[$tableAlias][] = $data['table']->inheritanceMap; - } - - // apply inheritance maps - $str = ''; - $c = array(); - - $index = 0; - foreach ($array as $tableAlias => $maps) { - $a = array(); - - // don't use table aliases if the query isn't a select query - if ($this->type !== Doctrine_Query::SELECT) { - $tableAlias = ''; - } else { - $tableAlias .= '.'; - } - - foreach ($maps as $map) { - $b = array(); - foreach ($map as $field => $value) { - if ($index > 0) { - $b[] = '(' . $tableAlias . $field . ' = ' . $value - . ' OR ' . $tableAlias . $field . ' IS NULL)'; - } else { - $b[] = $tableAlias . $field . ' = ' . $value; - } - } - - if ( ! empty($b)) { - $a[] = implode(' AND ', $b); - } - } - - if ( ! empty($a)) { - $c[] = implode(' AND ', $a); - } - $index++; - } - - $str .= implode(' AND ', $c); - - return $str; - } - - /** - * parseData - * parses the data returned by statement object - * - * This is method defines the core of Doctrine object population algorithm - * hence this method strives to be as fast as possible - * - * The key idea is the loop over the rowset only once doing all the needed operations - * within this massive loop. - * - * @param mixed $stmt - * @return array - */ - public function parseData2($stmt, $return) - { - - $cache = array(); - $rootMap = reset($this->_aliasMap); - $rootAlias = key($this->_aliasMap); - $componentName = $rootMap['table']->getComponentName(); - $index = 0; - $incr = true; - $lastAlias = ''; - $currData = array(); - - if ($return === Doctrine::FETCH_ARRAY) { - $driver = new Doctrine_Hydrate_Array(); - } else { - $driver = new Doctrine_Hydrate_Record(); - } - - $array = $driver->getElementCollection($componentName); - $identifiable = array(); - - while ($data = $stmt->fetch(PDO::FETCH_ASSOC)) { - $parse = true; - - foreach ($data as $key => $value) { - if ( ! isset($cache[$key])) { - $e = explode('__', $key); - $cache[$key]['field'] = $field = strtolower(array_pop($e)); - $componentAlias = $this->_tableAliases[strtolower(implode('__', $e))]; - - $cache[$key]['alias'] = $componentAlias; - - if (isset($this->_aliasMap[$componentAlias]['relation'])) { - $cache[$key]['component'] = $this->_aliasMap[$componentAlias]['relation']->getAlias(); - $cache[$key]['parent'] = $this->_aliasMap[$componentAlias]['parent']; - } else { - $cache[$key]['component'] = $this->_aliasMap[$componentAlias]['table']->getComponentName(); - } - - } - - $alias = $cache[$key]['alias']; - $component = $cache[$key]['component']; - $componentName = $this->_aliasMap[$cache[$key]['alias']]['table']->getComponentName(); - $table = $this->_aliasMap[$cache[$key]['alias']]['table']; - - - if ( ! isset($currData[$alias])) { - $currData[$alias] = array(); - } - if ( ! isset($prevData[$alias])) { - $prevData[$alias] = array(); - } - if ( ! isset($prevElement[$alias])) { - $prevElement[$alias] = array(); - } - - if ( ! isset($prev[$alias])) { - $prev[$alias] = array(); - } - - - $skip = false; - if (($alias !== $lastAlias || $parse) && ! empty($currData[$alias])) { - - // component changed - $element = $driver->getElement($currData[$alias], $componentName); - - // map aggregate values (if any) - $this->mapAggregateValues($element, $currData[$alias], $alias); - - if ($currData[$alias] !== $prevData[$alias] || $element !== $prevElement[$alias]) { - - if ($alias === $rootAlias) { - // dealing with root component - - $index = $driver->search($element, $array); - if ($index === false) { - $array[] = $element; - } - - $coll =& $array; - } else { - $parent = $cache[$key]['parent']; - $relation = $this->_aliasMap[$cache[$key]['alias']]['relation']; - // check the type of the relation - if ( ! $relation->isOneToOne()) { - // initialize the collection - $driver->initRelated($prev[$parent], $component); - - // append element - if (isset($identifiable[$alias])) { - $index = $driver->search($element, $prev[$parent][$component]); - - if ($index === false) { - $prev[$parent][$component][] = $element; - } - } - // register collection for later snapshots - $driver->registerCollection($prev[$parent][$component]); - } else { - $prev[$parent][$component] = $element; - } - $coll =& $prev[$parent][$component]; - } - - if ($index !== false) { - $prev[$alias] =& $coll[$index]; - } else { - // first check the count (we do not want to get the last element - // of an empty collection/array) - if (count($coll) > 0) { - // check the type - if (is_array($coll)) { - end($coll); - $prev[$alias] =& $coll[key($coll)]; - } else { - $prev[$alias] = $coll->getLast(); - } - } - } - - if (isset($currData[$alias])) { - $prevData[$alias] = $currData[$alias]; - } else { - $prevData[$alias] = array(); - } - $currData[$alias] = array(); - $identifiable[$alias] = null; - - $prevElement[$alias] =& $element; - - } - } - $field = $cache[$key]['field']; - $currData[$alias][$field] = $value; - - if ($value !== null) { - $identifiable[$alias] = true; - } - $lastAlias = $alias; - $parse = false; - } - - } - $identifiable = array(); - foreach ($currData as $alias => $data) { - $table = $this->_aliasMap[$alias]['table']; - $componentName = $table->getComponentName(); - // component changed - - $element = $driver->getElement($currData[$alias], $componentName); - - // map aggregate values (if any) - $this->mapAggregateValues($element, $currData[$alias], $alias); - - if ( ! isset($prevData[$alias]) || (isset($currData[$alias]) && $currData[$alias] !== $prevData[$alias]) - || $element !== $prevElement[$alias]) { - - - if ($alias === $rootAlias) { - // dealing with root component - $index = $driver->search($element, $array); - if ($index === false) { - $array[] = $element; - } - $coll =& $array; - } else { - $parent = $this->_aliasMap[$alias]['parent']; - $relation = $this->_aliasMap[$alias]['relation']; - $componentAlias = $relation->getAlias(); - - // check the type of the relation - if ( ! $relation->isOneToOne()) { - // initialize the collection - $driver->initRelated($prev[$parent], $componentAlias); - - // append element - if (isset($identifiable[$alias])) { - $index = $driver->search($element, $prev[$parent][$component]); - - if ($index === false) { - $prev[$parent][$componentAlias][] = $element; - } - } - // register collection for later snapshots - $driver->registerCollection($prev[$parent][$componentAlias]); - } else { - $prev[$parent][$componentAlias] = $element; - } - $coll =& $prev[$parent][$componentAlias]; - } - - if ($index !== false) { - $prev[$alias] =& $coll[$index]; - } else { - // first check the count (we do not want to get the last element - // of an empty collection/array) - if (count($coll) > 0) { - if (is_array($coll)) { - end($coll); - $prev[$alias] =& $coll[key($coll)]; - } else { - $prev[$alias] = $coll->getLast(); - } - } - } - } - if (isset($currData[$alias])) { - $prevData[$alias] = $currData[$alias]; - } else { - $prevData[$alias] = array(); - } - $currData[$alias] = array(); - unset($identifiable[$alias]); - - $prevElement[$alias] = $element; - } - - $driver->flush(); - - $stmt->closeCursor(); - return $array; - } - - /** - * @return string returns a string representation of this object - */ - public function __toString() - { - return Doctrine_Lib::formatSql($this->getQuery()); - } -} diff --git a/draft/new-core/QueryApi.php b/draft/new-core/QueryApi.php deleted file mode 100644 index e74316e16..000000000 --- a/draft/new-core/QueryApi.php +++ /dev/null @@ -1,243 +0,0 @@ -. - */ - -/** - * Doctrine_Query - * - * @package Doctrine - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @category Object Relational Mapping - * @link www.phpdoctrine.com - * @since 1.0 - * @version $Revision: 1296 $ - * @author Konsta Vesterinen - */ -class Doctrine_Query -{ - /** - * create - * returns a new Doctrine_Query object - * - * @return Doctrine_Query - */ - public static function create() - { - return new Doctrine_Query(); - } - - /** - * addSelect - * adds fields to the SELECT part of the query - * - * @param string $select DQL SELECT part - * @return Doctrine_Query - */ - public function addSelect($select) - { - return $this->getParser('select')->parse($select, true); - } - - /** - * addWhere - * adds conditions to the WHERE part of the query - * - * @param string $where DQL WHERE part - * @param mixed $params an array of parameters or a simple scalar - * @return Doctrine_Query - */ - public function addWhere($where, $params = array()) - { - if(is_array($params)) { - $this->params = array_merge($this->params, $params); - } else { - $this->params[] = $params; - } - return $this->getParser('where')->parse($where, true); - } - - /** - * addGroupBy - * adds fields to the GROUP BY part of the query - * - * @param string $groupby DQL GROUP BY part - * @return Doctrine_Query - */ - public function addGroupBy($groupby) - { - return $this->getParser('groupby')->parse($groupby, true); - } - - /** - * addHaving - * adds conditions to the HAVING part of the query - * - * @param string $having DQL HAVING part - * @return Doctrine_Query - */ - public function addHaving($having) - { - return $this->getParser('having')->parse($having, true); - } - - /** - * addOrderBy - * adds fields to the ORDER BY part of the query - * - * @param string $orderby DQL ORDER BY part - * @return Doctrine_Query - */ - public function addOrderBy($orderby) - { - return $this->getParser('orderby')->parse($orderby, true); - } - - /** - * select - * sets the SELECT part of the query - * - * @param string $select DQL SELECT part - * @return Doctrine_Query - */ - public function select($select) - { - return $this->getParser('from')->parse($select); - } - - /** - * from - * sets the FROM part of the query - * - * @param string $from DQL FROM part - * @return Doctrine_Query - */ - public function from($from) - { - return $this->getParser('from')->parse($from); - } - - /** - * innerJoin - * appends an INNER JOIN to the FROM part of the query - * - * @param string $join DQL INNER JOIN - * @return Doctrine_Query - */ - public function innerJoin($join) - { - return $this->getParser('from')->parse('INNER JOIN ' . $join); - } - - /** - * leftJoin - * appends a LEFT JOIN to the FROM part of the query - * - * @param string $join DQL LEFT JOIN - * @return Doctrine_Query - */ - public function leftJoin($join) - { - return $this->getParser('from')->parse('LERT JOIN ' . $join); - } - - /** - * groupBy - * sets the GROUP BY part of the query - * - * @param string $groupby DQL GROUP BY part - * @return Doctrine_Query - */ - public function groupBy($groupby) - { - return $this->getParser('groupby')->parse($groupby); - } - - /** - * where - * sets the WHERE part of the query - * - * @param string $join DQL WHERE part - * @param mixed $params an array of parameters or a simple scalar - * @return Doctrine_Query - */ - public function where($where, $params = array()) - { - if(is_array($params)) { - $this->params = array_merge($this->params, $params); - } else { - $this->params[] = $params; - } - return $this->getParser('where')->parse($where); - } - - /** - * having - * sets the HAVING part of the query - * - * @param string $having DQL HAVING part - * @param mixed $params an array of parameters or a simple scalar - * @return Doctrine_Query - */ - public function having($having, $params) - { - if(is_array($params)) { - $this->params = array_merge($this->params, $params); - } else { - $this->params[] = $params; - } - return $this->getParser('having')->parse($having); - } - - /** - * orderBy - * sets the ORDER BY part of the query - * - * @param string $groupby DQL ORDER BY part - * @return Doctrine_Query - */ - public function orderBy($dql) - { - return $this->getParser('orderby')->parse($dql); - } - - /** - * limit - * sets the DQL query limit - * - * @param integer $limit limit to be used for limiting the query results - * @return Doctrine_Query - */ - public function limit($limit) - { - return $this->getParser('limit')->parse($dql); - } - - /** - * offset - * sets the DQL query offset - * - * @param integer $offset offset to be used for paginating the query - * @return Doctrine_Query - */ - public function offset($dql) - { - return $this->getParser('offset')->parse($dql); - } -} diff --git a/draft/new-core/RawSql.php b/draft/new-core/RawSql.php deleted file mode 100644 index 19781a944..000000000 --- a/draft/new-core/RawSql.php +++ /dev/null @@ -1,254 +0,0 @@ -. - */ -Doctrine::autoload('Doctrine_Hydrate'); -/** - * Doctrine_RawSql - * - * @package Doctrine - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @category Object Relational Mapping - * @link www.phpdoctrine.com - * @since 1.0 - * @version $Revision: 1181 $ - * @author Konsta Vesterinen - */ -class Doctrine_RawSql extends Doctrine_Hydrate -{ - /** - * @var array $fields - */ - private $fields; - - /** - * __call - * method overloader - * - * @param string $name - * @param array $args - * @return Doctrine_RawSql - */ - public function __call($name, $args) - { - if ( ! isset($this->parts[$name])) { - throw new Doctrine_RawSql_Exception("Unknown overload method $name. Availible overload methods are ".implode(" ",array_keys($this->parts))); - } - if ($name == 'select') { - preg_match_all('/{([^}{]*)}/U', $args[0], $m); - - $this->fields = $m[1]; - $this->parts["select"] = array(); - } else { - $this->parts[$name][] = $args[0]; - } - return $this; - } - - /** - * get - */ - public function get($name) - { - if ( ! isset($this->parts[$name])) { - throw new Doctrine_RawSql_Exception('Unknown query part '.$name); - } - return $this->parts[$name]; - } - - /** - * parseQuery - * - * @param string $query - * @return Doctrine_RawSql - */ - public function parseQuery($query) - { - preg_match_all('/{([^}{]*)}/U', $query, $m); - - $this->fields = $m[1]; - $this->clear(); - - $e = Doctrine_Query::sqlExplode($query,' '); - - foreach ($e as $k => $part) { - $low = strtolower($part); - switch (strtolower($part)) { - case 'select': - case 'from': - case 'where': - case 'limit': - case 'offset': - case 'having': - $p = $low; - if ( ! isset($parts[$low])) { - $parts[$low] = array(); - } - break; - case 'order': - case 'group': - $i = ($k + 1); - if (isset($e[$i]) && strtolower($e[$i]) === 'by') { - $p = $low; - $p .= 'by'; - $parts[$low.'by'] = array(); - - } else { - $parts[$p][] = $part; - } - break; - case 'by': - continue; - default: - if ( ! isset($parts[$p][0])) { - $parts[$p][0] = $part; - } else { - $parts[$p][0] .= ' '.$part; - } - } - } - - $this->parts = $parts; - $this->parts['select'] = array(); - - return $this; - } - - /** - * getQuery - * - * - * @return string - */ - public function getQuery() - { - foreach ($this->fields as $field) { - $e = explode(".", $field); - if ( ! isset($e[1])) { - throw new Doctrine_RawSql_Exception("All selected fields in Sql query must be in format tableAlias.fieldName"); - } - if ( ! isset($this->tables[$e[0]])) { - try { - $this->addComponent($e[0], ucwords($e[0])); - } catch(Doctrine_Exception $exception) { - throw new Doctrine_RawSql_Exception("The associated component for table alias $e[0] couldn't be found."); - } - } - - if ($e[1] == '*') { - foreach ($this->tables[$e[0]]->getColumnNames() as $name) { - $field = $e[0] . '.' . $name; - $this->parts['select'][$field] = $field . ' AS ' . $e[0] . '__' . $name; - } - } else { - $field = $e[0] . '.' . $e[1]; - $this->parts['select'][$field] = $field . ' AS ' . $e[0] . '__' . $e[1]; - } - } - - // force-add all primary key fields - - foreach ($this->tableAliases as $alias) { - foreach ($this->tables[$alias]->getPrimaryKeys() as $key) { - $field = $alias . '.' . $key; - if ( ! isset($this->parts['select'][$field])) { - $this->parts['select'][$field] = $field . ' AS ' . $alias . '__' . $key; - } - } - } - - $q = 'SELECT ' . implode(', ', $this->parts['select']); - - $string = $this->applyInheritance(); - if ( ! empty($string)) { - $this->parts['where'][] = $string; - } - $copy = $this->parts; - unset($copy['select']); - - $q .= ( ! empty($this->parts['from']))? ' FROM ' . implode(' ', $this->parts['from']) : ''; - $q .= ( ! empty($this->parts['where']))? ' WHERE ' . implode(' AND ', $this->parts['where']) : ''; - $q .= ( ! empty($this->parts['groupby']))? ' GROUP BY ' . implode(', ', $this->parts['groupby']) : ''; - $q .= ( ! empty($this->parts['having']))? ' HAVING ' . implode(' ', $this->parts['having']) : ''; - $q .= ( ! empty($this->parts['orderby']))? ' ORDER BY ' . implode(' ', $this->parts['orderby']) : ''; - $q .= ( ! empty($this->parts['limit']))? ' LIMIT ' . implode(' ', $this->parts['limit']) : ''; - $q .= ( ! empty($this->parts['offset']))? ' OFFSET ' . implode(' ', $this->parts['offset']) : ''; - - if ( ! empty($string)) { - array_pop($this->parts['where']); - } - return $q; - } - - /** - * getFields - * - * @return array - */ - public function getFields() - { - return $this->fields; - } - - /** - * addComponent - * - * @param string $tableAlias - * @param string $componentName - * @return Doctrine_RawSql - */ - public function addComponent($tableAlias, $componentName) - { - $e = explode('.', $componentName); - - $currPath = ''; - $table = null; - - foreach ($e as $k => $component) { - $currPath .= '.' . $component; - - if ($k == 0) { - $currPath = substr($currPath,1); - } - - if (isset($this->tableAliases[$currPath])) { - $alias = $this->tableAliases[$currPath]; - } else { - $alias = $tableAlias; - } - - if ($table) { - $tableName = $table->getAliasName($component); - } - $table = $this->conn->getTable($component); - $this->tables[$alias] = $table; - $this->tableAliases[$currPath] = $alias; - - if ($k !== 0) { - $this->joins[$alias] = $prevAlias; - } - - $prevAlias = $alias; - $prevPath = $currPath; - } - - return $this; - } - -} diff --git a/draft/new-core/Record.php b/draft/new-core/Record.php deleted file mode 100644 index 8d7be0c8c..000000000 --- a/draft/new-core/Record.php +++ /dev/null @@ -1,1693 +0,0 @@ -. - */ -Doctrine::autoload('Doctrine_Access'); -/** - * Doctrine_Record - * All record classes should inherit this super class - * - * @author Konsta Vesterinen - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @package Doctrine - * @category Object Relational Mapping - * @link www.phpdoctrine.com - * @since 1.0 - * @version $Revision: 1298 $ - */ -abstract class Doctrine_Record2 extends Doctrine_Access implements Countable, IteratorAggregate, Serializable -{ - /** - * 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; - - /** - * the following protected variables use '_' prefixes, the reason for this is to allow child - * classes call for example $this->id, $this->state for getting the values of columns named 'id' and 'state' - * rather than the values of these protected variables - */ - /** - * @var object Doctrine_Table $_table the factory that created this data access object - */ - protected $_table; - - /** - * @var Doctrine_Node_ node object - */ - protected $_node; - - /** - * @var integer $_id the primary keys of this object - */ - protected $_id = array(); - - /** - * @var array $_data the record data - */ - protected $_data = array(); - - /** - * @var array $_values the values array, aggregate values and such are mapped into this array - */ - protected $_values = array(); - - /** - * @var integer $_state the state of this record - * @see STATE_* constants - */ - protected $_state; - - /** - * @var array $_modified an array containing properties that have been modified - */ - protected $_modified = array(); - - /** - * @var Doctrine_Validator_ErrorStack error stack object - */ - protected $_errorStack; - - /** - * @var array $references an array containing all the references - */ - private $references = array(); - - /** - * @var integer $index this index is used for creating object identifiers - */ - private static $index = 1; - - /** - * @var Doctrine_Null $null a Doctrine_Null object used for extremely fast - * null value testing - */ - private static $null; - - /** - * @var integer $oid object identifier, each Record object has a unique object identifier - */ - private $oid; - - /** - * constructor - * @param Doctrine_Table|null $table a Doctrine_Table object or null, - * if null the table object is retrieved from current connection - * - * @param boolean $isNewEntry whether or not this record is transient - * - * @throws Doctrine_Connection_Exception if object is created using the new operator and there are no - * open connections - * @throws Doctrine_Record_Exception if the cleanData operation fails somehow - */ - public function __construct($table = null, $isNewEntry = false) - { - if (isset($table) && $table instanceof Doctrine_Table) { - $this->_table = $table; - $exists = ( ! $isNewEntry); - } else { - $class = get_class($this); - // get the table of this class - $this->_table = Doctrine_Manager::getInstance() - ->getTable(get_class($this)); - - $exists = false; - } - - // Check if the current connection has the records table in its registry - // If not this record is only used for creating table definition and setting up - // relations. - - if ($this->_table->getConnection()->hasTable($this->_table->getComponentName())) { - $this->oid = self::$index; - - self::$index++; - - $keys = $this->_table->getPrimaryKeys(); - - 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(); - - // get the column count - $count = count($this->_data); - - // clean data array - $this->cleanData(); - - $this->prepareIdentifiers($exists); - - if ( ! $exists) { - if ($count > 0) { - $this->_state = Doctrine_Record::STATE_TDIRTY; - } else { - $this->_state = Doctrine_Record::STATE_TCLEAN; - } - - // set the default values for this record - $this->assignDefaultValues(); - - // listen the onCreate event - $this->_table->getAttribute(Doctrine::ATTR_LISTENER)->onCreate($this); - - } else { - $this->_state = Doctrine_Record::STATE_CLEAN; - - if ($count < $this->_table->getColumnCount()) { - $this->_state = Doctrine_Record::STATE_PROXY; - } - - // listen the onLoad event - $this->_table->getAttribute(Doctrine::ATTR_LISTENER)->onLoad($this); - } - - $this->_errorStack = new Doctrine_Validator_ErrorStack(); - - $repository = $this->_table->getRepository(); - $repository->add($this); - } - $this->construct(); - } - - /** - * initNullObject - * - * @param Doctrine_Null $null - * @return void - */ - public static function initNullObject(Doctrine_Null $null) - { - self::$null = $null; - } - - /** - * @return Doctrine_Null - */ - public static function getNullObject() - { - return self::$null; - } - - /** - * setUp - * this method is used for setting up relations and attributes - * it should be implemented by child classes - * - * @return void - */ - public function setUp() - { } - /** - * construct - * Empty tempalte method to provide concrete Record classes with the possibility - * to hook into the constructor procedure - * - * @return void - */ - public function construct() - { } - /** - * getOID - * returns the object identifier - * - * @return integer - */ - public function getOID() - { - return $this->oid; - } - - /** - * isValid - * - * @return boolean whether or not this record passes all column validations - */ - public function isValid() - { - if ( ! $this->_table->getAttribute(Doctrine::ATTR_VLD)) { - return true; - } - // Clear the stack from any previous errors. - $this->_errorStack->clear(); - - // Run validation process - $validator = new Doctrine_Validator(); - $validator->validateRecord($this); - $this->validate(); - if ($this->_state == self::STATE_TDIRTY || $this->_state == self::STATE_TCLEAN) { - $this->validateOnInsert(); - } else { - $this->validateOnUpdate(); - } - - return $this->_errorStack->count() == 0 ? true : false; - } - - /** - * Emtpy template method to provide concrete Record classes with the possibility - * to hook into the validation procedure, doing any custom / specialized - * validations that are neccessary. - */ - protected function validate() - {} - /** - * Empty tempalte method to provide concrete Record classes with the possibility - * to hook into the validation procedure only when the record is going to be - * updated. - */ - protected function validateOnUpdate() - {} - /** - * Empty tempalte method to provide concrete Record classes with the possibility - * to hook into the validation procedure only when the record is going to be - * inserted into the data store the first time. - */ - protected function validateOnInsert() - {} - /** - * getErrorStack - * - * @return Doctrine_Validator_ErrorStack returns the errorStack associated with this record - */ - public function getErrorStack() - { - return $this->_errorStack; - } - - /** - * errorStack - * assigns / returns record errorStack - * - * @param Doctrine_Validator_ErrorStack errorStack to be assigned for this record - * @return void|Doctrine_Validator_ErrorStack returns the errorStack associated with this record - */ - public function errorStack($stack = null) - { - if($stack !== null) { - if( ! ($stack instanceof Doctrine_Validator_ErrorStack)) { - throw new Doctrine_Record_Exception('Argument should be an instance of Doctrine_Validator_ErrorStack.'); - } - $this->_errorStack = $stack; - } else { - return $this->_errorStack; - } - } - - /** - * setDefaultValues - * sets the default values for records internal data - * - * @param boolean $overwrite whether or not to overwrite the already set values - * @return boolean - */ - public function assignDefaultValues($overwrite = false) - { - if ( ! $this->_table->hasDefaultValues()) { - return false; - } - foreach ($this->_data as $column => $value) { - $default = $this->_table->getDefaultValueOf($column); - - if ($default === null) - $default = self::$null; - - if ($value === self::$null || $overwrite) { - $this->_data[$column] = $default; - $this->_modified[] = $column; - $this->_state = Doctrine_Record::STATE_TDIRTY; - } - } - } - - /** - * cleanData - * this method does several things to records internal data - * - * 1. It unserializes array and object typed columns - * 2. Uncompresses gzip typed columns - * 3. Gets the appropriate enum values for enum typed columns - * 4. Initializes special null object pointer for null values (for fast column existence checking purposes) - * - * - * example: - * - * $data = array("name"=>"John","lastname"=> null, "id" => 1,"unknown" => "unknown"); - * $names = array("name", "lastname", "id"); - * $data after operation: - * $data = array("name"=>"John","lastname" => Object(Doctrine_Null)); - * - * here column 'id' is removed since its auto-incremented primary key (read-only) - * - * @throws Doctrine_Record_Exception if unserialization of array/object typed column fails or - * if uncompression of gzip typed column fails - * - * @return integer - */ - private function cleanData() - { - $tmp = $this->_data; - - $this->_data = array(); - - $count = 0; - - foreach ($this->_table->getColumnNames() as $name) { - $type = $this->_table->getTypeOf($name); - - if ( ! isset($tmp[$name])) { - $this->_data[$name] = self::$null; - } else { - switch ($type) { - case 'array': - case 'object': - if ($tmp[$name] !== self::$null) { - if (is_string($tmp[$name])) { - $value = unserialize($tmp[$name]); - - if ($value === false) - throw new Doctrine_Record_Exception('Unserialization of ' . $name . ' failed.'); - } else { - $value = $tmp[$name]; - } - $this->_data[$name] = $value; - } - break; - case 'gzip': - if ($tmp[$name] !== self::$null) { - $value = gzuncompress($tmp[$name]); - - if ($value === false) - throw new Doctrine_Record_Exception('Uncompressing of ' . $name . ' failed.'); - - $this->_data[$name] = $value; - } - break; - case 'enum': - $this->_data[$name] = $this->_table->enumValue($name, $tmp[$name]); - break; - default: - $this->_data[$name] = $tmp[$name]; - } - $count++; - } - } - - return $count; - } - - /** - * hydrate - * hydrates this object from given array - * - * @param array $data - * @return boolean - */ - public function hydrate(array $data) - { - foreach ($data as $k => $v) { - $this->_data[$k] = $v; - } - $this->cleanData(); - $this->prepareIdentifiers(); - } - - /** - * prepareIdentifiers - * prepares identifiers for later use - * - * @param boolean $exists whether or not this record exists in persistent data store - * @return void - */ - private function prepareIdentifiers($exists = true) - { - switch ($this->_table->getIdentifierType()) { - case Doctrine_Identifier::AUTO_INCREMENT: - case Doctrine_Identifier::SEQUENCE: - $name = $this->_table->getIdentifier(); - - if ($exists) { - if (isset($this->_data[$name]) && $this->_data[$name] !== self::$null) { - $this->_id[$name] = $this->_data[$name]; - } - } - - unset($this->_data[$name]); - - break; - case Doctrine_Identifier::NORMAL: - $this->_id = array(); - $name = $this->_table->getIdentifier(); - - if (isset($this->_data[$name]) && $this->_data[$name] !== self::$null) { - $this->_id[$name] = $this->_data[$name]; - } - break; - case Doctrine_Identifier::COMPOSITE: - $names = $this->_table->getIdentifier(); - - foreach ($names as $name) { - if ($this->_data[$name] === self::$null) { - $this->_id[$name] = null; - } else { - $this->_id[$name] = $this->_data[$name]; - } - } - break; - } - } - - /** - * serialize - * this method is automatically called when this Doctrine_Record is serialized - * - * @return array - */ - public function serialize() - { - $this->_table->getAttribute(Doctrine::ATTR_LISTENER)->onSleep($this); - - $vars = get_object_vars($this); - - unset($vars['references']); - unset($vars['originals']); - unset($vars['_table']); - unset($vars['_errorStack']); - - $name = $this->_table->getIdentifier(); - $this->_data = array_merge($this->_data, $this->_id); - - foreach ($this->_data as $k => $v) { - if ($v instanceof Doctrine_Record) { - unset($vars['_data'][$k]); - } elseif ($v === self::$null) { - unset($vars['_data'][$k]); - } else { - switch ($this->_table->getTypeOf($k)) { - case "array": - case "object": - $vars['_data'][$k] = serialize($vars['_data'][$k]); - break; - } - } - } - - return serialize($vars); - } - - /** - * unseralize - * this method is automatically called everytime a Doctrine_Record object is unserialized - * - * @param string $serialized Doctrine_Record as serialized string - * @throws Doctrine_Record_Exception if the cleanData operation fails somehow - * @return void - */ - public function unserialize($serialized) - { - $manager = Doctrine_Manager::getInstance(); - $connection = $manager->getConnectionForComponent(get_class($this)); - - $this->oid = self::$index; - self::$index++; - - $this->_table = $connection->getTable(get_class($this)); - - $array = unserialize($serialized); - - foreach ($array as $name => $values) { - $this->$name = $values; - } - - $this->_table->getRepository()->add($this); - - $this->cleanData(); - - $this->prepareIdentifiers($this->exists()); - - $this->_table->getAttribute(Doctrine::ATTR_LISTENER)->onWakeUp($this); - } - - /** - * getState - * returns the current state of the object - * - * @see Doctrine_Record::STATE_* constants - * @return integer - */ - public function getState() - { - return $this->_state; - } - - /** - * state - * returns / assigns the state of this record - * - * @param integer|string $state if set, this method tries to set the record state to $state - * @see Doctrine_Record::STATE_* constants - * - * @throws Doctrine_Record_State_Exception if trying to set an unknown state - * @return null|integer - */ - public function state($state = null) - { - if ($state == null) { - return $this->_state; - } - $err = false; - if (is_integer($state)) { - - if ($state >= 1 && $state <= 6) { - $this->_state = $state; - } else { - $err = true; - } - } elseif (is_string($state)) { - $upper = strtoupper($state); - switch ($upper) { - case 'DIRTY': - case 'CLEAN': - case 'TDIRTY': - case 'TCLEAN': - case 'PROXY': - case 'DELETED': - $this->_state = constant('Doctrine_Record::STATE_' . $upper); - break; - default: - $err = true; - } - } - - if ($err) { - throw new Doctrine_Record_State_Exception('Unknown record state ' . $state); - } - } - - /** - * refresh - * refresh internal data from the database - * - * @throws Doctrine_Record_Exception When the refresh operation fails (when the database row - * this record represents does not exist anymore) - * @return boolean - */ - public function refresh() - { - $id = $this->obtainIdentifier(); - if ( ! is_array($id)) { - $id = array($id); - } - if (empty($id)) { - return false; - } - $id = array_values($id); - - $query = $this->_table->getQuery()." WHERE ".implode(" = ? AND ",$this->_table->getPrimaryKeys())." = ?"; - $stmt = $this->_table->getConnection()->execute($query,$id); - - $this->_data = $stmt->fetch(PDO::FETCH_ASSOC); - - if ( ! $this->_data) - throw new Doctrine_Record_Exception('Failed to refresh. Record does not exist anymore'); - - $this->_data = array_change_key_case($this->_data, CASE_LOWER); - - $this->_modified = array(); - $this->cleanData(true); - - $this->prepareIdentifiers(); - - $this->_state = Doctrine_Record::STATE_CLEAN; - - $this->_table->getAttribute(Doctrine::ATTR_LISTENER)->onLoad($this); - - return true; - } - - /** - * factoryRefresh - * refreshes the data from outer source (Doctrine_Table) - * - * @throws Doctrine_Record_Exception When the primary key of this record doesn't match the primary key fetched from a collection - * @return void - */ - public function factoryRefresh() - { - $this->_data = $this->_table->getData(); - $old = $this->_id; - - $this->cleanData(); - - $this->prepareIdentifiers(); - - if ($this->_id != $old) { - throw new Doctrine_Record_Exception("The refreshed primary key doesn't match the one in the record memory.", Doctrine::ERR_REFRESH); - } - - $this->_state = Doctrine_Record::STATE_CLEAN; - $this->_modified = array(); - - $this->_table->getAttribute(Doctrine::ATTR_LISTENER)->onLoad($this); - } - - /** - * getTable - * returns the table object for this record - * - * @return object Doctrine_Table a Doctrine_Table object - */ - public function getTable() - { - return $this->_table; - } - - /** - * getData - * return all the internal data - * - * @return array an array containing all the properties - */ - public function getData() - { - return $this->_data; - } - - /** - * rawGet - * returns the value of a property, if the property is not yet loaded - * this method does NOT load it - * - * @param $name name of the property - * @throws Doctrine_Record_Exception if trying to get an unknown property - * @return mixed - */ - public function rawGet($name) - { - if ( ! isset($this->_data[$name])) { - throw new Doctrine_Record_Exception('Unknown property '. $name); - } - if ($this->_data[$name] === self::$null) - return null; - - return $this->_data[$name]; - } - - /** - * load - * loads all the unitialized properties from the database - * - * @return boolean - */ - public function load() - { - // only load the data from database if the Doctrine_Record is in proxy state - if ($this->_state == Doctrine_Record::STATE_PROXY) { - $this->refresh(); - - $this->_state = Doctrine_Record::STATE_CLEAN; - - return true; - } - return false; - } - - /** - * get - * returns a value of a property or a related component - * - * @param mixed $name name of the property or related component - * @param boolean $invoke whether or not to invoke the onGetProperty listener - * @throws Doctrine_Record_Exception if trying to get a value of unknown property / related component - * @return mixed - */ - public function get($name, $invoke = true) - { - $value = self::$null; - $lower = strtolower($name); - - $lower = $this->_table->getColumnName($lower); - - if (isset($this->_data[$lower])) { - // check if the property is null (= it is the Doctrine_Null object located in self::$null) - if ($this->_data[$lower] === self::$null) { - $this->load(); - } - - if ($this->_data[$lower] === self::$null) { - $value = null; - } else { - $value = $this->_data[$lower]; - } - - } - - if ($value !== self::$null) { - $value = $this->_table->invokeGet($this, $name, $value); - - if ($invoke && $name !== $this->_table->getIdentifier()) { - return $this->_table->getAttribute(Doctrine::ATTR_LISTENER)->onGetProperty($this, $name, $value); - } else { - return $value; - } - } - - if (isset($this->_id[$lower])) { - return $this->_id[$lower]; - } - if ($name === $this->_table->getIdentifier()) { - return null; - } - if (isset($this->_values[$lower])) { - return $this->_values[$lower]; - } - - try { - if ( ! isset($this->references[$name])) { - $this->loadReference($name); - } - } catch(Doctrine_Table_Exception $e) { - throw new Doctrine_Record_Exception("Unknown property / related component '$name'."); - } - - return $this->references[$name]; - } - - /** - * mapValue - * This simple method is used for mapping values to $values property. - * Usually this method is used internally by Doctrine for the mapping of - * aggregate values. - * - * @param string $name the name of the mapped value - * @param mixed $value mixed value to be mapped - * @return void - */ - public function mapValue($name, $value) - { - $name = strtolower($name); - $this->_values[$name] = $value; - } - - /** - * set - * method for altering properties and Doctrine_Record references - * if the load parameter is set to false this method will not try to load uninitialized record data - * - * @param mixed $name name of the property or reference - * @param mixed $value value of the property or reference - * @param boolean $load whether or not to refresh / load the uninitialized record data - * - * @throws Doctrine_Record_Exception if trying to set a value for unknown property / related component - * @throws Doctrine_Record_Exception if trying to set a value of wrong type for related component - * - * @return Doctrine_Record - */ - public function set($name, $value, $load = true) - { - $lower = strtolower($name); - - $lower = $this->_table->getColumnName($lower); - - if (isset($this->_data[$lower])) { - if ($value instanceof Doctrine_Record) { - $id = $value->getIncremented(); - - if ($id !== null) { - $value = $id; - } - } - - if ($load) { - $old = $this->get($lower, false); - } else { - $old = $this->_data[$lower]; - } - - if ($old !== $value) { - $value = $this->_table->invokeSet($this, $name, $value); - - $value = $this->_table->getAttribute(Doctrine::ATTR_LISTENER)->onSetProperty($this, $name, $value); - - if ($value === null) - $value = self::$null; - - $this->_data[$lower] = $value; - $this->_modified[] = $lower; - switch ($this->_state) { - case Doctrine_Record::STATE_CLEAN: - $this->_state = Doctrine_Record::STATE_DIRTY; - break; - case Doctrine_Record::STATE_TCLEAN: - $this->_state = Doctrine_Record::STATE_TDIRTY; - break; - }; - } - } else { - try { - $this->coreSetRelated($name, $value); - } catch(Doctrine_Table_Exception $e) { - throw new Doctrine_Record_Exception("Unknown property / related component '$name'."); - } - } - } - - public function coreSetRelated($name, $value) - { - $rel = $this->_table->getRelation($name); - - // one-to-many or one-to-one relation - if ($rel instanceof Doctrine_Relation_ForeignKey || - $rel instanceof Doctrine_Relation_LocalKey) { - if ( ! $rel->isOneToOne()) { - // one-to-many relation found - if ( ! ($value instanceof Doctrine_Collection)) { - throw new Doctrine_Record_Exception("Couldn't call Doctrine::set(), second argument should be an instance of Doctrine_Collection when setting one-to-many references."); - } - $value->setReference($this,$rel); - } else { - // one-to-one relation found - if ( ! ($value instanceof Doctrine_Record)) { - throw new Doctrine_Record_Exception("Couldn't call Doctrine::set(), second argument should be an instance of Doctrine_Record when setting one-to-one references."); - } - if ($rel instanceof Doctrine_Relation_LocalKey) { - $this->set($rel->getLocal(), $value, false); - } else { - $value->set($rel->getForeign(), $this, false); - } - } - - } elseif ($rel instanceof Doctrine_Relation_Association) { - // join table relation found - if ( ! ($value instanceof Doctrine_Collection)) { - throw new Doctrine_Record_Exception("Couldn't call Doctrine::set(), second argument should be an instance of Doctrine_Collection when setting many-to-many references."); - } - } - - $this->references[$name] = $value; - } - - /** - * contains - * - * @param string $name - * @return boolean - */ - public function contains($name) - { - $lower = strtolower($name); - - if (isset($this->_data[$lower])) { - return true; - } - if (isset($this->_id[$lower])) { - return true; - } - if (isset($this->references[$name])) { - return true; - } - return false; - } - - /** - * @param string $name - * @return void - */ - public function __unset($name) - { - if (isset($this->_data[$name])) { - $this->_data[$name] = array(); - } - // todo: what to do with references ? - } - - /** - * 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 components - * - * @param Doctrine_Connection $conn optional connection parameter - * @return void - */ - public function save(Doctrine_Connection $conn = null) - { - if ($conn === null) { - $conn = $this->_table->getConnection(); - } - $conn->beginTransaction(); - - $saveLater = $conn->unitOfWork->saveRelated($this); - - if ($this->isValid()) { - $conn->save($this); - } else { - $conn->transaction->addInvalid($this); - } - - foreach ($saveLater as $fk) { - $table = $fk->getTable(); - $alias = $this->_table->getAlias($table->getComponentName()); - - if (isset($this->references[$alias])) { - $obj = $this->references[$alias]; - $obj->save($conn); - } - } - - // save the MANY-TO-MANY associations - - $conn->unitOfWork->saveAssociations($this); - //$this->saveAssociations(); - - $conn->commit(); - } - - /** - * Tries to save the object and all its related components. - * In contrast to Doctrine_Record::save(), this method does not - * throw an exception when validation fails but returns TRUE on - * success or FALSE on failure. - * - * @param Doctrine_Connection $conn optional connection parameter - * @return TRUE if the record was saved sucessfully without errors, FALSE otherwise. - */ - public function trySave(Doctrine_Connection $conn = null) { - try { - $this->save($conn); - return true; - } catch (Doctrine_Validator_Exception $ignored) { - return false; - } - } - - /** - * replace - * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT - * query, except that if there is already a row in the table with the same - * key field values, the REPLACE query just updates its values instead of - * inserting a new row. - * - * The REPLACE type of query does not make part of the SQL standards. Since - * practically only MySQL and SQLIte implement it natively, this type of - * query isemulated through this method for other DBMS using standard types - * of queries inside a transaction to assure the atomicity of the operation. - * - * @param Doctrine_Connection $conn optional connection parameter - * @throws Doctrine_Connection_Exception if some of the key values was null - * @throws Doctrine_Connection_Exception if there were no key fields - * @throws PDOException if something fails at PDO level - * @return integer number of rows affected - */ - public function replace(Doctrine_Connection $conn = null) - { - if ($conn === null) { - $conn = $this->_table->getConnection(); - } - - return $conn->replace($this->_table->getTableName(), $this->getPrepared(), $this->id); - } - - /** - * returns an array of modified fields and associated values - * @return array - */ - public function getModified() - { - $a = array(); - - foreach ($this->_modified as $k => $v) { - $a[$v] = $this->_data[$v]; - } - return $a; - } - - /** - * getPrepared - * - * returns an array of modified fields and values with data preparation - * adds column aggregation inheritance and converts Records into primary key values - * - * @param array $array - * @return array - */ - public function getPrepared(array $array = array()) { - $a = array(); - - if (empty($array)) { - $array = $this->_modified; - } - foreach ($array as $k => $v) { - $type = $this->_table->getTypeOf($v); - - if ($this->_data[$v] === self::$null) { - $a[$v] = null; - continue; - } - - switch ($type) { - case 'array': - case 'object': - $a[$v] = serialize($this->_data[$v]); - break; - case 'gzip': - $a[$v] = gzcompress($this->_data[$v],5); - break; - case 'boolean': - $a[$v] = $this->getTable()->getConnection()->convertBooleans($this->_data[$v]); - break; - case 'enum': - $a[$v] = $this->_table->enumIndex($v,$this->_data[$v]); - break; - default: - if ($this->_data[$v] instanceof Doctrine_Record) - $this->_data[$v] = $this->_data[$v]->getIncremented(); - - $a[$v] = $this->_data[$v]; - } - } - $map = $this->_table->inheritanceMap; - foreach ($map as $k => $v) { - $old = $this->get($k, false); - - if ((string) $old !== (string) $v || $old === null) { - $a[$k] = $v; - $this->_data[$k] = $v; - } - } - - return $a; - } - - /** - * count - * this class implements countable interface - * - * @return integer the number of columns in this record - */ - public function count() - { - return count($this->_data); - } - - /** - * alias for count() - * - * @return integer the number of columns in this record - */ - public function columnCount() - { - return $this->count(); - } - - /** - * toArray - * returns the record as an array - * - * @return array - */ - public function toArray() - { - $a = array(); - - foreach ($this as $column => $value) { - $a[$column] = $value; - } - if ($this->_table->getIdentifierType() == Doctrine_Identifier::AUTO_INCREMENT) { - $i = $this->_table->getIdentifier(); - $a[$i] = $this->getIncremented(); - } - return $a; - } - - /** - * exists - * returns true if this record is persistent, otherwise false - * - * @return boolean - */ - public function exists() - { - return ($this->_state !== Doctrine_Record::STATE_TCLEAN && - $this->_state !== Doctrine_Record::STATE_TDIRTY); - } - - /** - * method for checking existence of properties and Doctrine_Record references - * @param mixed $name name of the property or reference - * @return boolean - */ - public function hasRelation($name) - { - if (isset($this->_data[$name]) || isset($this->_id[$name])) { - return true; - } - return $this->_table->hasRelation($name); - } - - /** - * getIterator - * @return Doctrine_Record_Iterator a Doctrine_Record_Iterator that iterates through the data - */ - public function getIterator() - { - return new Doctrine_Record_Iterator($this); - } - - /** - * 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 - */ - public function delete(Doctrine_Connection $conn = null) - { - if ($conn == null) { - $conn = $this->_table->getConnection(); - } - return $conn->delete($this); - } - - /** - * copy - * returns a copy of this object - * - * @return Doctrine_Record - */ - public function copy() - { - $ret = $this->_table->create($this->_data); - $modified = array(); - foreach ($this->_data as $key => $val) { - if ( ! ($val instanceof Doctrine_Null)) { - $ret->_modified[] = $key; - } - } - return $ret; - } - - /** - * copyDeep - * returns a copy of this object and all its related objects - * - * @return Doctrine_Record - */ - public function copyDeep(){ - $copy = $this->copy(); - - foreach ($this->references as $key => $value) { - if ($value instanceof Doctrine_Collection) { - foreach ($value as $record) { - $copy->{$key}[] = $record->copyDeep(); - } - } else { - $copy->set($key, $value->copyDeep()); - } - } - return $copy; - } - - /** - * assignIdentifier - * - * @param integer $id - * @return void - */ - final public function assignIdentifier($id = false) - { - if ($id === false) { - $this->_id = array(); - $this->cleanData(); - $this->_state = Doctrine_Record::STATE_TCLEAN; - $this->_modified = array(); - } elseif ($id === true) { - $this->prepareIdentifiers(false); - $this->_state = Doctrine_Record::STATE_CLEAN; - $this->_modified = array(); - } else { - $name = $this->_table->getIdentifier(); - - $this->_id[$name] = $id; - $this->_state = Doctrine_Record::STATE_CLEAN; - $this->_modified = array(); - } - } - - /** - * returns the primary keys of this object - * - * @return array - */ - final public function obtainIdentifier() - { - return $this->_id; - } - - /** - * returns the value of autoincremented primary key of this object (if any) - * - * @return integer - */ - final public function getIncremented() - { - $id = current($this->_id); - if ($id === false) - return null; - - return $id; - } - - /** - * getLast - * this method is used internally be Doctrine_Query - * it is needed to provide compatibility between - * records and collections - * - * @return Doctrine_Record - */ - public function getLast() - { - return $this; - } - - /** - * hasRefence - * @param string $name - * @return boolean - */ - public function hasReference($name) - { - return isset($this->references[$name]); - } - - /** - * obtainReference - * - * @param string $name - * @throws Doctrine_Record_Exception if trying to get an unknown related component - */ - public function obtainReference($name) - { - if (isset($this->references[$name])) { - return $this->references[$name]; - } - throw new Doctrine_Record_Exception("Unknown reference $name"); - } - - /** - * initalizes a one-to-many / many-to-many relation - * - * @param Doctrine_Collection $coll - * @param Doctrine_Relation $connector - * @return boolean - */ - public function initReference(Doctrine_Collection $coll, Doctrine_Relation $connector) - { - $alias = $connector->getAlias(); - - if (isset($this->references[$alias])) { - return false; - } - if ( ! $connector->isOneToOne()) { - if ( ! ($connector instanceof Doctrine_Relation_Association)) { - $coll->setReference($this, $connector); - } - $this->references[$alias] = $coll; - $this->originals[$alias] = clone $coll; - - return true; - } - return false; - } - - /** - * getReferences - * @return array all references - */ - public function getReferences() - { - return $this->references; - } - - /** - * loadReference - * loads a related component - * - * @throws Doctrine_Table_Exception if trying to load an unknown related component - * @param string $name - * @return void - */ - final public function loadReference($name) - { - $fk = $this->_table->getRelation($name); - - if ($fk->isOneToOne()) { - $this->references[$name] = $fk->fetchRelatedFor($this); - - } else { - $coll = $fk->fetchRelatedFor($this); - - $this->references[$name] = $coll; - } - } - - /** - * binds One-to-One composite relation - * - * @param string $objTableName - * @param string $fkField - * @return void - */ - final public function ownsOne($componentName, $foreignKey, $options = null) - { - $this->_table->bind($componentName, $foreignKey, Doctrine_Relation::ONE_COMPOSITE, $options); - } - - /** - * binds One-to-Many composite relation - * - * @param string $objTableName - * @param string $fkField - * @return void - */ - final public function ownsMany($componentName, $foreignKey, $options = null) - { - $this->_table->bind($componentName, $foreignKey, Doctrine_Relation::MANY_COMPOSITE, $options); - } - - /** - * binds One-to-One aggregate relation - * - * @param string $objTableName - * @param string $fkField - * @return void - */ - final public function hasOne($componentName, $foreignKey, $options = null) - { - $this->_table->bind($componentName, $foreignKey, Doctrine_Relation::ONE_AGGREGATE, $options); - } - - /** - * binds One-to-Many aggregate relation - * - * @param string $objTableName - * @param string $fkField - * @return void - */ - final public function hasMany($componentName, $foreignKey, $options = null) - { - $this->_table->bind($componentName, $foreignKey, Doctrine_Relation::MANY_AGGREGATE, $options); - } - - /** - * hasColumn - * sets a column definition - * - * @param string $name - * @param string $type - * @param integer $length - * @param mixed $options - * @return void - */ - final public function hasColumn($name, $type, $length = 2147483647, $options = "") - { - $this->_table->setColumn($name, $type, $length, $options); - } - - /** - * countRelated - * - * @param string $name the name of the related component - * @return integer - */ - public function countRelated($name) - { - $rel = $this->_table->getRelation($name); - $componentName = $rel->getTable()->getComponentName(); - $alias = $rel->getTable()->getAlias(get_class($this)); - $query = new Doctrine_Query(); - $query->from($componentName. '(' . 'COUNT(1)' . ')')->where($componentName. '.' .$alias. '.' . $this->getTable()->getIdentifier(). ' = ?'); - $array = $query->execute(array($this->getIncremented())); - return $array[0]['COUNT(1)']; - } - - /** - * merge - * merges this record with an array of values - * - * @param array $values - * @return void - */ - public function merge(array $values) - { - foreach ($this->_table->getColumnNames() as $value) { - try { - if (isset($values[$value])) { - $this->set($value, $values[$value]); - } - } catch(Exception $e) { - // silence all exceptions - } - } - } - public function setAttribute($attr, $value) - { - $this->_table->setAttribute($attr, $value); - } - public function setTableName($tableName) - { - $this->_table->setOption('tableName', $tableName); - } - public function setInheritanceMap($map) - { - $this->_table->setOption('inheritanceMap', $map); - } - public function setEnumValues($column, $values) - { - $this->_table->setEnumValues($column, $values); - } - - /** - * attribute - * sets or retrieves an option - * - * @see Doctrine::ATTR_* constants availible attributes - * @param mixed $attr - * @param mixed $value - * @return mixed - */ - public function attribute($attr, $value) - { - if ($value == null) { - if (is_array($attr)) { - foreach ($attr as $k => $v) { - $this->_table->setAttribute($k, $v); - } - } else { - return $this->_table->getAttribute($attr); - } - } else { - $this->_table->setAttribute($attr, $value); - } - } - - /** - * option - * sets or retrieves an option - * - * @see Doctrine_Table::$options availible options - * @param mixed $name the name of the option - * @param mixed $value options value - * @return mixed - */ - public function option($name, $value = null) - { - if ($value == null) { - if (is_array($name)) { - foreach ($name as $k => $v) { - $this->_table->setOption($k, $v); - } - } else { - return $this->_table->getOption($name); - } - } else { - $this->_table->setOption($name, $value); - } - } - - /** - * index - * defines or retrieves an index - * if the second parameter is set this method defines an index - * if not this method retrieves index named $name - * - * @param string $name the name of the index - * @param array $definition the definition array - * @return mixed - */ - public function index($name, array $definition = array()) - { - if ( ! $definition) { - return $this->_table->getIndex($name); - } else { - return $this->_table->addIndex($name, $definition); - } - } - - /** - * addListener - * - * @param Doctrine_Db_EventListener_Interface|Doctrine_Overloadable $listener - * @return Doctrine_Db - */ - public function addListener($listener, $name = null) - { - $this->_table->addListener($listener, $name = null); - return $this; - } - - /** - * getListener - * - * @return Doctrine_Db_EventListener_Interface|Doctrine_Overloadable - */ - public function getListener() - { - return $this->_table->getListener(); - } - - /** - * setListener - * - * @param Doctrine_Db_EventListener_Interface|Doctrine_Overloadable $listener - * @return Doctrine_Db - */ - public function setListener($listener) - { - $this->_table->setListener($listener); - return $this; - } - - /** - * call - * - * @param string|array $callback valid callback - * @param string $column column name - * @param mixed arg1 ... argN optional callback arguments - * @return Doctrine_Record - */ - public function call($callback, $column) - { - $args = func_get_args(); - array_shift($args); - - if (isset($args[0])) { - $column = $args[0]; - $args[0] = $this->get($column); - - $newvalue = call_user_func_array($callback, $args); - - $this->_data[$column] = $newvalue; - } - return $this; - } - - /** - * getter for node assciated with this record - * - * @return mixed if tree returns Doctrine_Node otherwise returns false - */ - public function getNode() - { - if ( ! $this->_table->isTree()) { - return false; - } - - if ( ! isset($this->_node)) { - $this->_node = Doctrine_Node::factory($this, - $this->getTable()->getOption('treeImpl'), - $this->getTable()->getOption('treeOptions') - ); - } - - return $this->_node; - } - - /** - * used to delete node from tree - MUST BE USE TO DELETE RECORD IF TABLE ACTS AS TREE - * - */ - public function deleteNode() { - $this->getNode()->delete(); - } - - /** - * returns a string representation of this object - */ - public function __toString() - { - return Doctrine_Lib::getRecordAsString($this); - } -} diff --git a/draft/new-core/Table.php b/draft/new-core/Table.php deleted file mode 100644 index 26bf9cc6c..000000000 --- a/draft/new-core/Table.php +++ /dev/null @@ -1,1547 +0,0 @@ -. - */ - -/** - * Doctrine_Table - * - * This class represents a database table. - * Each Doctrine_Table holds the information of foreignKeys and associations - * to other tables. - * - * @author Konsta Vesterinen - * @package Doctrine - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @version $Revision: 1288 $ - * @category Object Relational Mapping - * @link www.phpdoctrine.com - * @since 1.0 - */ -class Doctrine_Table extends Doctrine_Configurable implements Countable -{ - /** - * @var array $data temporary data which is then loaded into Doctrine_Record::$data - */ - private $data = array(); - - /** - * @var array $relations an array containing all the Doctrine_Relation objects for this table - */ - private $relations = array(); - - /** - * @var array $primaryKeys an array containing all primary key column names - */ - private $primaryKeys = array(); - - /** - * @var mixed $identifier - */ - private $identifier; - - /** - * @see Doctrine_Identifier constants - * @var integer $identifierType the type of identifier this table uses - */ - private $identifierType; - - /** - * @var Doctrine_Connection $conn Doctrine_Connection object that created this table - */ - private $conn; - - /** - * @var string $name - */ - private $name; - - /** - * @var array $identityMap first level cache - */ - private $identityMap = array(); - - /** - * @var Doctrine_Table_Repository $repository record repository - */ - private $repository; - - /** - * @var array $columns an array of column definitions, - * keys as column names and values as column definitions - * - * the value array has three values: - * - * the column type, eg. 'integer' - * the column length, eg. 11 - * the column options/constraints/validators. eg array('notnull' => true) - * - * so the full columns array might look something like the following: - * array( - * 'name' => array('string', 20, array('notnull' => true, 'default' => 'someone')), - * 'age' => array('integer', 11, array('notnull' => true)) - * ) - */ - protected $columns = array(); - - /** - * @var array $columnAliases an array of column aliases - * keys as column aliases and values as column names - */ - protected $columnAliases = array(); - - /** - * @var array $bound bound relations - */ - private $bound = array(); - - /** - * @var array $boundAliases bound relation aliases - */ - private $boundAliases = array(); - - /** - * @var integer $columnCount cached column count, Doctrine_Record uses this column count in when - * determining its state - */ - private $columnCount; - - /** - * @var boolean $hasDefaultValues whether or not this table has default values - */ - private $hasDefaultValues; - - /** - * @var array $options an array containing all options - * - * -- name name of the component, for example component name of the GroupTable is 'Group' - * - * -- parents the parent classes of this component - * - * -- declaringClass name of the table definition declaring class (when using inheritance the class - * that defines the table structure can be any class in the inheritance hierarchy, - * hence we need reflection to check out which class actually calls setTableDefinition) - * - * -- 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 - * - * -- sequenceName Some databases need sequences instead of auto incrementation primary keys, - * you can set specific sequence for your table by calling setOption('sequenceName', $seqName) - * where $seqName is the name of the desired sequence - * - * -- enumMap enum value arrays - * - * -- inheritanceMap inheritanceMap is used for inheritance mapping, keys representing columns and values - * the column values that should correspond to child classes - * - * -- type table type (mysql example: INNODB) - * - * -- charset character set - * - * -- foreignKeys the foreign keys of this table - * - * -- collation - * - * -- indexes the index definitions of this table - * - * -- treeImpl the tree implementation of this table (if any) - * - * -- treeOptions the tree options - */ - protected $options = array('name' => null, - 'tableName' => null, - 'sequenceName' => null, - 'inheritanceMap' => array(), - 'enumMap' => array(), - 'engine' => null, - 'charset' => null, - 'collation' => null, - 'treeImpl' => null, - 'treeOptions' => null, - 'indexes' => array(), - ); - - /** - * @var Doctrine_Tree $tree tree object associated with this table - */ - protected $tree; - - /** - * the constructor - * @throws Doctrine_Connection_Exception if there are no opened connections - * @throws Doctrine_Table_Exception if there is already an instance of this table - * @return void - */ - public function __construct($name, Doctrine_Connection $conn) - { - $this->conn = $conn; - - $this->setParent($this->conn); - - $this->options['name'] = $name; - - if ( ! class_exists($name) || empty($name)) { - throw new Doctrine_Exception("Couldn't find class $name"); - } - $record = new $name($this); - - $names = array(); - - $class = $name; - - // get parent classes - - do { - if ($class == "Doctrine_Record") - break; - - $name = $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(); - - // set the table definition for the given tree implementation - if($this->isTree()) - $this->getTree()->setTableDefinition(); - - $this->columnCount = count($this->columns); - - if (isset($this->columns)) { - // get the declaring class of setTableDefinition method - $method = new ReflectionMethod($this->options['name'], 'setTableDefinition'); - $class = $method->getDeclaringClass(); - - $this->options['declaringClass'] = $class; - - if ( ! isset($this->options['tableName'])) { - $this->options['tableName'] = Doctrine::tableize($class->getName()); - } - switch (count($this->primaryKeys)) { - case 0: - $this->columns = array_merge(array('id' => - array('integer', - 20, - array('autoincrement' => true, - 'primary' => true, - ) - ) - ), $this->columns); - - $this->primaryKeys[] = 'id'; - $this->identifier = 'id'; - $this->identifierType = Doctrine_Identifier::AUTO_INCREMENT; - $this->columnCount++; - break; - default: - if (count($this->primaryKeys) > 1) { - $this->identifier = $this->primaryKeys; - $this->identifierType = Doctrine_Identifier::COMPOSITE; - - } else { - foreach ($this->primaryKeys as $pk) { - $e = $this->columns[$pk][2]; - - $found = false; - - foreach ($e as $option => $value) { - if ($found) - break; - - $e2 = explode(':', $option); - - switch (strtolower($e2[0])) { - case 'autoincrement': - case 'autoinc': - $this->identifierType = Doctrine_Identifier::AUTO_INCREMENT; - $found = true; - break; - case 'seq': - case 'sequence': - $this->identifierType = Doctrine_Identifier::SEQUENCE; - $found = true; - - if ($value) { - $this->options['sequenceName'] = $value; - } else { - if (($sequence = $this->getAttribute(Doctrine::ATTR_DEFAULT_SEQUENCE)) !== null) { - $this->options['sequenceName'] = $sequence; - } else { - $this->options['sequenceName'] = $this->conn->getSequenceName($this->options['tableName']); - } - } - break; - } - } - if ( ! isset($this->identifierType)) { - $this->identifierType = Doctrine_Identifier::NORMAL; - } - $this->identifier = $pk; - } - } - } - } - } else { - throw new Doctrine_Table_Exception("Class '$name' has no table definition."); - } - - $record->setUp(); - - // if tree, set up tree - if ($this->isTree()) { - $this->getTree()->setUp(); - } - - // save parents - array_pop($names); - $this->options['parents'] = $names; - - $this->repository = new Doctrine_Table_Repository($this); - } - - /** - * export - * exports this table to database based on column and option definitions - * - * @throws Doctrine_Connection_Exception if some error other than Doctrine::ERR_ALREADY_EXISTS - * occurred during the create table operation - * @return boolean whether or not the export operation was successful - * false if table already existed in the database - */ - public function export() - { - if ( ! Doctrine::isValidClassname($this->options['declaringClass']->getName())) { - throw new Doctrine_Table_Exception('Class name not valid.'); - } - - try { - $columns = array(); - $primary = array(); - - foreach ($this->columns as $name => $column) { - $definition = $column[2]; - $definition['type'] = $column[0]; - $definition['length'] = $column[1]; - - switch ($definition['type']) { - case 'enum': - if (isset($definition['default'])) { - $definition['default'] = $this->enumIndex($name, $definition['default']); - } - break; - case 'boolean': - if (isset($definition['default'])) { - $definition['default'] = $this->conn->convertBooleans($definition['default']); - } - break; - } - $columns[$name] = $definition; - - if(isset($definition['primary']) && $definition['primary']) { - $primary[] = $name; - } - } - - if ($this->getAttribute(Doctrine::ATTR_EXPORT) & Doctrine::EXPORT_CONSTRAINTS) { - - foreach ($this->getRelations() as $name => $relation) { - $fk = $relation->toArray(); - $fk['foreignTable'] = $relation->getTable()->getTableName(); - - if ($relation->getTable() === $this && in_array($relation->getLocal(), $primary)) { - continue; - } - - if ($relation->hasConstraint()) { - - $options['foreignKeys'][] = $fk; - } elseif ($relation instanceof Doctrine_Relation_LocalKey) { - $options['foreignKeys'][] = $fk; - } - } - } - - $options['primary'] = $primary; - - $this->conn->export->createTable($this->options['tableName'], $columns, array_merge($this->options, $options)); - } catch(Doctrine_Connection_Exception $e) { - // we only want to silence table already exists errors - if($e->getPortableCode() !== Doctrine::ERR_ALREADY_EXISTS) { - throw $e; - } - } - } - - /** - * exportConstraints - * exports the constraints of this table into database based on option definitions - * - * @throws Doctrine_Connection_Exception if something went wrong on db level - * @return void - */ - public function exportConstraints() - { - try { - $this->conn->beginTransaction(); - - foreach ($this->options['index'] as $index => $definition) { - $this->conn->export->createIndex($this->options['tableName'], $index, $definition); - } - $this->conn->commit(); - } catch(Doctrine_Connection_Exception $e) { - $this->conn->rollback(); - - throw $e; - } - } - - /** - * __get - * an alias for getOption - * - * @param string $option - */ - public function __get($option) - { - if (isset($this->options[$option])) { - return $this->options[$option]; - } - return null; - } - - /** - * __isset - * - * @param string $option - */ - public function __isset($option) - { - return isset($this->options[$option]); - } - - /** - * addForeignKey - * - * adds a foreignKey to this table - * - * @return void - */ - public function addForeignKey(array $definition) - { - $this->options['foreignKeys'][] = $definition; - } - - /** - * addIndex - * - * adds an index to this table - * - * @return void - */ - public function addIndex($index, array $definition) - { - $index = $this->conn->getIndexName($index); - $this->options['indexes'][$index] = $definition; - } - - /** - * getIndex - * - * @return array|boolean array on success, FALSE on failure - */ - public function getIndex($index) - { - if (isset($this->options['indexes'][$index])) { - return $this->options['indexes'][$index]; - } - - return false; - } - - /** - * createQuery - * creates a new Doctrine_Query object and adds the component name - * of this table as the query 'from' part - * - * @return Doctrine_Query - */ - public function createQuery() - { - return Doctrine_Query::create()->from($this->getComponentName()); - } - - /** - * getRepository - * - * @return Doctrine_Table_Repository - */ - public function getRepository() - { - return $this->repository; - } - - public function setOption($name, $value) - { - switch ($name) { - case 'name': - case 'tableName': - break; - case 'enumMap': - case 'inheritanceMap': - case 'index': - case 'treeOptions': - if ( ! is_array($value)) { - throw new Doctrine_Table_Exception($name . ' should be an array.'); - } - break; - } - $this->options[$name] = $value; - } - public function getOption($name) - { - if (isset($this->options[$name])) { - return $this->options[$name]; - } - return null; - } - - /** - * getColumnName - * - * returns a column name for column alias - * if the actual name for the alias cannot be found - * this method returns the given alias - * - * @param string $alias column alias - * @return string column name - */ - public function getColumnName($alias) - { - if(isset($this->columnAliases[$alias])) { - return $this->columnAliases[$alias]; - } - - return $alias; - } - - /** - * setColumn - * - * @param string $name - * @param string $type - * @param integer $length - * @param mixed $options - * @throws Doctrine_Table_Exception if trying use wrongly typed parameter - * @return void - */ - public function setColumn($name, $type, $length = null, $options = array()) - { - if (is_string($options)) { - $options = explode('|', $options); - } - - foreach ($options as $k => $option) { - if (is_numeric($k)) { - if ( ! empty($option)) { - $options[$option] = true; - } - unset($options[$k]); - } - } - - $name = strtolower($name); - $parts = explode(' as ', $name); - - if (count($parts) > 1) { - $this->columnAliases[$parts[1]] = $parts[0]; - $name = $parts[0]; - } - - - if ($length == null) { - $length = 2147483647; - } - - if ((string) (int) $length !== (string) $length) { - throw new Doctrine_Table_Exception('Invalid argument given for column length'); - } - - $this->columns[$name] = array($type, $length, $options); - - if (isset($options['primary'])) { - $this->primaryKeys[] = $name; - } - if (isset($options['default'])) { - $this->hasDefaultValues = true; - } - } - - /** - * hasDefaultValues - * returns true if this table has default values, otherwise false - * - * @return boolean - */ - public function hasDefaultValues() - { - return $this->hasDefaultValues; - } - - /** - * getDefaultValueOf - * returns the default value(if any) for given column - * - * @param string $column - * @return mixed - */ - public function getDefaultValueOf($column) - { - $column = strtolower($column); - if ( ! isset($this->columns[$column])) { - throw new Doctrine_Table_Exception("Couldn't get default value. Column ".$column." doesn't exist."); - } - if (isset($this->columns[$column][2]['default'])) { - return $this->columns[$column][2]['default']; - } else { - return null; - } - } - - /** - * @return mixed - */ - public function getIdentifier() - { - return $this->identifier; - } - - /** - * @return integer - */ - public function getIdentifierType() - { - return $this->identifierType; - } - - /** - * hasColumn - * @return boolean - */ - public function hasColumn($name) - { - return isset($this->columns[$name]); - } - - /** - * @param mixed $key - * @return void - */ - public function setPrimaryKey($key) - { - switch (gettype($key)) { - case "array": - $this->primaryKeys = array_values($key); - break; - case "string": - $this->primaryKeys[] = $key; - break; - }; - } - - /** - * returns all primary keys - * @return array - */ - public function getPrimaryKeys() - { - return $this->primaryKeys; - } - - /** - * @return boolean - */ - public function hasPrimaryKey($key) - { - return in_array($key,$this->primaryKeys); - } - - /** - * returns all bound relations - * - * @return array - */ - public function getBounds() - { - return $this->bound; - } - - /** - * returns a bound relation array - * - * @param string $name - * @return array - */ - public function getBound($name) - { - if ( ! isset($this->bound[$name])) { - throw new Doctrine_Table_Exception('Unknown bound ' . $name); - } - return $this->bound[$name]; - } - - /** - * returns a bound relation array - * - * @param string $name - * @return array - */ - public function getBoundForName($name, $component) - { - foreach ($this->bound as $k => $bound) { - $e = explode('.', $bound['field']); - - if ($bound['class'] == $name && $e[0] == $component) { - return $this->bound[$k]; - } - } - throw new Doctrine_Table_Exception('Unknown bound ' . $name); - } - - /** - * returns the alias for given component name - * - * @param string $name - * @return string - */ - public function getAlias($name) - { - if (isset($this->boundAliases[$name])) { - return $this->boundAliases[$name]; - } - return $name; - } - - /** - * returns component name for given alias - * - * @param string $alias - * @return string - */ - public function getAliasName($alias) - { - if ($name = array_search($alias, $this->boundAliases)) { - return $name; - } - return $alias; - } - - /** - * unbinds all relations - * - * @return void - */ - public function unbindAll() - { throw new Exception(); - $this->bound = array(); - $this->relations = array(); - $this->boundAliases = array(); - } - - /** - * unbinds a relation - * returns true on success, false on failure - * - * @param $name - * @return boolean - */ - public function unbind($name) - { - if ( ! isset($this->bound[$name])) { - return false; - } - unset($this->bound[$name]); - - if (isset($this->relations[$name])) { - unset($this->relations[$name]); - } - if (isset($this->boundAliases[$name])) { - unset($this->boundAliases[$name]); - } - return true; - } - - /** - * binds a relation - * - * @param string $name - * @param string $field - * @return void - */ - public function bind($name, $field, $type, $options = null) - { - if (isset($this->relations[$name])) { - unset($this->relations[$name]); - } - - $lower = strtolower($name); - - if (isset($this->columns[$lower])) { - throw new Doctrine_Table_Exception("Couldn't bind relation. Column with name " . $lower . ' already exists!'); - } - - $e = explode(' as ', $name); - $name = $e[0]; - - if (isset($e[1])) { - $alias = $e[1]; - $this->boundAliases[$name] = $alias; - } else { - $alias = $name; - } - - $this->bound[$alias] = array('field' => $field, - 'type' => $type, - 'class' => $name, - 'alias' => $alias); - if ($options !== null) { - $opt = array(); - if (is_string($options)) { - $opt['local'] = $options; - } else { - $opt = (array) $options; - } - - $this->bound[$alias] = array_merge($this->bound[$alias], $opt); - } - } - - /** - * @return Doctrine_Connection - */ - public function getConnection() - { - return $this->conn; - } - - /** - * hasRelatedComponent - * @return boolean - */ - public function hasRelatedComponent($name, $component) - { - return (strpos($this->bound[$name]['field'], $component . '.') !== false); - } - - /** - * @param string $name component name of which a foreign key object is bound - * @return boolean - */ - final public function hasRelation($name) - { - if (isset($this->bound[$name])) { - return true; - } - foreach ($this->bound as $k=>$v) { - if ($this->hasRelatedComponent($k, $name)) { - return true; - } - } - return false; - } - - /** - * getRelation - * - * @param string $name component name of which a foreign key object is bound - * @return Doctrine_Relation - */ - public function getRelation($name, $recursive = true) - { - if (isset($this->relations[$name])) { - return $this->relations[$name]; - } - - if ( ! $this->conn->hasTable($this->options['name'])) { - $allowExport = true; - } else { - $allowExport = false; - } - - if (isset($this->bound[$name])) { - - $definition = $this->bound[$name]; - - list($component, $definition['foreign']) = explode('.', $definition['field']); - unset($definition['field']); - - $definition['table'] = $this->conn->getTable($definition['class'], $allowExport); - $definition['constraint'] = false; - - if ($component == $this->options['name'] || in_array($component, $this->options['parents'])) { - - // ONE-TO-ONE - if ($definition['type'] == Doctrine_Relation::ONE_COMPOSITE || - $definition['type'] == Doctrine_Relation::ONE_AGGREGATE) { - // tree structure parent relation found - - if ( ! isset($definition['local'])) { - $definition['local'] = $definition['foreign']; - $definition['foreign'] = $definition['table']->getIdentifier(); - } - - $relation = new Doctrine_Relation_LocalKey($definition); - - } else { - // tree structure children relation found - - if ( ! isset($definition['local'])) { - $tmp = $definition['table']->getIdentifier(); - - $definition['local'] = $tmp; - } - - //$definition['foreign'] = $tmp; - $definition['constraint'] = true; - - $relation = new Doctrine_Relation_ForeignKey($definition); - } - - } elseif ($component == $definition['class'] || - ($component == $definition['alias'])) { // && ($name == $this->options['name'] || in_array($name,$this->parents)) - - if ( ! isset($defintion['local'])) { - $definition['local'] = $this->identifier; - } - - $definition['constraint'] = true; - - // ONE-TO-MANY or ONE-TO-ONE - $relation = new Doctrine_Relation_ForeignKey($definition); - - } else { - // MANY-TO-MANY - // only aggregate relations allowed - - if ($definition['type'] != Doctrine_Relation::MANY_AGGREGATE) { - throw new Doctrine_Table_Exception("Only aggregate relations are allowed for many-to-many relations"); - } - - $classes = array_merge($this->options['parents'], array($this->options['name'])); - - foreach (array_reverse($classes) as $class) { - try { - $bound = $definition['table']->getBoundForName($class, $component); - break; - } catch(Doctrine_Table_Exception $exc) { } - } - if ( ! isset($bound)) { - throw new Doctrine_Table_Exception("Couldn't map many-to-many relation for " - . $this->options['name'] . " and $name. Components use different join tables."); - } - if ( ! isset($definition['local'])) { - $definition['local'] = $this->identifier; - } - $e2 = explode('.', $bound['field']); - $fields = explode('-', $e2[1]); - - if ($e2[0] != $component) { - throw new Doctrine_Table_Exception($e2[0] . ' doesn\'t match ' . $component); - } - $associationTable = $this->conn->getTable($e2[0], $allowExport); - - if (count($fields) > 1) { - // SELF-REFERENCING THROUGH JOIN TABLE - - $def['table'] = $associationTable; - $def['local'] = $this->identifier; - $def['foreign'] = $fields[0]; - $def['alias'] = $e2[0]; - $def['class'] = $e2[0]; - $def['type'] = Doctrine_Relation::MANY_COMPOSITE; - - $this->relations[$e2[0]] = new Doctrine_Relation_ForeignKey($def); - - $definition['assocTable'] = $associationTable; - $definition['local'] = $fields[0]; - $definition['foreign'] = $fields[1]; - $relation = new Doctrine_Relation_Association_Self($definition); - } else { - if($definition['table'] === $this) { - - } else { - // auto initialize a new one-to-one relationships for association table - $associationTable->bind($this->getComponentName(), - $associationTable->getComponentName(). '.' . $e2[1], - Doctrine_Relation::ONE_AGGREGATE - ); - - $associationTable->bind($definition['table']->getComponentName(), - $associationTable->getComponentName(). '.' . $definition['foreign'], - Doctrine_Relation::ONE_AGGREGATE - ); - - // NORMAL MANY-TO-MANY RELATIONSHIP - - $def['table'] = $associationTable; - $def['foreign'] = $e2[1]; - $def['local'] = $definition['local']; - $def['alias'] = $e2[0]; - $def['class'] = $e2[0]; - $def['type'] = Doctrine_Relation::MANY_COMPOSITE; - $this->relations[$e2[0]] = new Doctrine_Relation_ForeignKey($def); - - $definition['local'] = $e2[1]; - $definition['assocTable'] = $associationTable; - $relation = new Doctrine_Relation_Association($definition); - } - } - } - - $this->relations[$name] = $relation; - - return $this->relations[$name]; - } - - - // load all relations - $this->getRelations(); - - if ($recursive) { - return $this->getRelation($name, false); - } else { - throw new Doctrine_Table_Exception($this->options['name'] . " doesn't have a relation to " . $name); - } - - } - - /** - * returns an array containing all foreign key objects - * - * @return array - */ - final public function getRelations() - { - foreach ($this->bound as $k => $v) { - $this->getRelation($k); - } - - return $this->relations; - } - - /** - * create - * creates a new record - * - * @param $array an array where keys are field names and values representing field values - * @return Doctrine_Record - */ - public function create(array $array = array()) { - $this->data = $array; - $record = new $this->options['name']($this, true); - $this->data = array(); - return $record; - } - - /** - * finds a record by its identifier - * - * @param $id database row id - * @return Doctrine_Record|false a record for given database identifier - */ - public function find($id) - { - if ($id !== null) { - if ( ! is_array($id)) { - $id = array($id); - } else { - $id = array_values($id); - } - - $query = 'SELECT ' . implode(', ', array_keys($this->columns)) . ' FROM ' . $this->getTableName() . ' WHERE ' . implode(' = ? AND ', $this->primaryKeys) . ' = ?'; - $query = $this->applyInheritance($query); - - $params = array_merge($id, array_values($this->options['inheritanceMap'])); - - $stmt = $this->conn->execute($query, $params); - - $this->data = $stmt->fetch(PDO::FETCH_ASSOC); - - if ($this->data === false) - return false; - - return $this->getRecord(); - } - return false; - } - - /** - * applyInheritance - * @param $where query where part to be modified - * @return string query where part with column aggregation inheritance added - */ - final public function applyInheritance($where) - { - if ( ! empty($this->options['inheritanceMap'])) { - $a = array(); - foreach ($this->options['inheritanceMap'] as $field => $value) { - $a[] = $field . ' = ?'; - } - $i = implode(' AND ', $a); - $where .= ' AND ' . $i; - } - return $where; - } - - /** - * findAll - * returns a collection of records - * - * @return Doctrine_Collection - */ - public function findAll() - { - $graph = new Doctrine_Query($this->conn); - $users = $graph->query("FROM ".$this->options['name']); - return $users; - } - - /** - * findByDql - * finds records with given DQL where clause - * returns a collection of records - * - * @param string $dql DQL after WHERE clause - * @param array $params query parameters - * @return Doctrine_Collection - */ - public function findBySql($dql, array $params = array()) { - $q = new Doctrine_Query($this->conn); - $users = $q->query("FROM ".$this->options['name']." WHERE ".$dql, $params); - return $users; - } - - public function findByDql($dql, array $params = array()) { - return $this->findBySql($dql, $params); - } - - /** - * clear - * clears the first level cache (identityMap) - * - * @return void - */ - public function clear() - { - $this->identityMap = array(); - } - - /** - * getRecord - * first checks if record exists in identityMap, if not - * returns a new record - * - * @return Doctrine_Record - */ - public function getRecord() - { - $this->data = array_change_key_case($this->data, CASE_LOWER); - - $key = $this->getIdentifier(); - - if ( ! is_array($key)) { - $key = array($key); - } - - foreach ($key as $k) { - if ( ! isset($this->data[$k])) { - throw new Doctrine_Table_Exception("Primary key value for $k wasn't found"); - } - $id[] = $this->data[$k]; - } - - $id = implode(' ', $id); - - if (isset($this->identityMap[$id])) { - $record = $this->identityMap[$id]; - $record->hydrate($this->data); - } else { - $recordName = $this->getClassnameToReturn(); - $record = new $recordName($this); - $this->identityMap[$id] = $record; - } - $this->data = array(); - - return $record; - } - - /** - * Get the classname to return. Most often this is just the options['name'] - * - * Check the subclasses option and the inheritanceMap for each subclass to see - * if all the maps in a subclass is met. If this is the case return that - * subclass name. If no subclasses match or if there are no subclasses defined - * return the name of the class for this tables record. - * - * @todo this function could use reflection to check the first time it runs - * if the subclassing option is not set. - * - * @return string The name of the class to create - * - */ - public function getClassnameToReturn() - { - if ( ! isset($this->options['subclasses'])) { - return $this->options['name']; - } - foreach ($this->options['subclasses'] as $subclass) { - $table = $this->conn->getTable($subclass); - $inheritanceMap = $table->getOption('inheritanceMap'); - $nomatch = false; - foreach ($inheritanceMap as $key => $value) { - if ( ! isset($this->data[$key]) || $this->data[$key] != $value) { - $nomatch = true; - break; - } - } - if ( ! $nomatch) { - return $table->getComponentName(); - } - } - return $this->options['name']; - } - - /** - * @param $id database row id - * @throws Doctrine_Find_Exception - */ - final public function getProxy($id = null) - { - if ($id !== null) { - $query = 'SELECT ' . implode(', ',$this->primaryKeys) - . ' FROM ' . $this->getTableName() - . ' WHERE ' . implode(' = ? && ',$this->primaryKeys).' = ?'; - $query = $this->applyInheritance($query); - - $params = array_merge(array($id), array_values($this->options['inheritanceMap'])); - - $this->data = $this->conn->execute($query,$params)->fetch(PDO::FETCH_ASSOC); - - if ($this->data === false) - return false; - } - return $this->getRecord(); - } - - /** - * count - * - * @return integer - */ - public function count() - { - $a = $this->conn->getDBH()->query("SELECT COUNT(1) FROM ".$this->options['tableName'])->fetch(PDO::FETCH_NUM); - return current($a); - } - - /** - * @return Doctrine_Query a Doctrine_Query object - */ - public function getQueryObject() - { - $graph = new Doctrine_Query($this->getConnection()); - $graph->load($this->getComponentName()); - return $graph; - } - - /** - * execute - * @param string $query - * @param array $array - * @param integer $limit - * @param integer $offset - */ - public function execute($query, array $array = array(), $limit = null, $offset = null) { - $coll = new Doctrine_Collection($this); - $query = $this->conn->modifyLimitQuery($query,$limit,$offset); - if ( ! empty($array)) { - $stmt = $this->conn->getDBH()->prepare($query); - $stmt->execute($array); - } else { - $stmt = $this->conn->getDBH()->query($query); - } - $data = $stmt->fetchAll(PDO::FETCH_ASSOC); - $stmt->closeCursor(); - - foreach ($data as $row) { - $this->data = $row; - $record = $this->getRecord(); - $coll->add($record); - } - return $coll; - } - - /** - * @param string $field - * @return array - */ - final public function getEnumValues($field) - { - if (isset($this->columns[$field][2]['values'])) { - return $this->columns[$field][2]['values']; - } else { - return array(); - } - } - - /** - * enumValue - * - * @param string $field - * @param integer $index - * @return mixed - */ - public function enumValue($field, $index) - { - if ($index instanceof Doctrine_Null) - return $index; - - return isset($this->columns[$field][2]['values'][$index]) ? $this->columns[$field][2]['values'][$index] : $index; - } - - /** - * enumIndex - * - * @param string $field - * @param mixed $value - * @return mixed - */ - public function enumIndex($field, $value) - { - $values = $this->getEnumValues($field); - - return array_search($value, $values); - } - - /** - * invokeSet - * - * @param mixed $value - */ - public function invokeSet(Doctrine_Record $record, $name, $value) - { - if ( ! ($this->getAttribute(Doctrine::ATTR_ACCESSORS) & Doctrine::ACCESSOR_SET)) { - return $value; - } - $prefix = $this->getAttribute(Doctrine::ATTR_ACCESSOR_PREFIX_SET); - if ( ! $prefix) - $prefix = 'set'; - - $method = $prefix . $name; - - if (method_exists($record, $method)) { - return $record->$method($value); - } - - return $value; - } - - /** - * invokeGet - * - * @param mixed $value - */ - public function invokeGet(Doctrine_Record $record, $name, $value) - { - if ( ! ($this->getAttribute(Doctrine::ATTR_ACCESSORS) & Doctrine::ACCESSOR_GET)) { - return $value; - } - $prefix = $this->getAttribute(Doctrine::ATTR_ACCESSOR_PREFIX_GET); - if ( ! $prefix) - $prefix = 'get'; - - $method = $prefix . $name; - - if (method_exists($record, $method)) { - return $record->$method($value); - } - - return $value; - } - - /** - * getDefinitionOf - * - * @return string ValueWrapper class name on success, false on failure - */ - public function getValueWrapperOf($column) - { - if (isset($this->columns[$column][2]['wrapper'])) { - return $this->columns[$column][2]['wrapper']; - } - return false; - } - - /** - * getColumnCount - * - * @return integer the number of columns in this table - */ - final public function getColumnCount() - { - return $this->columnCount; - } - - /** - * returns all columns and their definitions - * - * @return array - */ - final public function getColumns() - { - return $this->columns; - } - - /** - * returns an array containing all the column names - * - * @return array - */ - public function getColumnNames() - { - return array_keys($this->columns); - } - - /** - * getDefinitionOf - * - * @return mixed array on success, false on failure - */ - public function getDefinitionOf($column) - { - if (isset($this->columns[$column])) { - return $this->columns[$column]; - } - return false; - } - - /** - * getTypeOf - * - * @return mixed string on success, false on failure - */ - public function getTypeOf($column) - { - if (isset($this->columns[$column])) { - return $this->columns[$column][0]; - } - return false; - } - - /** - * setData - * doctrine uses this function internally - * users are strongly discouraged to use this function - * - * @param array $data internal data - * @return void - */ - public function setData(array $data) - { - $this->data = $data; - } - - /** - * returns the maximum primary key value - * - * @return integer - */ - final public function getMaxIdentifier() - { - $sql = "SELECT MAX(".$this->getIdentifier().") FROM ".$this->getTableName(); - $stmt = $this->conn->getDBH()->query($sql); - $data = $stmt->fetch(PDO::FETCH_NUM); - return isset($data[0])?$data[0]:1; - } - - /** - * returns internal data, used by Doctrine_Record instances - * when retrieving data from database - * - * @return array - */ - final public function getData() - { - return $this->data; - } - - /** - * getter for associated tree - * - * @return mixed if tree return instance of Doctrine_Tree, otherwise returns false - */ - public function getTree() { - if (isset($this->options['treeImpl'])) { - if ( ! $this->tree) { - $options = isset($this->options['treeOptions']) ? $this->options['treeOptions'] : array(); - $this->tree = Doctrine_Tree::factory($this, - $this->options['treeImpl'], - $options - ); - } - return $this->tree; - } - return false; - } - public function getComponentName() - { - return $this->options['name']; - } - public function getTableName() - { - return $this->options['tableName']; - } - public function setTableName($tableName) - { - $this->options['tableName'] = $tableName; - } - - /** - * determine if table acts as tree - * - * @return mixed if tree return true, otherwise returns false - */ - public function isTree() { - return ( ! is_null($this->options['treeImpl'])) ? true : false; - } - - /** - * returns a string representation of this object - * - * @return string - */ - public function __toString() - { - return Doctrine_Lib::getTableAsString($this); - } -}