diff --git a/lib/Doctrine/Connection.php b/lib/Doctrine/Connection.php index 24ba2d1b3..dc171bcbb 100644 --- a/lib/Doctrine/Connection.php +++ b/lib/Doctrine/Connection.php @@ -195,16 +195,6 @@ abstract class Doctrine_Connection $this->_platform->setQuoteIdentifiers($this->_config->getQuoteIdentifiers()); } - /** - * Sets the Configuration used by the Connection. - * - * @param Doctrine::Common::Configuration $config - */ - public function setConfiguration(Doctrine_Configuration $config) - { - $this->_config = $config; - } - /** * Gets the Configuration used by the Connection. * @@ -218,16 +208,6 @@ abstract class Doctrine_Connection return $this->_config; } - /** - * Sets the EventManager used by the Connection. - * - * @param Doctrine::Common::EventManager $eventManager - */ - public function setEventManager(Doctrine_EventManager $eventManager) - { - $this->_eventManager = $eventManager; - } - /** * Gets the EventManager used by the Connection. * diff --git a/lib/Doctrine/DataDict.php b/lib/Doctrine/DataDict.php deleted file mode 100644 index dbc48d728..000000000 --- a/lib/Doctrine/DataDict.php +++ /dev/null @@ -1,99 +0,0 @@ -. - */ - -#namespace Doctrine::DBAL::DataDicts; - -/** - * Doctrine_DataDict - * - * @package Doctrine - * @subpackage DataDict - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.phpdoctrine.org - * @since 1.0 - * @version $Revision$ - * @author Konsta Vesterinen - * @author Lukas Smith (PEAR MDB2 library) - * @todo Merge all the DataDict classes into the appropriate DBAL DatabasePlatform classes. - */ -class Doctrine_DataDict extends Doctrine_Connection_Module -{ - /** - * Obtain an array of changes that may need to applied - * - * @param array $current new definition - * @param array $previous old definition - * @return array containing all changes that will need to be applied - */ - public function compareDefinition($current, $previous) - { - $type = !empty($current['type']) ? $current['type'] : null; - - if ( ! method_exists($this, "_compare{$type}Definition")) { - throw new Doctrine_DataDict_Exception('type "'.$current['type'].'" is not yet supported'); - } - - if (empty($previous['type']) || $previous['type'] != $type) { - return $current; - } - - $change = $this->{"_compare{$type}Definition"}($current, $previous); - - if ($previous['type'] != $type) { - $change['type'] = true; - } - - $previous_notnull = !empty($previous['notnull']) ? $previous['notnull'] : false; - $notnull = !empty($current['notnull']) ? $current['notnull'] : false; - if ($previous_notnull != $notnull) { - $change['notnull'] = true; - } - - $previous_default = array_key_exists('default', $previous) ? $previous['default'] : - ($previous_notnull ? '' : null); - $default = array_key_exists('default', $current) ? $current['default'] : - ($notnull ? '' : null); - if ($previous_default !== $default) { - $change['default'] = true; - } - - return $change; - } - - /** - * parseBoolean - * parses a literal boolean value and returns - * proper sql equivalent - * - * @param string $value boolean value to be parsed - * @return string parsed boolean value - */ - public function parseBoolean($value) - { - // parse booleans - if ($value == 'true') { - $value = 1; - } elseif ($value == 'false') { - $value = 0; - } - return $value; - } -} \ No newline at end of file diff --git a/lib/Doctrine/Manager.php b/lib/Doctrine/Manager.php deleted file mode 100644 index 2adf187a3..000000000 --- a/lib/Doctrine/Manager.php +++ /dev/null @@ -1,837 +0,0 @@ -. - */ - -/** - * - * Doctrine_Manager is the base component of all doctrine based projects. - * It opens and keeps track of all connections (database connections). - * - * @package Doctrine - * @subpackage Manager - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.phpdoctrine.org - * @since 1.0 - * @version $Revision$ - * @author Konsta Vesterinen - * @todo Remove. - */ -class Doctrine_Manager implements Doctrine_Configurable, Countable, IteratorAggregate -{ - /** - * @var array $connections an array containing all the opened connections - */ - protected $_connections = array(); - - /** - * @var array $bound an array containing all components that have a bound connection - */ - protected $_bound = array(); - - /** - * @var integer $index the incremented index - */ - protected $_index = 0; - - /** - * @var integer $currIndex the current connection index - */ - protected $_currIndex = 0; - - /** - * @var string $root root directory - */ - protected $_root; - - /** - * @var Doctrine_Query_Registry the query registry - */ - protected $_queryRegistry; - - /** - * - */ - protected static $driverMap = array('oci' => 'oracle'); - - /** - * constructor - * - * this is private constructor (use getInstance to get an instance of this class) - */ - private function __construct() - { - $this->_root = dirname(__FILE__); - } - - /** - * setDefaultAttributes - * sets default attributes - * - * @todo I do not understand the flow here. Explain or refactor? - * @return boolean - */ - public function setDefaultAttributes() - { - static $init = false; - if ( ! $init) { - $init = true; - $attributes = array( - Doctrine::ATTR_RESULT_CACHE => null, - Doctrine::ATTR_QUERY_CACHE => null, - Doctrine::ATTR_LOAD_REFERENCES => true, - Doctrine::ATTR_LISTENER => new Doctrine_EventListener(), - Doctrine::ATTR_RECORD_LISTENER => null, - Doctrine::ATTR_THROW_EXCEPTIONS => true, - Doctrine::ATTR_QUERY_LIMIT => Doctrine::LIMIT_RECORDS, - Doctrine::ATTR_IDXNAME_FORMAT => "%s_idx", - Doctrine::ATTR_SEQNAME_FORMAT => "%s_seq", - Doctrine::ATTR_TBLNAME_FORMAT => "%s", - Doctrine::ATTR_QUOTE_IDENTIFIER => false, - Doctrine::ATTR_SEQCOL_NAME => 'id', - Doctrine::ATTR_PORTABILITY => Doctrine::PORTABILITY_ALL, - Doctrine::ATTR_EXPORT => Doctrine::EXPORT_ALL, - Doctrine::ATTR_DECIMAL_PLACES => 2, - Doctrine::ATTR_DEFAULT_PARAM_NAMESPACE => 'doctrine' - ); - foreach ($attributes as $attribute => $value) { - $old = $this->getAttribute($attribute); - if ($old === null) { - $this->setAttribute($attribute,$value); - } - } - return true; - } - return false; - } - - public function hasAttribute($key) - { - return false; - } - - public function setAttribute($name, $value) {} - public function getAttribute($name) { - if ($name == Doctrine::ATTR_MODEL_LOADING) { - return Doctrine::MODEL_LOADING_CONSERVATIVE; - } - } - - /** - * returns the root directory of Doctrine - * - * @return string - * @todo Better name. - */ - final public function getRoot() - { - return $this->_root; - } - - /** - * getInstance - * returns an instance of this class - * (this class uses the singleton pattern) - * - * @return Doctrine_Manager - */ - public static function getInstance() - { - static $instance; - if ( ! isset($instance)) { - $instance = new self(); - } - return $instance; - } - - /** - * getQueryRegistry - * lazy-initializes the query registry object and returns it - * - * @return Doctrine_Query_Registry - */ - public function getQueryRegistry() - { - if ( ! isset($this->_queryRegistry)) { - $this->_queryRegistry = new Doctrine_Query_Registry; - } - return $this->_queryRegistry; - } - - /** - * setQueryRegistry - * sets the query registry - * - * @return Doctrine_Manager this object - */ - public function setQueryRegistry(Doctrine_Query_Registry $registry) - { - $this->_queryRegistry = $registry; - - return $this; - } - - /** - * fetch - * fetches data using the provided queryKey and - * the associated query in the query registry - * - * if no query for given queryKey is being found a - * Doctrine_Query_Registry exception is being thrown - * - * @param string $queryKey the query key - * @param array $params prepared statement params (if any) - * @return mixed the fetched data - */ - public function find($queryKey, $params = array(), $hydrationMode = Doctrine::HYDRATE_RECORD) - { - return Doctrine_Manager::getInstance() - ->getQueryRegistry() - ->get($queryKey) - ->execute($params, $hydrationMode); - } - - /** - * fetchOne - * fetches data using the provided queryKey and - * the associated query in the query registry - * - * if no query for given queryKey is being found a - * Doctrine_Query_Registry exception is being thrown - * - * @param string $queryKey the query key - * @param array $params prepared statement params (if any) - * @return mixed the fetched data - */ - public function findOne($queryKey, $params = array(), $hydrationMode = Doctrine::HYDRATE_RECORD) - { - return Doctrine_Manager::getInstance() - ->getQueryRegistry() - ->get($queryKey) - ->fetchOne($params, $hydrationMode); - } - - /** - * connection - * - * if the adapter parameter is set this method acts as - * a short cut for Doctrine_Manager::getInstance()->openConnection($adapter, $name); - * - * if the adapter paramater is not set this method acts as - * a short cut for Doctrine_Manager::getInstance()->getCurrentConnection() - * - * @param PDO|Doctrine_Adapter_Interface $adapter database driver - * @param string $name name of the connection, if empty numeric key is used - * @throws Doctrine_Manager_Exception if trying to bind a connection with an existing name - * @return Doctrine_Connection - */ - public static function connection($adapter = null, $name = null) - { - if ($adapter == null) { - return Doctrine_Manager::getInstance()->getCurrentConnection(); - } else { - return Doctrine_Manager::getInstance()->openConnection($adapter, $name); - } - } - - /** - * openConnection - * opens a new connection and saves it to Doctrine_Manager->connections - * - * @param PDO|Doctrine_Adapter_Interface $adapter database driver - * @param string $name name of the connection, if empty numeric key is used - * @throws Doctrine_Manager_Exception if trying to bind a connection with an existing name - * @throws Doctrine_Manager_Exception if trying to open connection for unknown driver - * @return Doctrine_Connection - */ - public function openConnection($adapter, $name = null, $setCurrent = true) - { - if (is_object($adapter)) { - if ( ! ($adapter instanceof PDO) && ! in_array('Doctrine_Adapter_Interface', class_implements($adapter))) { - throw new Doctrine_Manager_Exception("First argument should be an instance of PDO or implement Doctrine_Adapter_Interface"); - } - - $driverName = $adapter->getAttribute(Doctrine::ATTR_DRIVER_NAME); - } else if (is_array($adapter)) { - if ( ! isset($adapter[0])) { - throw new Doctrine_Manager_Exception('Empty data source name given.'); - } - $e = explode(':', $adapter[0]); - - if ($e[0] == 'uri') { - $e[0] = 'odbc'; - } - - $parts['dsn'] = $adapter[0]; - $parts['scheme'] = $e[0]; - $parts['user'] = (isset($adapter[1])) ? $adapter[1] : null; - $parts['pass'] = (isset($adapter[2])) ? $adapter[2] : null; - - $driverName = $e[0]; - $adapter = $parts; - } else { - $parts = $this->parseDsn($adapter); - $driverName = $parts['scheme']; - $adapter = $parts; - } - - // initialize the default attributes - $this->setDefaultAttributes(); - - if ($name !== null) { - $name = (string) $name; - if (isset($this->_connections[$name])) { - if ($setCurrent) { - $this->_currIndex = $name; - } - return $this->_connections[$name]; - } - } else { - $name = $this->_index; - $this->_index++; - } - - $drivers = array('mysql' => 'Doctrine_Connection_Mysql', - 'sqlite' => 'Doctrine_Connection_Sqlite', - 'pgsql' => 'Doctrine_Connection_Pgsql', - 'oci' => 'Doctrine_Connection_Oracle', - 'oci8' => 'Doctrine_Connection_Oracle', - 'oracle' => 'Doctrine_Connection_Oracle', - 'mssql' => 'Doctrine_Connection_Mssql', - 'dblib' => 'Doctrine_Connection_Mssql', - 'firebird' => 'Doctrine_Connection_Firebird', - 'informix' => 'Doctrine_Connection_Informix', - 'mock' => 'Doctrine_Connection_Mock'); - - if ( ! isset($drivers[$driverName])) { - throw new Doctrine_Manager_Exception('Unknown driver ' . $driverName); - } - - $className = $drivers[$driverName]; - $conn = new $className($adapter); - $conn->setName($name); - - $this->_connections[$name] = $conn; - - if ($setCurrent) { - $this->_currIndex = $name; - } - return $this->_connections[$name]; - } - - /** - * parsePdoDsn - * - * @param array $dsn An array of dsn information - * @return array The array parsed - * @todo package:dbal - */ - public function parsePdoDsn($dsn) - { - $parts = array(); - - $names = array('dsn', 'scheme', 'host', 'port', 'user', 'pass', 'path', 'query', 'fragment'); - - foreach ($names as $name) { - if ( ! isset($parts[$name])) { - $parts[$name] = null; - } - } - - $e = explode(':', $dsn); - $parts['scheme'] = $e[0]; - $parts['dsn'] = $dsn; - - $e = explode(';', $e[1]); - foreach ($e as $string) { - if ($string) { - $e2 = explode('=', $string); - - if (isset($e2[0]) && isset($e2[1])) { - list($key, $value) = $e2; - $parts[$key] = $value; - } - } - } - - return $parts; - } - - /** - * parseDsn - * - * @param string $dsn - * @return array Parsed contents of DSN - * @todo package:dbal - */ - public function parseDsn($dsn) - { - // fix sqlite dsn so that it will parse correctly - if (false !== strpos($dsn, ':///')) { - // replace windows directory separators - $dsn = str_replace("\\", "/", $dsn); - // replace file:/// format with parse_url()-compatible file:// - $dsn = str_replace(":///", "://", $dsn); - } - - // silence any warnings - $parts = @parse_url($dsn); - - $names = array('dsn', '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_Manager_Exception('Empty data source name'); - } - - switch ($parts['scheme']) { - case 'sqlite': - case 'sqlite2': - case 'sqlite3': - if (isset($parts['host']) && $parts['host'] == ':memory') { - $parts['database'] = ':memory:'; - $parts['dsn'] = 'sqlite::memory:'; - } else { - //fix windows dsn we have to add host: to path and set host to null - if (isset($parts['host'])) { - $parts['path'] = $parts['host'] . ":" . $parts["path"]; - $parts["host"] = null; - } - $parts['database'] = $parts['path']; - $parts['dsn'] = $parts['scheme'] . ':' . $parts['path']; - } - - break; - - case 'mssql': - case 'dblib': - if ( ! isset($parts['path']) || $parts['path'] == '/') { - throw new Doctrine_Manager_Exception('No database available in data source name'); - } - if (isset($parts['path'])) { - $parts['database'] = substr($parts['path'], 1); - } - if ( ! isset($parts['host'])) { - throw new Doctrine_Manager_Exception('No hostname set in data source name'); - } - - if (isset(self::$driverMap[$parts['scheme']])) { - $parts['scheme'] = self::$driverMap[$parts['scheme']]; - } - - $parts['dsn'] = $parts['scheme'] . ':host=' - . $parts['host'] . (isset($parts['port']) ? ':' . $parts['port']:null) . ';dbname=' - . $parts['database']; - - break; - - case 'mysql': - case 'informix': - case 'oci8': - case 'oci': - case 'firebird': - case 'pgsql': - case 'odbc': - case 'mock': - case 'oracle': - if ( ! isset($parts['path']) || $parts['path'] == '/') { - throw new Doctrine_Manager_Exception('No database available in data source name'); - } - if (isset($parts['path'])) { - $parts['database'] = substr($parts['path'], 1); - } - if ( ! isset($parts['host'])) { - throw new Doctrine_Manager_Exception('No hostname set in data source name'); - } - - if (isset(self::$driverMap[$parts['scheme']])) { - $parts['scheme'] = self::$driverMap[$parts['scheme']]; - } - - $parts['dsn'] = $parts['scheme'] . ':host=' - . $parts['host'] . (isset($parts['port']) ? ';port=' . $parts['port']:null) . ';dbname=' - . $parts['database']; - - break; - default: - throw new Doctrine_Manager_Exception('Unknown driver '.$parts['scheme']); - } - - return $parts; - } - - /** - * getConnection - * @param integer $index - * @return object Doctrine_Connection - * @throws Doctrine_Manager_Exception if trying to get a non-existent connection - */ - public function getConnection($name) - { - if ( ! isset($this->_connections[$name])) { - throw new Doctrine_Manager_Exception('Unknown connection: ' . $name); - } - - return $this->_connections[$name]; - } - - /** - * Creates a new Doctrine_Query object that uses the currently active connection. - * - * @return Doctrine_Query - */ - public function createQuery($dql = "") - { - $query = new Doctrine_Query($this->getCurrentConnection()); - if ( ! empty($dql)) { - $query->parseQuery($dql); - } - - return $query; - } - - /** - * Creates a new native (SQL) query. - * - * @return Doctrine_RawSql - */ - public function createNativeQuery($sql = "") - { - $nativeQuery = new Doctrine_RawSql($this->getCurrentConnection()); - if ( ! empty($sql)) { - $nativeQuery->parseQuery($sql); - } - - return $nativeQuery; - } - - /** - * Creates a query object out of a registered, named query. - * - * @param string $name The name of the query. - * @return Doctrine_Query The query object. - */ - public function createNamedQuery($name) - { - return $this->_queryRegistry->get($name); - } - - /** - * getComponentAlias - * retrieves the alias for given component name - * if the alias couldn't be found, this method returns the given - * component name - * - * @param string $componentName - * @return string the component alias - */ - public function getComponentAlias($componentName) - { - if (isset($this->componentAliases[$componentName])) { - return $this->componentAliases[$componentName]; - } - - return $componentName; - } - - /** - * sets an alias for given component name - * very useful when building a large framework with a possibility - * to override any given class - * - * @param string $componentName the name of the component - * @param string $alias - * @return Doctrine_Manager - */ - public function setComponentAlias($componentName, $alias) - { - $this->componentAliases[$componentName] = $alias; - - return $this; - } - - /** - * getConnectionName - * - * @param Doctrine_Connection $conn connection object to be searched for - * @return string the name of the connection - */ - public function getConnectionName(Doctrine_Connection $conn) - { - return array_search($conn, $this->_connections, true); - } - - /** - * bindComponent - * binds given component to given connection - * this means that when ever the given component uses a connection - * it will be using the bound connection instead of the current connection - * - * @param string $componentName - * @param string $connectionName - * @return boolean - */ - public function bindComponent($componentName, $connectionName) - { - $this->_bound[$componentName] = $connectionName; - } - - /** - * getConnectionForComponent - * - * @param string $componentName - * @return Doctrine_Connection - */ - public function getConnectionForComponent($componentName = null) - { - if (isset($this->_bound[$componentName])) { - return $this->getConnection($this->_bound[$componentName]); - } - return $this->getCurrentConnection(); - } - - /** - * hasConnectionForComponent - * - * @param string $componentName - * @return boolean - */ - public function hasConnectionForComponent($componentName = null) - { - return isset($this->_bound[$componentName]); - } - - /** - * getTable - * this is the same as Doctrine_Connection::getTable() except - * that it works seamlessly in multi-server/connection environment - * - * @see Doctrine_Connection::getTable() - * @param string $componentName - * @return Doctrine_Table - * @deprecated - */ - public function getTable($componentName) - { - return $this->getConnectionForComponent($componentName)->getTable($componentName); - } - - /** - * getMapper - * Returns the mapper object for the given component name. - * - * @param string $componentName - * @return Doctrine_Mapper - */ - public function getMapper($componentName) - { - return $this->getConnectionForComponent($componentName)->getEntityPersister($componentName); - } - - /** - * table - * this is the same as Doctrine_Connection::getTable() except - * that it works seamlessly in multi-server/connection environment - * - * @see Doctrine_Connection::getTable() - * @param string $componentName - * @return Doctrine_Table - */ - public static function table($componentName) - { - return Doctrine_Manager::getInstance() - ->getConnectionForComponent($componentName) - ->getTable($componentName); - } - - /** - * closes the connection - * - * @param Doctrine_Connection $connection - * @return void - */ - public function closeConnection(Doctrine_Connection $connection) - { - $connection->close(); - - $key = array_search($connection, $this->_connections, true); - - if ($key !== false) { - unset($this->_connections[$key]); - } - $this->_currIndex = key($this->_connections); - - unset($connection); - } - - /** - * getConnections - * returns all opened connections - * - * @return array - */ - public function getConnections() - { - return $this->_connections; - } - - /** - * setCurrentConnection - * sets the current connection to $key - * - * @param mixed $key the connection key - * @throws InvalidKeyException - * @return void - */ - public function setCurrentConnection($key) - { - $key = (string) $key; - if ( ! isset($this->_connections[$key])) { - throw new InvalidKeyException(); - } - $this->_currIndex = $key; - } - - /** - * contains - * whether or not the manager contains specified connection - * - * @param mixed $key the connection key - * @return boolean - */ - public function contains($key) - { - return isset($this->_connections[$key]); - } - - /** - * count - * returns the number of opened connections - * - * @return integer - * @todo This is unintuitive. - */ - public function count() - { - return count($this->_connections); - } - - /** - * getIterator - * returns an ArrayIterator that iterates through all connections - * - * @return ArrayIterator - */ - public function getIterator() - { - return new ArrayIterator($this->_connections); - } - - /** - * getCurrentConnection - * returns the current connection - * - * @throws Doctrine_Connection_Exception if there are no open connections - * @return Doctrine_Connection - */ - public function getCurrentConnection() - { - $i = $this->_currIndex; - if ( ! isset($this->_connections[$i])) { - throw new Doctrine_Connection_Exception(); - } - return $this->_connections[$i]; - } - - /** - * createDatabases - * - * Creates databases for connections - * - * @param string $specifiedConnections Array of connections you wish to create the database for - * @return void - * @todo package:dbal - */ - public function createDatabases($specifiedConnections = array()) - { - if ( ! is_array($specifiedConnections)) { - $specifiedConnections = (array) $specifiedConnections; - } - - $results = array(); - - foreach ($this as $name => $connection) { - if ( ! empty($specifiedConnections) && !in_array($name, $specifiedConnections)) { - continue; - } - - $results[$name] = $connection->createDatabase(); - } - - return $results; - } - - /** - * dropDatabases - * - * Drops databases for connections - * - * @param string $specifiedConnections Array of connections you wish to drop the database for - * @return void - * @todo package:dbal - */ - public function dropDatabases($specifiedConnections = array()) - { - if ( ! is_array($specifiedConnections)) { - $specifiedConnections = (array) $specifiedConnections; - } - - $results = array(); - - foreach ($this as $name => $connection) { - if ( ! empty($specifiedConnections) && !in_array($name, $specifiedConnections)) { - continue; - } - - $results[$name] = $connection->dropDatabase(); - } - - return $results; - } - - /** - * __toString - * returns a string representation of this object - * - * @return string - */ - public function __toString() - { - $r[] = "
";
-        $r[] = "Doctrine_Manager";
-        $r[] = "Connections : ".count($this->_connections);
-        $r[] = "
"; - return implode("\n",$r); - } -} diff --git a/lib/Doctrine/Overloadable.php b/lib/Doctrine/Overloadable.php deleted file mode 100644 index fc87ad04b..000000000 --- a/lib/Doctrine/Overloadable.php +++ /dev/null @@ -1,45 +0,0 @@ -. - */ - -/** - * Doctrine_Overloadable - * a very generic overloading interface - * - * @package Doctrine - * @subpackage Overloadable - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.phpdoctrine.org - * @since 1.0 - * @version $Revision$ - * @author Konsta Vesterinen - * @todo Remove. - */ -interface Doctrine_Overloadable { - /** - * __call - * method overloader - * - * @param string $m the name of the method - * @param array $a method arguments - * @return mixed anything - */ - public function __call($m, $a); -} \ No newline at end of file diff --git a/lib/Doctrine/Query_old.php b/lib/Doctrine/Query_old.php deleted file mode 100644 index 780736104..000000000 --- a/lib/Doctrine/Query_old.php +++ /dev/null @@ -1,590 +0,0 @@ -. - */ -Doctrine::autoload('Doctrine_Query_Abstract'); -/** - * Doctrine_Query - * A Doctrine_Query object represents a DQL query. It is used to query databases for - * data in an object-oriented fashion. A DQL query understands relations and inheritance - * and is dbms independant. - * - * @package Doctrine - * @subpackage Query - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.phpdoctrine.org - * @since 1.0 - * @version $Revision$ - * @author Konsta Vesterinen - * @todo Proposal: This class does far too much. It should have only 1 task: Collecting - * the DQL query parts and the query parameters (the query state and caching options/methods - * can remain here, too). - * The actual SQL construction could be done by a separate object (Doctrine_Query_SqlBuilder?) - * whose task it is to convert DQL into SQL. - * Furthermore the SqlBuilder? can then use other objects (Doctrine_Query_Tokenizer?), - * (Doctrine_Query_Parser(s)?) to accomplish his work. Doctrine_Query does not need - * to know the tokenizer/parsers. There could be extending - * implementations of SqlBuilder? that cover the specific SQL dialects. - * This would release Doctrine_Connection and the Doctrine_Connection_xxx classes - * from this tedious task. - * This would also largely reduce the currently huge interface of Doctrine_Query(_Abstract) - * and better hide all these transformation internals from the public Query API. - * - * @internal The lifecycle of a Query object is the following: - * After construction the query object is empty. Through using the fluent - * query interface the user fills the query object with DQL parts and query parameters. - * These get collected in {@link $_dqlParts} and {@link $_params}, respectively. - * When the query is executed the first time, or when {@link getSqlQuery()} - * is called the first time, the collected DQL parts get parsed and the resulting - * connection-driver specific SQL is generated. The generated SQL parts are - * stored in {@link $_sqlParts} and the final resulting SQL query is stored in - * {@link $_sql}. - */ -class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Serializable -{ - /** - * @var array - */ - protected $_subqueryAliases = array(); - - /** - * @var array $_aggregateAliasMap an array containing all aggregate aliases, keys as dql aliases - * and values as sql aliases - */ - protected $_aggregateAliasMap = array(); - - /** - * @param boolean $needsSubquery - */ - protected $_needsSubquery = false; - - /** - * @param boolean $isSubquery whether or not this query object is a subquery of another - * query object - */ - protected $_isSubquery; - - /** - * @var array $_neededTables an array containing the needed table aliases - */ - protected $_neededTables = array(); - - /** - * @var array - */ - protected $_expressionMap = array(); - - /** - * @var string $_sql cached SQL query - */ - protected $_sql; - - protected $_dql; - - - /** - * create - * returns a new Doctrine_Query object - * - * @param Doctrine_Connection $conn optional connection parameter - * @return Doctrine_Query - */ - public static function create($conn = null) - { - return new Doctrine_Query($conn); - } - - /** - * Resets the query to the state just after it has been instantiated. - */ - public function reset() - { - $this->_neededTables = array(); - $this->_expressionMap = array(); - $this->_subqueryAliases = array(); - $this->_needsSubquery = false; - $this->_isLimitSubqueryUsed = false; - } - - /** - * 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; - } - - /** - * addEnumParam - * sets input parameter as an enumerated parameter - * - * @param string $key the key of the input parameter - * @return Doctrine_Query - */ - public function addEnumParam($key, $table = null, $column = null) - { - $array = (isset($table) || isset($column)) ? array($table, $column) : array(); - - if ($key === '?') { - $this->_enumParams[] = $array; - } else { - $this->_enumParams[$key] = $array; - } - } - - /** - * getEnumParams - * get all enumerated parameters - * - * @return array all enumerated parameters - */ - public function getEnumParams() - { - return $this->_enumParams; - } - - /** - * getDql - * returns the DQL query that is represented by this query object. - * - * the query is built from $_dqlParts - * - * @return string the DQL query - */ - public function getDql() - { - if ($this->_dql !== null) { - return $this->_dql; - } - - $q = ''; - $q .= ( ! empty($this->_dqlParts['select']))? 'SELECT ' . implode(', ', $this->_dqlParts['select']) : ''; - $q .= ( ! empty($this->_dqlParts['from']))? ' FROM ' . implode(' ', $this->_dqlParts['from']) : ''; - $q .= ( ! empty($this->_dqlParts['where']))? ' WHERE ' . implode(' AND ', $this->_dqlParts['where']) : ''; - $q .= ( ! empty($this->_dqlParts['groupby']))? ' GROUP BY ' . implode(', ', $this->_dqlParts['groupby']) : ''; - $q .= ( ! empty($this->_dqlParts['having']))? ' HAVING ' . implode(' AND ', $this->_dqlParts['having']) : ''; - $q .= ( ! empty($this->_dqlParts['orderby']))? ' ORDER BY ' . implode(', ', $this->_dqlParts['orderby']) : ''; - $q .= ( ! empty($this->_dqlParts['limit']))? ' LIMIT ' . implode(' ', $this->_dqlParts['limit']) : ''; - $q .= ( ! empty($this->_dqlParts['offset']))? ' OFFSET ' . implode(' ', $this->_dqlParts['offset']) : ''; - - return $q; - } - - /** - * getParams - * - * @return array - */ - public function getParams() - { - return array_merge($this->_params['join'], $this->_params['set'], $this->_params['where'], $this->_params['having']); - } - - /** - * setParams - * - * @param array $params - */ - public function setParams(array $params = array()) { - $this->_params = $params; - } - - /** - * fetchArray - * Convenience method to execute using array fetching as hydration mode. - * - * @param string $params - * @return array - */ - public function fetchArray($params = array()) { - return $this->execute($params, Doctrine::HYDRATE_ARRAY); - } - - /** - * fetchOne - * Convenience method to execute the query and return the first item - * of the collection. - * - * @param string $params Parameters - * @param int $hydrationMode Hydration mode - * @return mixed Array or Doctrine_Collection or false if no result. - */ - public function fetchOne($params = array(), $hydrationMode = null) - { - $collection = $this->execute($params, $hydrationMode); - - if (count($collection) === 0) { - return false; - } - - if ($collection instanceof Doctrine_Collection) { - return $collection->getFirst(); - } else if (is_array($collection)) { - return array_shift($collection); - } - - return false; - } - - /** - * isSubquery - * if $bool parameter is set this method sets the value of - * Doctrine_Query::$isSubquery. If this value is set to true - * the query object will not load the primary key fields of the selected - * components. - * - * If null is given as the first parameter this method retrieves the current - * value of Doctrine_Query::$isSubquery. - * - * @param boolean $bool whether or not this query acts as a subquery - * @return Doctrine_Query|bool - */ - public function isSubquery($bool = null) - { - if ($bool === null) { - return $this->_isSubquery; - } - - $this->_isSubquery = (bool) $bool; - return $this; - } - - /** - * getAggregateAlias - * - * @param string $dqlAlias the dql alias of an aggregate value - * @return string - * @deprecated - */ - public function getAggregateAlias($dqlAlias) - { - return $this->getSqlAggregateAlias($dqlAlias); - } - - /** - * getSqlAggregateAlias - * - * @param string $dqlAlias the dql alias of an aggregate value - * @return string - */ - public function getSqlAggregateAlias($dqlAlias) - { - if (isset($this->_aggregateAliasMap[$dqlAlias])) { - // mark the expression as used - $this->_expressionMap[$dqlAlias][1] = true; - - return $this->_aggregateAliasMap[$dqlAlias]; - } else if ( ! empty($this->_pendingAggregates)) { - $this->processPendingAggregates(); - - return $this->getSqlAggregateAlias($dqlAlias); - } else { - throw new Doctrine_Query_Exception('Unknown aggregate alias: ' . $dqlAlias); - } - } - - /** - * getDqlPart - * returns a specific DQL query part. - * - * @param string $queryPart the name of the query part - * @return string the DQL query part - * @todo Description: List which query parts exist or point to the method/property - * where they are listed. - */ - public function getDqlPart($queryPart) - { - if ( ! isset($this->_dqlParts[$queryPart])) { - throw new Doctrine_Query_Exception('Unknown query part ' . $queryPart); - } - - return $this->_dqlParts[$queryPart]; - } - - /** - * contains - * - * Method to check if a arbitrary piece of dql exists - * - * @param string $dql Arbitrary piece of dql to check for - * @return boolean - */ - public function contains($dql) - { - return stripos($this->getDql(), $dql) === false ? false : true; - } - - - public function parseSubquery($subquery) - { - $trimmed = trim($this->_tokenizer->bracketTrim($subquery)); - - // check for possible subqueries - if (substr($trimmed, 0, 4) == 'FROM' || substr($trimmed, 0, 6) == 'SELECT') { - // parse subquery - $trimmed = $this->createSubquery()->parseDqlQuery($trimmed)->getQuery(); - } else { - // parse normal clause - $trimmed = $this->parseClause($trimmed); - } - - return '(' . $trimmed . ')'; - } - - /** - * preQuery - * - * Empty template method to provide Query subclasses with the possibility - * to hook into the query building procedure, doing any custom / specialized - * query building procedures that are neccessary. - * - * @return void - */ - public function preQuery() - { - - } - - /** - * postQuery - * - * Empty template method to provide Query subclasses with the possibility - * to hook into the query building procedure, doing any custom / specialized - * post query procedures (for example logging) that are neccessary. - * - * @return void - */ - public function postQuery() - { - - } - - /** - * builds the sql query from the given parameters and applies things such as - * column aggregation inheritance and limit subqueries if needed - * - * @param array $params an array of prepared statement params (needed only in mysql driver - * when limit subquery algorithm is used) - * @return string the built sql query - */ - public function getSqlQuery($params = array()) - { - if ($this->_state === self::STATE_DIRTY) { - $this->parse(); - } - - return $this->_sql; - } - - public function parse() - { - $this->reset(); - - // invoke the preQuery hook - $this->preQuery(); - - $parser = new Doctrine_Query_Parser($this); - $parser->parse(); - - if ($parser->isErrors()) { - throw new Doctrine_Query_Parser_Exception( - "Errors were detected during query parsing:\n" . - implode("\n", $parser->getErrors()) - ); - } - - $this->_state = self::STATE_CLEAN; - $this->_sql = $parser->getSql(); - } - - /** - * count - * fetches the count of the query - * - * This method executes the main query without all the - * selected fields, ORDER BY part, LIMIT part and OFFSET part. - * - * Example: - * Main query: - * SELECT u.*, p.phonenumber FROM User u - * LEFT JOIN u.Phonenumber p - * WHERE p.phonenumber = '123 123' LIMIT 10 - * - * The modified DQL query: - * SELECT COUNT(DISTINCT u.id) FROM User u - * LEFT JOIN u.Phonenumber p - * WHERE p.phonenumber = '123 123' - * - * @param array $params an array of prepared statement parameters - * @return integer the count of this query - */ - public function count($params = array()) - { - // triggers dql parsing/processing - $this->getQuery(); // this is ugly - - // initialize temporary variables - $where = $this->_sqlParts['where']; - $having = $this->_sqlParts['having']; - $groupby = $this->_sqlParts['groupby']; - $map = reset($this->_queryComponents); - $componentAlias = key($this->_queryComponents); - $table = $map['table']; - - // build the query base - $q = 'SELECT COUNT(DISTINCT ' . $this->getTableAlias($componentAlias) - . '.' . implode(',', $table->getIdentifierColumnNames()) - . ') AS num_results'; - - foreach ($this->_sqlParts['select'] as $field) { - if (strpos($field, '(') !== false) { - $q .= ', ' . $field; - } - } - - $q .= ' FROM ' . $this->_buildSqlFromPart(); - - // append discriminator column conditions (if any) - $string = $this->_createDiscriminatorConditionSql(); - if ( ! empty($string)) { - $where[] = $string; - } - - // append conditions - $q .= ( ! empty($where)) ? ' WHERE ' . implode(' AND ', $where) : ''; - $q .= ( ! empty($groupby)) ? ' GROUP BY ' . implode(', ', $groupby) : ''; - $q .= ( ! empty($having)) ? ' HAVING ' . implode(' AND ', $having): ''; - - if ( ! is_array($params)) { - $params = array($params); - } - // append parameters - $params = array_merge($this->_params['where'], $this->_params['having'], $params); - - $params = $this->convertEnums($params); - - $results = $this->getConnection()->fetchAll($q, $params); - - if (count($results) > 1) { - $count = 0; - foreach ($results as $result) { - $count += $result['num_results']; - } - } else { - $count = isset($results[0]) ? $results[0]['num_results']:0; - } - - return (int) $count; - } - - public function setDql($query) - { - $this->_dql = $query; - $this->_state = self::STATE_DIRTY; - } - - /** - * query - * query the database with DQL (Doctrine Query Language) - * - * @param string $query DQL query - * @param array $params prepared statement parameters - * @param int $hydrationMode Doctrine::FETCH_ARRAY or Doctrine::FETCH_RECORD - * @see Doctrine::FETCH_* constants - * @return mixed - */ - public function query($query, $params = array(), $hydrationMode = null) - { - $this->setDql($query); - return $this->execute($params, $hydrationMode); - } - - /** - * Copies a Doctrine_Query object. - * - * @param Doctrine_Query Doctrine query instance. - * If ommited the instance itself will be used as source. - * @return Doctrine_Query Copy of the Doctrine_Query instance. - */ - public function copy(Doctrine_Query $query = null) - { - if ( ! $query) { - $query = $this; - } - - $new = new Doctrine_Query(); - $new->_dqlParts = $query->_dqlParts; - $new->_params = $query->_params; - $new->_hydrator = $query->_hydrator; - - return $new; - } - - /** - * Frees the resources used by the query object. It especially breaks a - * cyclic reference between the query object and it's parsers. This enables - * PHP's current GC to reclaim the memory. - * This method can therefore be used to reduce memory usage when creating a lot - * of query objects during a request. - * - * @return Doctrine_Query this object - */ - public function free() - { - $this->reset(); - $this->_parsers = array(); - $this->_dqlParts = array(); - $this->_enumParams = array(); - } - - /** - * 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) - { - - } -} diff --git a/lib/Doctrine/RawSql.php b/lib/Doctrine/RawSql.php deleted file mode 100644 index 657c33362..000000000 --- a/lib/Doctrine/RawSql.php +++ /dev/null @@ -1,341 +0,0 @@ -. - */ - -/** - * Doctrine_RawSql - * - * Doctrine_RawSql is an implementation of Doctrine_Query_Abstract that skips the entire - * DQL parsing procedure. The "DQL" that is passed to a RawSql query object for execution - * is considered to be plain SQL and will be used "as is". The only query part that is special - * in a RawSql query is the SELECT part, which has a special syntax that provides Doctrine - * with the necessary information to properly hydrate the query results. - * - * @package Doctrine - * @subpackage RawSql - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.phpdoctrine.org - * @since 1.0 - * @version $Revision$ - * @author Konsta Vesterinen - * @deprecated Reimplement in NativeQuery with a more complete & robust implementation. - */ -class Doctrine_RawSql extends Doctrine_Query_Abstract -{ - /** - * @var array $fields - */ - private $fields = array(); - - /** - * @deprecated - */ - public function parseQueryPart($queryPartName, $queryPart, $append = false) - { - return $this->parseDqlQueryPart($queryPartName, $queryPart, $append); - } - - /** - * parseDqlQueryPart - * parses given DQL query part. Overrides Doctrine_Query_Abstract::parseDqlQueryPart(). - * This implementation does no parsing at all, except of the SELECT portion of the query - * which is special in RawSql queries. The entire remaining parts are used "as is", so - * the user of the RawSql query is responsible for writing SQL that is portable between - * different DBMS. - * - * @param string $queryPartName the name of the query part - * @param string $queryPart query part to be parsed - * @param boolean $append whether or not to append the query part to its stack - * if false is given, this method will overwrite - * the given query part stack with $queryPart - * @return Doctrine_Query this object - */ - public function parseDqlQueryPart($queryPartName, $queryPart, $append = false) - { - if ($queryPartName == 'select') { - $this->_parseSelectFields($queryPart); - return $this; - } - if ( ! isset($this->parts[$queryPartName])) { - $this->_sqlParts[$queryPartName] = array(); - } - - if ( ! $append) { - $this->_sqlParts[$queryPartName] = array($queryPart); - } else { - $this->_sqlParts[$queryPartName][] = $queryPart; - } - - return $this; - } - - /** - * Adds a DQL query part. Overrides Doctrine_Query_Abstract::_addDqlQueryPart(). - * This implementation for RawSql parses the new parts right away, generating the SQL. - */ - protected function _addDqlQueryPart($queryPartName, $queryPart, $append = false) - { - return $this->parseQueryPart($queryPartName, $queryPart, $append); - } - - /** - * Add select parts to fields. - * - * @param $queryPart sting The name of the querypart - */ - private function _parseSelectFields($queryPart){ - preg_match_all('/{([^}{]*)}/U', $queryPart, $m); - $this->fields = $m[1]; - $this->_sqlParts['select'] = array(); - } - - - public function parseQuery($query) - { - return $this->parseDqlQuery($query); - } - - /** - * parseDqlQuery - * parses an sql query and adds the parts to internal array. - * Overrides Doctrine_Query_Abstract::parseDqlQuery(). - * This implementation simply tokenizes the provided query string and uses them - * as SQL parts right away. - * - * @param string $query query to be parsed - * @return Doctrine_RawSql this object - */ - public function parseDqlQuery($query) - { - $this->_parseSelectFields($query); - $this->clear(); - - $tokens = $this->_tokenizer->sqlExplode($query, ' '); - - $parts = array(); - foreach ($tokens as $key => $part) { - $partLowerCase = strtolower($part); - switch ($partLowerCase) { - case 'select': - case 'from': - case 'where': - case 'limit': - case 'offset': - case 'having': - $type = $partLowerCase; - if ( ! isset($parts[$partLowerCase])) { - $parts[$partLowerCase] = array(); - } - break; - case 'order': - case 'group': - $i = $key + 1; - if (isset($tokens[$i]) && strtolower($tokens[$i]) === 'by') { - $type = $partLowerCase . 'by'; - $parts[$type] = array(); - } else { - //not a keyword so we add it to the previous type - $parts[$type][] = $part; - } - break; - case 'by': - continue; - default: - //not a keyword so we add it to the previous type. - if ( ! isset($parts[$type][0])) { - $parts[$type][0] = $part; - } else { - // why does this add to index 0 and not append to the - // array. If it had done that one could have used - // parseQueryPart. - $parts[$type][0] .= ' '.$part; - } - } - } - - $this->_sqlParts = $parts; - $this->_sqlParts['select'] = array(); - - return $this; - } - - /** - * getSqlQuery - * builds the sql query. - * - * @return string the built sql query - */ - public function getSqlQuery($params = array()) - { - $select = array(); - - 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'); - } - // try to auto-add component - if ( ! $this->hasSqlTableAlias($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.'); - } - } - - $componentAlias = $this->getComponentAlias($e[0]); - - if ($e[1] == '*') { - foreach ($this->_queryComponents[$componentAlias]['table']->getColumnNames() as $name) { - $field = $e[0] . '.' . $name; - - $select[$componentAlias][$field] = $field . ' AS ' . $e[0] . '__' . $name; - } - } else { - $field = $e[0] . '.' . $e[1]; - $select[$componentAlias][$field] = $field . ' AS ' . $e[0] . '__' . $e[1]; - } - } - - // force-add all primary key fields - - foreach ($this->getTableAliasMap() as $tableAlias => $componentAlias) { - $map = $this->_queryComponents[$componentAlias]; - - foreach ((array) $map['table']->getIdentifierColumnNames() as $key) { - $field = $tableAlias . '.' . $key; - - if ( ! isset($this->_sqlParts['select'][$field])) { - $select[$componentAlias][$field] = $field . ' AS ' . $tableAlias . '__' . $key; - } - } - } - - // first add the fields of the root component - reset($this->_queryComponents); - $componentAlias = key($this->_queryComponents); - - $q = 'SELECT ' . implode(', ', $select[$componentAlias]); - unset($select[$componentAlias]); - - foreach ($select as $component => $fields) { - if ( ! empty($fields)) { - $q .= ', ' . implode(', ', $fields); - } - } - - $string = $this->_createDiscriminatorConditionSql(); - if ( ! empty($string)) { - $this->_sqlParts['where'][] = $string; - } - $copy = $this->_sqlParts; - unset($copy['select']); - - $q .= ( ! empty($this->_sqlParts['from']))? ' FROM ' . implode(' ', $this->_sqlParts['from']) : ''; - $q .= ( ! empty($this->_sqlParts['where']))? ' WHERE ' . implode(' AND ', $this->_sqlParts['where']) : ''; - $q .= ( ! empty($this->_sqlParts['groupby']))? ' GROUP BY ' . implode(', ', $this->_sqlParts['groupby']) : ''; - $q .= ( ! empty($this->_sqlParts['having']))? ' HAVING ' . implode(' AND ', $this->_sqlParts['having']) : ''; - $q .= ( ! empty($this->_sqlParts['orderby']))? ' ORDER BY ' . implode(', ', $this->_sqlParts['orderby']) : ''; - $q .= ( ! empty($this->_sqlParts['limit']))? ' LIMIT ' . implode(' ', $this->_sqlParts['limit']) : ''; - $q .= ( ! empty($this->_sqlParts['offset']))? ' OFFSET ' . implode(' ', $this->_sqlParts['offset']) : ''; - - if ( ! empty($string)) { - array_pop($this->_sqlParts['where']); - } - return $q; - } - - /** - * getFields - * returns the fields associated with this parser - * - * @return array all the fields associated with this parser - */ - public function getFields() - { - return $this->fields; - } - - /** - * addComponent - * - * @param string $tableAlias - * @param string $componentName - * @return Doctrine_RawSql - */ - public function addComponent($tableAlias, $path) - { - $tmp = explode(' ', $path); - $originalAlias = (count($tmp) > 1) ? end($tmp) : null; - - $e = explode('.', $tmp[0]); - - $fullPath = $tmp[0]; - $fullLength = strlen($fullPath); - - $table = null; - - $currPath = ''; - - if (isset($this->_queryComponents[$e[0]])) { - $table = $this->_queryComponents[$e[0]]['table']; - - $currPath = $parent = array_shift($e); - } - - foreach ($e as $k => $component) { - // get length of the previous path - $length = strlen($currPath); - - // build the current component path - $currPath = ($currPath) ? $currPath . '.' . $component : $component; - - $delimeter = substr($fullPath, $length, 1); - - // if an alias is not given use the current path as an alias identifier - if (strlen($currPath) === $fullLength && isset($originalAlias)) { - $componentAlias = $originalAlias; - } else { - $componentAlias = $currPath; - } - if ( ! isset($table)) { - $conn = Doctrine_Manager::getInstance() - ->getConnectionForComponent($component); - - $table = $conn->getClassMetadata($component); - $this->_queryComponents[$componentAlias] = array( - 'table' => $table, 'mapper' => $conn->getMapper($component)); - } else { - $relation = $table->getRelation($component); - - $this->_queryComponents[$componentAlias] = array( - 'table' => $relation->getTable(), - 'mapper' => $this->_conn->getMapper($component), - 'parent' => $parent, - 'relation' => $relation); - } - $this->addSqlTableAlias($tableAlias, $componentAlias); - - $parent = $currPath; - } - - return $this; - } -} diff --git a/lib/Doctrine/Relation.php b/lib/Doctrine/Relation.php deleted file mode 100644 index 3a945a0cb..000000000 --- a/lib/Doctrine/Relation.php +++ /dev/null @@ -1,391 +0,0 @@ -. - */ - -/** - * Doctrine_Relation - * This class represents a relation between components - * - * @package Doctrine - * @subpackage Relation - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.phpdoctrine.org - * @since 1.0 - * @version $Revision$ - * @author Konsta Vesterinen - * @deprecated - */ -abstract class Doctrine_Relation implements ArrayAccess -{ - /** - * RELATION CONSTANTS - */ - - /** - * constant for ONE_TO_ONE and MANY_TO_ONE aggregate relationships - */ - const ONE_AGGREGATE = 0; - - /** - * constant for ONE_TO_ONE and MANY_TO_ONE composite relationships - */ - const ONE_COMPOSITE = 1; - - /** - * constant for MANY_TO_MANY and ONE_TO_MANY aggregate relationships - */ - const MANY_AGGREGATE = 2; - - /** - * constant for MANY_TO_MANY and ONE_TO_MANY composite relationships - */ - const MANY_COMPOSITE = 3; - - const ONE = 0; - const MANY = 2; - - protected $definition = array('alias' => true, // relation alias - 'foreign' => true, // foreign column names - 'local' => true, // local column names - 'class' => true, // related(foreign) class name - 'type' => true, // relation type - 'table' => true, // related(foreign) table object - 'localTable' => true, // local table object - 'name' => false, - 'onDelete' => false, - 'onUpdate' => false, - 'deferred' => false, - 'deferrable' => false, - 'constraint' => false, - 'equal' => false, - 'refClass' => false, // the name of the association class (many-many) - 'refTable' => false, // the association table object (many-many) - ); - - /** - * The mapper of the foreign (related) class. - */ - protected $_foreignMapper; - - /** - * The mapper of the local class. - */ - protected $_localMapper; - - /** - * constructor - * - * @param array $definition an associative array with the following structure: - * name foreign key constraint name - * - * local the local field(s) - * - * foreign the foreign reference field(s) - * - * table the foreign table object - * - * localTable the local table object - * - * refTable the reference table object (if any) - * - * onDelete referential delete action - * - * onUpdate referential update action - * - * deferred deferred constraint checking - * - * alias relation alias - * - * type the relation type, either Doctrine_Relation::ONE or Doctrine_Relation::MANY - * - * constraint boolean value, true if the relation has an explicit referential integrity constraint - * - * The onDelete and onUpdate keys accept the following values: - * - * CASCADE: Delete or update the row from the parent table and automatically delete or - * update the matching rows in the child table. Both ON DELETE CASCADE and ON UPDATE CASCADE are supported. - * Between two tables, you should not define several ON UPDATE CASCADE clauses that act on the same column - * in the parent table or in the child table. - * - * SET NULL: Delete or update the row from the parent table and set the foreign key column or columns in the - * child table to NULL. This is valid only if the foreign key columns do not have the NOT NULL qualifier - * specified. Both ON DELETE SET NULL and ON UPDATE SET NULL clauses are supported. - * - * NO ACTION: In standard SQL, NO ACTION means no action in the sense that an attempt to delete or update a primary - * key value is not allowed to proceed if there is a related foreign key value in the referenced table. - * - * RESTRICT: Rejects the delete or update operation for the parent table. NO ACTION and RESTRICT are the same as - * omitting the ON DELETE or ON UPDATE clause. - * - * SET DEFAULT - */ - public function __construct(array $definition) - { - $def = array(); - foreach ($this->definition as $key => $val) { - if ( ! isset($definition[$key]) && $val) { - try { - throw new Exception(); - } catch (Exception $e) { - echo $e->getTraceAsString() . "
"; - } - throw new Doctrine_Exception($key . ' is required!'); - } - if (isset($definition[$key])) { - $def[$key] = $definition[$key]; - } else { - $def[$key] = null; - } - } - $this->definition = $def; - $this->_foreignMapper = $this->getTable()->getEntityManager()->getEntityPersister($def['class']); - } - - /** - * hasConstraint - * whether or not this relation has an explicit constraint - * - * @return boolean - */ - public function hasConstraint() - { - return ($this->definition['constraint'] || - ($this->definition['onUpdate']) || - ($this->definition['onDelete'])); - } - - public function isDeferred() - { - return $this->definition['deferred']; - } - - public function isDeferrable() - { - return $this->definition['deferrable']; - } - - public function isEqual() - { - return $this->definition['equal']; - } - - public function offsetExists($offset) - { - return isset($this->definition[$offset]); - } - - public function offsetGet($offset) - { - if (isset($this->definition[$offset])) { - return $this->definition[$offset]; - } - - return null; - } - - public function offsetSet($offset, $value) - { - if (isset($this->definition[$offset])) { - $this->definition[$offset] = $value; - } - } - - public function offsetUnset($offset) - { - $this->definition[$offset] = false; - } - - /** - * toArray - * - * @return array - */ - public function toArray() - { - return $this->definition; - } - - /** - * getAlias - * returns the relation alias - * - * @return string - */ - final public function getAlias() - { - return $this->definition['alias']; - } - - public function getRelationName() - { - return $this->definition['relName']; - } - - /** - * getTable - * returns the foreign table object - * - * @return object Doctrine_Table - */ - final public function getTable() - { - return Doctrine_EntityManagerFactory::getManager($this->definition['class']) - ->getClassMetadata($this->definition['class']); - } - - /** - * getType - * returns the relation type, either 0 or 1 - * - * @see Doctrine_Relation MANY_* and ONE_* constants - * @return integer - */ - final public function getType() - { - return $this->definition['type']; - } - - /** - * getTable - * returns the foreign table object - * - * @return object Doctrine_Table - */ - final public function getClassMetadata() - { - return Doctrine_EntityManagerFactory::getManager($this->definition['class']) - ->getClassMetadata($this->definition['class']); - } - - /** - * getLocal - * returns the name of the local column - * - * @return string - */ - final public function getLocal() - { - return $this->definition['local']; - } - - /** - * getLocalFieldName - * returns the field name of the local column - */ - final public function getLocalFieldName() - { - return $this->definition['localTable']->getFieldName($this->definition['local']); - } - - /** - * getForeign - * returns the name of the foreignkey column where - * the localkey column is pointing at - * - * @return string - */ - final public function getForeign() - { - return $this->definition['foreign']; - } - - /** - * getLocalFieldName - * returns the field name of the local column - */ - final public function getForeignFieldName() - { - return $this->definition['table']->getFieldName($this->definition['foreign']); - } - - /** - * isComposite - * returns whether or not this relation is a composite relation - * - * @return boolean - */ - final public function isComposite() - { - return ($this->definition['type'] == Doctrine_Relation::ONE_COMPOSITE || - $this->definition['type'] == Doctrine_Relation::MANY_COMPOSITE); - } - - /** - * isOneToOne - * returns whether or not this relation is a one-to-one relation - * - * @return boolean - */ - final public function isOneToOne() - { - return ($this->definition['type'] == Doctrine_Relation::ONE_AGGREGATE || - $this->definition['type'] == Doctrine_Relation::ONE_COMPOSITE); - } - - /** - * getRelationDql - * - * @param integer $count - * @return string - */ - public function getRelationDql($count) - { - $component = $this->getClassMetadata()->getComponentName(); - - $dql = 'FROM ' . $component - . ' WHERE ' . $component . '.' . $this->definition['foreign'] - . ' IN (' . substr(str_repeat('?, ', $count), 0, -2) . ')'; - - return $dql; - } - - public function getForeignComponentName() - { - return $this->definition['class']; - } - - /** - * fetchRelatedFor - * - * fetches a component related to given record - * - * @param Doctrine_Entity $record - * @return Doctrine_Entity|Doctrine_Collection - */ - abstract public function fetchRelatedFor(Doctrine_Entity $record); - - /** - * __toString - * - * @return string - */ - public function __toString() - { - $r[] = "
";
-        foreach ($this->definition as $k => $v) {
-            if (is_object($v)) {
-                $v = 'Object(' . get_class($v) . ')';
-            }
-            $r[] = $k . ' : ' . $v;
-        }
-        $r[] = "
"; - return implode("\n", $r); - } -} \ No newline at end of file