summaryrefslogtreecommitdiff
path: root/framework/Data/DataGateway/TDataGatewayCommand.php
diff options
context:
space:
mode:
Diffstat (limited to 'framework/Data/DataGateway/TDataGatewayCommand.php')
-rw-r--r--framework/Data/DataGateway/TDataGatewayCommand.php340
1 files changed, 340 insertions, 0 deletions
diff --git a/framework/Data/DataGateway/TDataGatewayCommand.php b/framework/Data/DataGateway/TDataGatewayCommand.php
new file mode 100644
index 00000000..25666059
--- /dev/null
+++ b/framework/Data/DataGateway/TDataGatewayCommand.php
@@ -0,0 +1,340 @@
+<?php
+
+class TDataGatewayCommand extends TComponent
+{
+ private $_builder;
+
+ /**
+ * @param TDbCommandBuilder database specific database command builder.
+ */
+ public function __construct($builder)
+ {
+ $this->_builder = $builder;
+ }
+
+ /**
+ * @return TDbTableInfo
+ */
+ protected function getTableInfo()
+ {
+ return $this->_builder->getTableInfo();
+ }
+
+ /**
+ * @return TDbConnection
+ */
+ protected function getDbConnection()
+ {
+ return $this->_builder->getDbConnection();
+ }
+
+ /**
+ * @return TDbCommandBuilder
+ */
+ protected function getBuilder()
+ {
+ return $this->_builder;
+ }
+
+ /**
+ * Executes a delete command.
+ * @param TSqlCriteria delete conditions and parameters.
+ * @return integer number of records affected.
+ */
+ public function delete($criteria)
+ {
+ $where = $criteria->getCondition();
+ $parameters = $criteria->getParameters()->toArray();
+ $command = $this->getBuilder()->createDeleteCommand($where, $parameters);
+ $command->prepare();
+ return $command->execute();
+ }
+
+ /**
+ * Updates the table with new data.
+ * @param array date for update.
+ * @param TSqlCriteria update conditions and parameters.
+ * @return integer number of records affected.
+ */
+ public function update($data, $criteria)
+ {
+ $where = $criteria->getCondition();
+ $parameters = $criteria->getParameters()->toArray();
+ $command = $this->getBuilder()->createUpdateCommand($data,$where, $parameters);
+ $command->prepare();
+ return $command->execute();
+ }
+
+ /**
+ * Find one record matching the critera.
+ * @param TSqlCriteria find conditions and parameters.
+ * @return array matching record.
+ */
+ public function find($criteria)
+ {
+ return $this->getFindCommand($criteria)->queryRow();
+ }
+
+ /**
+ * Find one or more matching records.
+ * @param TSqlCriteria $criteria
+ * @return TDbDataReader record reader.
+ */
+ public function findAll($criteria)
+ {
+ return $this->getFindCommand($criteria)->query();
+ }
+
+ /**
+ * @param mixed primary key value, or composite key values as array.
+ * @return array matching record.
+ */
+ public function findByPk($keys)
+ {
+ list($where, $parameters) = $this->getPrimaryKeyCondition((array)$keys);
+ $command = $this->getBuilder()->createFindCommand($where, $parameters);
+ return $command->queryRow();
+ }
+
+ /**
+ * @param array multiple primary key values or composite value arrays
+ * @return TDbDataReader record reader.
+ */
+ public function findAllByPk($keys)
+ {
+ $where = $this->getCompositeKeyCondition((array)$keys);
+ $command = $this->getBuilder()->createFindCommand($where);
+ return $command->query();
+ }
+
+ /**
+ * @param array multiple primary key values or composite value arrays
+ * @return integer number of rows affected.
+ */
+ public function deleteByPk($keys)
+ {
+ $where = $this->getCompositeKeyCondition((array)$keys);
+ $command = $this->getBuilder()->createDeleteCommand($where);
+ $command->prepare();
+ return $command->execute();
+ }
+
+ /**
+ * Construct a "pk IN ('key1', 'key2', ...)" criteria.
+ * @param array values for IN predicate
+ * @param string SQL string for primary keys IN a list.
+ */
+ protected function getCompositeKeyCondition($values)
+ {
+ $primary = $this->getTableInfo()->getPrimaryKeys();
+ $count = count($primary);
+ if($count===0)
+ {
+ throw new TDbException('dbtablegateway_no_primary_key_found',
+ $this->getTableInfo()->getTableFullName());
+ }
+ if(!is_array($values) || count($values) === 0)
+ {
+ throw new TDbException('dbtablegateway_missing_pk_values',
+ $this->getTableInfo()->getTableFullName());
+ }
+ if($count>1 && !is_array($values[0]))
+ $values = array($values);
+ if($count > 1 && count($values[0]) !== $count)
+ {
+ throw new TDbException('dbtablegateway_pk_value_count_mismatch',
+ $this->getTableInfo()->getTableFullName());
+ }
+
+ $columns = array();
+ foreach($primary as $key)
+ $columns[] = $this->getTableInfo()->getColumn($key)->getColumnName();
+ return '('.implode(', ',$columns).') IN '.$this->quoteTuple($values);
+ }
+
+ /**
+ * @param TDbConnection database connection.
+ * @param array values
+ * @return string quoted recursive tuple values, e.g. "('val1', 'val2')".
+ */
+ protected function quoteTuple($array)
+ {
+ $conn = $this->getDbConnection();
+ $data = array();
+ foreach($array as $k=>$v)
+ $data[] = is_array($v) ? $this->quoteTuple($v) : $conn->quoteString($v);
+ return '('.implode(', ', $data).')';
+ }
+
+ /**
+ * Create the condition and parameters for find by primary.
+ * @param array primary key values
+ * @return array tuple($where, $parameters)
+ */
+ protected function getPrimaryKeyCondition($values)
+ {
+ $primary = $this->getTableInfo()->getPrimaryKeys();
+ if(count($primary)===0)
+ {
+ throw new TDbException('dbtablegateway_no_primary_key_found',
+ $this->getTableInfo()->getTableFullName());
+ }
+ $criteria=array();
+ $bindings=array();
+ $i = 0;
+ foreach($primary as $key)
+ {
+ $column = $this->getTableInfo()->getColumn($key)->getColumnName();
+ $criteria[] = $column.' = :'.$key;
+ $bindings[$key] = $values[$i++];
+ }
+ return array(implode(' AND ', $criteria), $bindings);
+ }
+
+ /**
+ * Find one or more matching records for arbituary SQL.
+ * @param TSqlCriteria $criteria
+ * @return TDbDataReader record reader.
+ */
+ public function findBySql($criteria)
+ {
+ return $this->getSqlCommand($criteria)->query();
+ }
+
+ /**
+ * Build sql command from the criteria. Limit, Offset and Ordering are applied if applicable.
+ * @param TSqlCriteria $criteria
+ * @return TDbCommand command corresponding to the criteria.
+ */
+ protected function getSqlCommand($criteria)
+ {
+ $sql = $criteria->getCondition();
+ $ordering = $criteria->getOrdersBy();
+ $limit = $criteria->getLimit();
+ $offset = $criteria->getOffset();
+ if(count($ordering) > 0)
+ $sql = $this->getBuilder()->applyOrdering($sql, $ordering);
+ if($limit>=0 || $offset>=0)
+ $sql = $this->getBuilder()->applyLimitOffset($sql, $limit, $offset);
+ $command = $this->getBuilder()->createCommand($sql);
+ $this->getBuilder()->bindArrayValues($command, $criteria->getParameters()->toArray());
+ return $command;
+ }
+
+ /**
+ * Build the find command from the criteria. Limit, Offset and Ordering are applied if applicable.
+ * @param TSqlCriteria $criteria
+ * @return TDbCommand.
+ */
+ protected function getFindCommand($criteria)
+ {
+ $where = $criteria->getCondition();
+ $parameters = $criteria->getParameters()->toArray();
+ $ordering = $criteria->getOrdersBy();
+ $limit = $criteria->getLimit();
+ $offset = $criteria->getOffset();
+ return $this->getBuilder()->createFindCommand($where,$parameters,$ordering,$limit,$offset);
+ }
+
+ /**
+ * @param TSqlCriteria $criteria
+ * @return integer number of records.
+ */
+ public function count($criteria)
+ {
+ if($criteria===null)
+ return intval($this->getBuilder()->createCountCommand()->queryScalar());
+ $where = $criteria->getCondition();
+ $parameters = $criteria->getParameters()->toArray();
+ $ordering = $criteria->getOrdersBy();
+ $limit = $criteria->getLimit();
+ $offset = $criteria->getOffset();
+ $command = $this->getBuilder()->createCountCommand($where,$parameters,$ordering,$limit,$offset);
+ return intval($command->queryScalar());
+ }
+
+ /**
+ * Inserts a new record into the table. Each array key must
+ * correspond to a column name in the table unless a null value is permitted.
+ * @param array new record data.
+ * @return mixed last insert id if one column contains a serial or sequence,
+ * otherwise true if command executes successfully and affected 1 or more rows.
+ */
+ public function insert($data)
+ {
+ $command=$this->getBuilder()->createInsertCommand($data);
+ $command->prepare();
+ if($command->execute() > 0)
+ {
+ $value = $this->getLastInsertId();
+ return $value !== null ? $value : true;
+ }
+ return false;
+ }
+
+ /**
+ * Iterate through all the columns and returns the last insert id of the
+ * first column that has a sequence or serial.
+ * @return mixed last insert id, null if none is found.
+ */
+ public function getLastInsertID()
+ {
+ foreach($this->getTableInfo()->getColumns() as $column)
+ {
+ if($column->hasSequence())
+ return $this->getDbConnection()->getLastInsertID($column->getSequenceName());
+ }
+ }
+
+ /**
+ * @param string __call method name
+ * @param string criteria conditions
+ * @param array method arguments
+ * @return TActiveRecordCriteria criteria created from the method name and its arguments.
+ */
+ public function createCriteriaFromString($method, $condition, $args)
+ {
+ $fields = $this->extractMatchingConditions($method, $condition);
+ $args=count($args) === 1 && is_array($args[0]) ? $args[0] : $args;
+ if(count($fields)>count($args))
+ {
+ throw new TDbException('dbtablegateway_mismatch_args_exception',
+ $method,count($fields),count($args));
+ }
+ return new TSqlCriteria(implode(' ',$fields), $args);
+ }
+
+ /**
+ * Calculates the AND/OR condition from dynamic method substrings using
+ * table meta data, allows for any AND-OR combinations.
+ * @param string dynamic method name
+ * @param string dynamic method search criteria
+ * @return array search condition substrings
+ */
+ protected function extractMatchingConditions($method, $condition)
+ {
+ $table = $this->getTableInfo();
+ $columns = $table->getLowerCaseColumnNames();
+ $regexp = '/('.implode('|', array_keys($columns)).')(and|_and_|or|_or_)?/i';
+ $matches = array();
+ if(!preg_match_all($regexp, strtolower($condition), $matches,PREG_SET_ORDER))
+ {
+ throw new TDbException('dbtablegateway_mismatch_column_name',
+ $method, implode(', ', $columns), $table->getTableFullName());
+ }
+
+ $fields = array();
+ foreach($matches as $match)
+ {
+ $key = $columns[$match[1]];
+ $column = $table->getColumn($key)->getColumnName();
+ $sql = $column . ' = ? ';
+ if(count($match) > 2)
+ $sql .= strtoupper(str_replace('_', '', $match[2]));
+ $fields[] = $sql;
+ }
+ return $fields;
+ }
+}
+
+?> \ No newline at end of file