. * * @category Main * @package RPMPHP * * @author Remi Collet * @author Johan Cwiklinski * @copyright 2010-2014 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 https://git.remirepo.net/cgit/web/rpmphp.git/ * @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/ * * @category Main * @package RPMPHP * * @author Remi Collet * @author Johan Cwiklinski * @license http://www.gnu.org/licenses/agpl-3.0-standalone.html AGPL License 3.0 or (at your option) any later version * @link https://git.remirepo.net/cgit/web/rpmphp.git/ */ 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; $distinct = ''; if (is_array($crit) && count($crit)) { foreach ($crit as $key => $val) { if ($key==="FIELDS") { $field = $val; unset($crit[$key]); } else if ($key==="DISTINCT") { if ($val) { $distinct = $key; } 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 $distinct " : ",") . $f; } else if (is_array($f)) { $this->_sql .= (empty($this->_sql) ? "SELECT $distinct $t." : ",$t.") . implode(",$t.", $f); } else { $this->_sql .= (empty($this->_sql) ? "SELECT $distinct " : ",") . "$t.$f"; } } } else if (empty($field)) { $this->_sql = "SELECT *"; } else { $this->_sql = "SELECT $distinct `$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 if (($value[0]=='>' || $value[0]=='<') && is_numeric(substr($value,1))) { // > integer $ret .= "$name $value"; } else if (strpos($value,'%')===false){ // String $ret .= "$name=" . $this->_conn->quote($value); } else { // String with pattern $ret .= "$name LIKE " . $this->_conn->quote($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( "\nSQL: " . $this->_sql . "\nERROR: " . $err[2] . "\nCODE:" . $err[0] ); } } 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); } } ?>