summaryrefslogtreecommitdiffstats
path: root/class/TableIterator.php
diff options
context:
space:
mode:
authorJohan "Papa" Cwiklinski <trasher@odysseus.(none)>2010-08-01 09:10:38 +0200
committerJohan "Papa" Cwiklinski <trasher@odysseus.(none)>2010-08-01 09:10:38 +0200
commitb8307ab30e45b55d403f56ddf0a6715c00dd8d20 (patch)
tree146b7d1c713d9dbfdcfeaa98358a47cb0b99b775 /class/TableIterator.php
parent12b1b6ecf7c8cc0e6ff418443787d7c247aa413a (diff)
parent6e6d59bf0677c6b2d5b92a6abdab15a7ecaf9947 (diff)
Report Remi's modifications
Diffstat (limited to 'class/TableIterator.php')
-rw-r--r--class/TableIterator.php286
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