diff options
author | Johan "Papa" Cwiklinski <trasher@odysseus.(none)> | 2010-08-01 09:10:38 +0200 |
---|---|---|
committer | Johan "Papa" Cwiklinski <trasher@odysseus.(none)> | 2010-08-01 09:10:38 +0200 |
commit | b8307ab30e45b55d403f56ddf0a6715c00dd8d20 (patch) | |
tree | 146b7d1c713d9dbfdcfeaa98358a47cb0b99b775 /class/TableIterator.php | |
parent | 12b1b6ecf7c8cc0e6ff418443787d7c247aa413a (diff) | |
parent | 6e6d59bf0677c6b2d5b92a6abdab15a7ecaf9947 (diff) |
Report Remi's modifications
Diffstat (limited to 'class/TableIterator.php')
-rw-r--r-- | class/TableIterator.php | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/class/TableIterator.php b/class/TableIterator.php new file mode 100644 index 0000000..0903f37 --- /dev/null +++ b/class/TableIterator.php @@ -0,0 +1,286 @@ +<?php +/** + * Class which implement a simple Iterator over a PDO connexion + * + * PHP version 5 + * + * Copyright © 2010 Remi Collet + * + * This file is part of rpmphp. + * + * rpmphp is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * rpmphp is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with rpmphp. If not, see <http://www.gnu.org/licenses/>. + * + * @category Main + * @package RPMPHP + * + * @author Remi Collet <unknown@unknwown.com> + * @author Johan Cwiklinski <johan@x-tnd.be> + * @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); + } +} +?>
\ No newline at end of file |