getBootstrap(); $this->_cache = $bootstrap->getResource('cache'); if ($adapter === null) { $adapter = $bootstrap->getResource('db'); } if (!$adapter instanceof AbstractAdapter) { throw new \RuntimeException("Could not create table. The database adapter must be an instance of \Cube\Db\Adapter\AbstractAdapter"); } if (empty($this->_name)) { $this->_name = strtolower(get_class()); } $adapterConfig = $adapter->getConfig(); if (isset($adapterConfig['prefix'])) { $this->_prefix = $adapterConfig['prefix']; } $this->setAdapter($adapter); } /** * * get table name * * @return string */ public function getName() { return $this->_name; } /** * * get table prefix * * @return string */ public function getPrefix() { return $this->_prefix; } /** * * set table prefix * * @param string $prefix * * @return $this */ public function setPrefix($prefix = null) { $this->_prefix = $prefix; return $this; } /** * * get database adapter * * @return \Cube\Db\Adapter\AbstractAdapter */ public function getAdapter() { return $this->_adapter; } /** * * set database adapter * * @param \Cube\Db\Adapter\AbstractAdapter $adapter * * @return $this * @throws \RuntimeException */ public function setAdapter($adapter) { if (!$adapter instanceof AbstractAdapter) { throw new \RuntimeException("Could not create table. The database adapter must be an instance of \Cube\Db\Adapter\AbstractAdapter"); } $this->_adapter = $adapter; return $this; } /** * * get row object class * * @return string */ public function getRowClass() { return $this->_rowClass; } /** * * set row object class * * @param string $rowClass * * @return $this */ public function setRowClass($rowClass) { $this->_rowClass = (string)$rowClass; return $this; } /** * * get rowset object class * * @return string */ public function getRowsetClass() { return $this->_rowsetClass; } /** * * set rowset object class * * @param string $rowsetClass * * @return $this */ public function setRowsetClass($rowsetClass) { $this->_rowsetClass = (string)$rowsetClass; return $this; } /** * * get the reference between the table and a requested table * * @param string $refTableClass * @param string $ruleKey * * @return array * @throws \RuntimeException */ public function getReference($refTableClass, $ruleKey = null) { if ($ruleKey !== null) { if (!isset($this->_referenceMap[$ruleKey])) { throw new \RuntimeException( sprintf("A reference rule with the name '%s' does not exist in the definition of '%s'.", $ruleKey, get_class($this))); } if ($this->_referenceMap[$ruleKey][self::REF_TABLE_CLASS] != $refTableClass) { throw new \RuntimeException( sprintf("The reference rule '%s' does not reference the table '%s'.", $ruleKey, $refTableClass)); } return $this->_referenceMap[$ruleKey]; } foreach ($this->_referenceMap as $reference) { if ($reference[self::REF_TABLE_CLASS] == $refTableClass) { return $reference; } } throw new \RuntimeException( sprintf("There is no reference from table '%s' to table '%s'.", get_class($this), $refTableClass)); } /** * * add a reference to the reference map of the table * * @param string $ruleKey * @param mixed $columns * @param string $refTableClass * @param mixed $refColumns * * @return $this */ public function setReference($ruleKey, $columns, $refTableClass, $refColumns) { $reference = array(self::COLUMNS => (array)$columns, self::REF_TABLE_CLASS => $refTableClass, self::REF_COLUMNS => (array)$refColumns); $this->_referenceMap[$ruleKey] = $reference; return $this; } /** * * set the reference map of the table * * @param array $referenceMap * * @return $this */ public function setReferenceMap(array $referenceMap) { $this->_referenceMap = $referenceMap; return $this; } /** * * get dependent tables * * @return array */ public function getDependentTables() { return $this->_dependentTables; } /** * * set dependent tables * * @param array $dependentTables * * @return $this */ public function setDependentTables(array $dependentTables) { $this->_dependentTables = $dependentTables; return $this; } /** * * create an instance of the select object * * @param array|string|\Cube\Db\Expr $cols The columns to select from this table. * * @return \Cube\Db\Select */ public function select($cols = '*') { $select = new Select($this->_adapter); $select->setPrefix($this->getPrefix()) ->from($this->_name, $cols); return $select; } /** * * Inserts a table row with specified data. * * @param array $data Column-value pairs. * * @return int the id of the inserted column. */ public function insert(array $data) { $this->_purgeQueriesCache(); $this->_adapter->insert($this->_prefix . $this->_name, $data); return $this->lastInsertId(); } /** * * Updates table rows with specified data based on a WHERE clause. * * @param array $data Column-value pairs. * @param mixed $where UPDATE WHERE clause(s). * * @return int The number of affected rows. */ public function update(array $data, $where) { $result = $this->_adapter->update($this->_prefix . $this->_name, $data, $where); if ($result > 0) { $this->_purgeQueriesCache(); } return $result; } /** * * delete table rows based on a WHERE clause. * * @param mixed $where DELETE WHERE clause(s). * * @return int The number of affected rows. */ public function delete($where) { $result = $this->_adapter->delete($this->_prefix . $this->_name, $where); if ($result > 0) { $this->_purgeQueriesCache(); } return $result; } /** * * fetches all matched rows * * @param string|\Cube\Db\Select $where SQL where clause, or a select object * @param string|array $order * @param int $count * @param int $offset * @param string|array $cache * * @return \Cube\Db\Table\Rowset\AbstractRowset */ public function fetchAll($where = null, $order = null, $count = null, $offset = null, $cache = null) { if (!$where instanceof Select) { $select = $this->select() ->where($where) ->order($order) ->limit($count, $offset); } else { $select = $where; } $cachedData = false; $cacheFile = null; $rows = null; // cacheQueries: if requested in method, if enabled for the table and if enabled globally $cacheQueries = ($cache !== null) ? $this->_getCache('cacheQueries') : false; if ($cacheQueries !== false) { $cacheFile = md5($select->assemble()); if (($data = $this->_cache->read($cacheFile, CacheAdapter::QUERIES)) !== false) { $cacheCol = (is_array($cache)) ? $cache[CacheAdapter::CACHE_COL] : $cache; $data = empty($data) ? array(0) : $data; $select->reset(Select::WHERE) ->where("{$cacheCol} IN (?)", $data); $cachedData = true; } } $stmt = $this->_adapter->query($select); $rows = $stmt->fetchAll(Db::FETCH_ASSOC); if ($cachedData === false) { if ($cacheQueries !== false) { $data = array(); $cacheWhere = (is_array($cache)) ? $cache[CacheAdapter::CACHE_WHERE] : $cache; foreach ($rows as $row) { $data[] = $row[$cacheWhere]; } $this->_cache->write($cacheFile, CacheAdapter::QUERIES, $data, self::QUERIES_CACHE_EXPIRES); } } $data = array( 'table' => $this, 'data' => $rows, ); return new $this->_rowsetClass($data); } /** * * fetch a single matched row from a result set * * @param string|\Cube\Db\Select $where SQL where clause, or a select object * @param string|array $order * @param int $offset * @param string $cacheId * * @return \Cube\Db\Table\Row\AbstractRow|null */ public function fetchRow($where = null, $order = null, $offset = null, $cacheId = null) { return $this->fetchAll($where, $order, 1, $offset, $cacheId)->getRow(0); } /** * * get the id resulted from an insert operation * * @return int */ public function lastInsertId() { return $this->_adapter->lastInsertId(); } /** * * returns table information * * @param string $key specific info part to return * * @throws \InvalidArgumentException * @return mixed */ public function info($key = null) { $this->_getPrimary(); $info = array( self::NAME => $this->_name, self::COLS => $this->_getCols(), self::PRIMARY => (array)$this->_primary, self::METADATA => $this->_metadata, self::REFERENCE_MAP => $this->_referenceMap, self::DEPENDENT_TABLES => $this->_dependentTables, ); if ($key === null) { return $info; } if (!array_key_exists($key, $info)) { throw new \InvalidArgumentException( sprintf("There is no table information for the key '%s'.", $key)); } return $info[$key]; } /** * * get table metadata * use cache if caching is enabled * * @return array */ protected function _getMetadata() { if (!count($this->_metadata)) { $cachedData = false; $cacheMetadata = $this->_getCache('cacheMetadata'); $cacheFile = null; if ($cacheMetadata !== false) { $cacheFile = md5("DESCRIBE " . $this->_prefix . $this->_name); } if ($cacheMetadata !== false) { if (($data = $this->_cache->read($cacheFile, CacheAdapter::METADATA)) !== false) { $this->_metadata = $data; $cachedData = true; } } if ($cachedData === false) { $this->_metadata = $this->_adapter->describeTable($this->_prefix . $this->_name); if ($cacheMetadata !== false) { $this->_cache->write($cacheFile, CacheAdapter::METADATA, $this->_metadata); } } } return $this->_metadata; } /** * * get cache * * @param string $key * * @return mixed */ protected function _getCache($key = null) { if ($this->_cache !== false) { if ($key === null) { return $this->_cache; } else { $methodName = 'get' . ucfirst($key); if (method_exists($this->_cache, $methodName)) { if ($key != 'cacheQueries' || $this->_cacheableQueries) { return $this->_cache->$methodName(); } } } } return false; } /** * * purge queries cache * * @return $this */ protected function _purgeQueriesCache() { $cacheQueries = $this->_getCache('cacheQueries'); if ($cacheQueries !== false) { $this->_cache->getAdapter()->purge(CacheAdapter::QUERIES, true); } return $this; } /** * * get table columns * * @return array */ protected function _getCols() { if ($this->_cols === null) { $this->_cols = array_keys( $this->_getMetadata()); } return $this->_cols; } /** * * get primary key(s) * * @throws \RuntimeException * @return array */ protected function _getPrimary() { if (!$this->_primary) { $this->_getMetadata(); $this->_primary = array(); foreach ($this->_metadata as $col) { if ($col['PRIMARY']) { $this->_primary[$col['PRIMARY_POSITION']] = $col['COLUMN_NAME']; } } } else if (!is_array($this->_primary)) { $this->_primary = array(1 => $this->_primary); } else if (isset($this->_primary[0])) { array_unshift($this->_primary, null); unset($this->_primary[0]); } $cols = $this->_getCols(); if (!array_intersect((array)$this->_primary, $cols) == (array)$this->_primary) { throw new \RuntimeException( sprintf("Invalid primary key column(s): %s.", implode(',', (array)$this->_primary))); } return $this->_primary; } }