1 : <?php
2 : /**
3 : * PHPDevShell is a RAD Framework aimed at developing administrative applications.
4 : *
5 : * @package PHPDevShell
6 : * @link http://www.phpdevshell.org
7 : * @copyright Copyright (C) 2007 Jason Schoeman, All rights reserved.
8 : * @license GNU/LGPL, see readme/licensed_under_lgpl or http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
9 : *
10 : * Copyright notice: See readme/notice
11 : * By using PHPDevShell you agree to notice and license, if you dont agree to this notice/license you are not allowed to use PHPDevShell.
12 : *
13 : */
14 : /**
15 : * This is a blueprint for a connector, ie an object which handles the basic I/O to a database.
16 : * Its main use it to add a layer of exception throwing to mysql functions
17 : *
18 : * All of these methods are based on php-mysql interface function of the same name
19 : *
20 : * @author Greg
21 : *
22 : */
23 :
24 : interface PHPDS_dbConnector
25 : {
26 : public function free();
27 : public function connect();
28 : public function query($sql);
29 : public function protect($param);
30 : public function fetchAssoc();
31 : public function seek($row_number);
32 : public function numrows();
33 : public function affectedRows();
34 : public function lastId();
35 : public function rowResults();
36 : public function startTransaction();
37 : public function endTransaction($commit = true);
38 : }
39 :
40 :
41 : /* TODO: the inter-connection between this and $db is not really clean, but this aim is to make the whole process cleaner.
42 :
43 : /**
44 : *
45 : * NOTE: you're not supposed to deal with connectors any way
46 : *
47 : * @author Greg
48 : *
49 : */
50 : class PHPDS_PDOconnector extends PHPDS_dependant implements PHPDS_dbConnector
51 : {
52 : /**
53 : * @var php resource type the link for the mysql connection (as returned by mysql_connect)
54 : */
55 : private $link;
56 :
57 : /**
58 : * @var php resource type the result resource of a query (as returned by mysql_query)
59 : */
60 : private $result;
61 :
62 : /**
63 : * Dependence constructor.
64 : *
65 : * @param object $db the main db object
66 : * @return nothing
67 : */
68 : public function __construct ($dependance)
69 : {
70 1 : $this->PHPDS_dependance($dependance);
71 1 : }
72 :
73 : /**
74 : * Clears the current connection (useful for example if we're fetching one row at a time and we give up before the end)
75 : *
76 : * @return boolean, TRUE on success or FALSE on failure
77 : * @see includes/PHPDS_db_connector#free()
78 : */
79 : public function free()
80 : {
81 0 : if (!empty($this->result)) {
82 0 : mysql_free_result($this->result);
83 0 : $this->result = null;
84 0 : }
85 0 : }
86 :
87 : /**
88 : * Connect to the database server (compatibility method)
89 : *
90 : * @date 20100219
91 : * @version 1.0
92 : * @author greg
93 : * @see stable/phpdevshell/includes/PHPDS_db_connector#connect()
94 : */
95 : public function connect()
96 : {
97 : // TODO: get our independance from db parameters and get our own
98 : // Does user want a persistant connection?
99 20 : if ($this->configuration['persistent_db_connection'] == true) {
100 0 : $this->link = mysql_pconnect($this->db->server, $this->db->dbUsername, $this->db->dbPassword);
101 0 : } else {
102 20 : $this->link = mysql_connect($this->db->server, $this->db->dbUsername, $this->db->dbPassword);
103 : }
104 : // Create database link.
105 0 : $ok = mysql_select_db($this->db->dbName, $this->link);
106 : // Display error on link.
107 0 : if (empty($ok))
108 0 : throw new PHPDS_databaseException(mysql_error());
109 0 : elseif (!empty($this->configuration['database_charset']))
110 0 : mysql_set_charset($this->configuration['database_charset']);
111 0 : }
112 :
113 : /**
114 : * Actually send the query to MySQL (through $db)
115 : *
116 : * @date 20100219
117 : * @version 2.0.2
118 : * @author greg
119 : * @date 20100305 2.0.1 : fixed a bug with the _db_ prefix subsitution
120 : * @date 20100729 (greg) (2.0.2) throw error
121 : * @param $sql string, the actual sql query
122 : * @return php resource the resulting resource (or false is something bad happened)
123 : * @see includes/PHPDS_db_connector#query()
124 : */
125 : public function query($sql)
126 : {
127 20 : $template = $this->template;
128 : try {
129 20 : if (empty($this->link)) $this->connect();
130 : // Replace the DB prefix.
131 0 : $configuration = $this->configuration;
132 0 : $real_sql = preg_replace('/_db_/', $configuration['database_prefix'], $sql);
133 : // Run query.
134 : // TODO: this should NOT rely on template
135 0 : if (! isset($template->stopScript) && ! empty($real_sql)) {
136 : // Count Queries Used...
137 0 : $this->db->countQueries ++;
138 0 : $this->_log($real_sql);
139 0 : $this->result = mysql_query($real_sql, $this->link) or $template->stopScript = $this->returnSqlError($real_sql);
140 0 : if ($this->result == false) {
141 0 : throw new PHPDS_databaseException(mysql_error($this->link), mysql_errno($this->link));
142 : }
143 0 : return $this->result;
144 : } else {
145 0 : return false;
146 : }
147 : // TODO: check result validity for non-select requests
148 20 : } catch (Exception $e) {
149 20 : $msg = '<p>The MySQL database engine returned with an error (code '. $e->getCode() . ' - ' . $e->getMessage() . '</p>';
150 20 : throw new PHPDS_databaseException($msg, 0, $e);
151 : }
152 : }
153 :
154 : /**
155 : * Protect a single string from possible hacker (i.e. escape possible harmfull chars)
156 : *
157 : * @date 20100216
158 : * @version 1.0
159 : * @author greg
160 : * @param $param string, the parameter to espace
161 : * @return string, the escaped string
162 : * @see includes/PHPDS_db_connector#protect()
163 : */
164 : public function protect($param)
165 : {
166 0 : return mysql_real_escape_string($param);
167 : }
168 :
169 : /**
170 : * Return the next line as an associative array
171 : *
172 : * @date 20100216
173 : * @version 1.0
174 : * @author greg
175 : * @return array, the resulting line (or false is nothing is found)
176 : * @see includes/PHPDS_db_connector#fetch_assoc()
177 : */
178 : public function fetchAssoc()
179 : {
180 0 : if (is_resource($this->result)) return mysql_fetch_assoc($this->result);
181 0 : else return false;
182 : }
183 :
184 : /**
185 : * Move the internal pointer to the asked line
186 : *
187 : * @date 20100216
188 : * @version 1.0
189 : * @author greg
190 : * @param $row_number integer, the line number
191 : * @return boolean, TRUE on success or FALSE on failure
192 : * @see includes/PHPDS_db_connector#seek()
193 : */
194 : public function seek($row_number)
195 : {
196 0 : if (is_resource($this->result)) return mysql_data_seek($this->result, $row_number);
197 0 : else return false;
198 : }
199 :
200 : /**
201 : * Return the number of rows in the result of the query
202 : *
203 : * @date 20100216
204 : * @version 1.0
205 : * @author greg
206 : * @return integer, the number of rows
207 : * @see includes/PHPDS_db_connector#numrows()
208 : */
209 : public function numrows()
210 : {
211 0 : if (is_resource($this->result)) return mysql_num_rows($this->result);
212 0 : else return false;
213 : }
214 :
215 : /**
216 : * Return the number of affected rows in the result of the query
217 : *
218 : * @date 20101103
219 : * @version 1.0
220 : * @author Jason
221 : * @return integer, the number of affected rows
222 : * @see includes/PHPDS_db_connector#affectedRows()
223 : */
224 : public function affectedRows()
225 : {
226 0 : return mysql_affected_rows();
227 : }
228 :
229 : /**
230 : * This method returns the last MySQL error as a string if there is any. It will also
231 : * return the actual erroneous SQL statement if the display_sql_on_error property is
232 : * set to true. This is very helpfull when debugging an SQL related problem.
233 : *
234 : * @param string The actual query string.
235 : * @return string
236 : * @version 1.0.1
237 : * @date 20100329 prevent an exception if display_sql_on_error is not set
238 : * @author Don Schoeman <titan@phpdevshell.org>
239 : */
240 : public function returnSqlError ($query)
241 : {
242 0 : $result = mysql_error($this->link);
243 0 : if (empty($this->displaySqlOnError) && ! empty($result)) {
244 0 : $result = mysql_errno($this->link) . ": " . $result . '<br />' . $query;
245 0 : }
246 0 : return $result;
247 : }
248 :
249 : /**
250 : * Debugging Instance.
251 : *
252 : * @return debug object
253 : */
254 : public function debugInstance ($ignored = null)
255 : {
256 0 : return parent::debugInstance('db');
257 : }
258 :
259 : /**
260 : * Simply returns last inserted id from database.
261 : *
262 : * @date 20100610 (greg) (v1.0.1) added $this->link
263 : * @version 1.0.1
264 : * @author jason
265 : * @return int
266 : */
267 : public function lastId () {
268 0 : return mysql_insert_id($this->link);
269 : }
270 :
271 : /**
272 : * Will return a single row as a string depending on what column was selected.
273 : *
274 : * @date 17062010 (jason)
275 : * @version 1.0
276 : * @author jason
277 : * @return string
278 : */
279 : public function rowResults ($row = 0)
280 : {
281 0 : if (is_resource($this->result)) return mysql_result($this->result, $row);
282 0 : else return false;
283 : }
284 :
285 : /**
286 : * Start SQL transaction.
287 : */
288 : public function startTransaction()
289 : {
290 0 : return $this->query("START TRANSACTION");
291 : }
292 :
293 : /**
294 : * Ends SQL transaction.
295 : *
296 : * @param <type> $commit
297 : */
298 : public function endTransaction($commit = true)
299 : {
300 0 : if ($commit) {
301 0 : $this->query("COMMIT");
302 0 : } else {
303 0 : $this->query("ROLLBACK");
304 : }
305 0 : }
306 :
307 : }
|