. * * @category Main * @package RPMPHP * * @author Remi Collet * @author Johan Cwiklinski * @copyright 2010 Remi Collet * @license http://www.gnu.org/licenses/agpl-3.0-standalone.html AGPL License 3.0 or (at your option) any later version * @link http://github.com/remicollet/rpmphp/ * @since The begining of times. */ /** * Helper for simple query => use directly or through CommonTable::request() * * Freely inspired from DBmysqlIterator class from GLPI * (already written by Remi, and ported to PDO) * See http://www.glpi-project.org/ */ class TableIterator implements Iterator { private $con; private $sql; private $res = false; private $row; private $pos; /** * Constructor * * @param CommonDBTM $dbconnexion Database Connnexion * (must be a CommonDBTM object) * @param string $table table name or complete SQL request * @param string|array $crit string or array of filed/values, * ex array("id"=>1), if empty => all rows */ function __construct (PDO $dbconnexion, $table, $crit='') { $this->conn = $dbconnexion; if (is_string($table) && strpos($table, " ")) { $this->sql = $table; } else { // check field, orderby, limit, start in criterias $field=""; $orderby=""; $limit=0; $start=0; if (is_array($crit) && count($crit)) { foreach ($crit as $key => $val) { if ($key==="FIELDS") { $field = $val; unset($crit[$key]); } else if ($key==="ORDER") { $orderby = $val; unset($crit[$key]); } else if ($key==="LIMIT") { $limit = $val; unset($crit[$key]); } else if ($key==="START") { $start = $val; unset($crit[$key]); } } } // SELECT field list if (is_array($field)) { $this->sql = ""; foreach ($field as $t => $f) { if (is_numeric($t)) { $this->sql .= (empty($this->sql) ? "SELECT " : ",") . $f; } else if (is_array($f)) { $this->sql .= (empty($this->sql) ? "SELECT $t." : ",$t.") . implode(",$t.", $f); } else { $this->sql .= (empty($this->sql) ? "SELECT " : ",") . "$t.$f"; } } } else if (empty($field)) { $this->sql = "SELECT *"; } else { $this->sql = "SELECT `$field`"; } // FROM table list if (is_array($table)) { $this->sql .= " FROM `".implode("`, `", $table)."`"; } else { $this->sql .= " FROM `$table`"; } // WHERE criteria list if (!empty($crit)) { $this->sql .= " WHERE ".$this->_analyseCrit($crit); } // ORDER BY if (is_array($orderby)) { $this->sql .= " ORDER BY `".implode("`, `", $orderby)."`"; } else if (!empty($orderby)) { $this->sql .= " ORDER BY `$orderby`"; } if (is_numeric($limit) && $limit>0) { $this->sql .= " LIMIT $limit"; if (is_numeric($start) && $start>0) { $this->sql .= " OFFSET $start"; } } } //echo "SQL: ".$this->sql."\n"; $this->res = $this->conn->prepare($this->sql); if ($this->res===false) { $err = $this->db->errorInfo(); throw new Exception($err[2]); } $this->pos = -1; } /** * Class destructor */ function __destruct () { if ($this->res) { $this->res->closeCursor(); } } /** * Build WHERE clause * * @param string|array $crit To document * @param string $bool logical operator between criteria * * @return To document */ private function _analyseCrit ($crit, $bool="AND") { if (!is_array($crit)) { return $crit; } $ret = ""; foreach ($crit as $name => $value) { if (!empty($ret)) { $ret .= " $bool "; } if (is_numeric($name)) { // No Key case => recurse. $ret .= "(" . $this->_analyseCrit($value, $bool) . ")"; } else if ($name==="OR" || $name==="AND") { // Binary logical operator $ret .= "(" . $this->_analyseCrit($value, $name) . ")"; } else if ($name==="NOT") { // Uninary logicial operator $ret .= " NOT (" . $this->_analyseCrit($value, "AND") . ")"; } else if ($name==="FKEY") { // Foreign Key condition if (is_array($value) && count($value)==2) { reset($value); list($t1,$f1)=each($value); list($t2,$f2)=each($value); $ret .= (is_numeric($t1) ? "$f1" : "$t1.$f1") . "=" . (is_numeric($t2) ? "$f2" : "$t2.$f2"); } else { trigger_error("BAD FOREIGN KEY", E_USER_ERROR); } } else if (is_array($value)) { // Array of Value $ret .= "$name IN ('". implode("','", $value)."')"; } else if (is_null($value)) { // NULL condition $ret .= "$name IS NULL"; } else if (is_numeric($value)) { // Integer $ret .= "$name=$value"; } else { // String $ret .= "$name='$value'"; } } return $ret; } /** * Go to the begin of the request (launch it) * * @return hastable|false : next row */ public function rewind () { if ($this->res && $this->pos>=0) { $this->res->closeCursor(); $this->pos = -1; } if ($this->res && $this->pos<0) { if (!$this->res->execute()) { $err = $this->res->errorInfo(); throw new Exception($err[2]); } } return $this->next(); } /** * Retrieve current row * * @return hastable|false */ public function current() { return $this->row; } /** * Retrieve key of current row * * @return mixed */ public function key() { return (isset($this->row["id"]) ? $this->row["id"] : $this->pos); } /** * Retrieve next row * * @return hastable|false */ public function next() { if (!$this->res) { return false; } $this->row = $this->res->fetch(PDO::FETCH_ASSOC); $this->pos++; return $this->row; } /** * Is current row defined * * @return boolean */ public function valid() { return $this->res && $this->row; } /** * Compute number of rows * * @return integer */ public function numrows() { return ($this->res ? $this->res->rowCount() : 0); } } ?>