source: sandbox/workflow/trunk/inc/engine/src/common/Base.php @ 2165

Revision 2165, 10.1 KB checked in by pedroerp, 14 years ago (diff)

Ticket #603 - Merged 2123:2132 /sandbox/workflow/branches/603 em /sandbox/workflow/trunk

  • Property svn:executable set to *
Line 
1<?php
2/**
3 * This class is derived by all the API classes so they get the
4 * database connection and the database methods.
5 *
6 * @package Galaxia
7 * @license http://www.gnu.org/copyleft/gpl.html GPL
8 */
9class Base {
10        /**
11         * @var object $db Database abstraction object used to access the database
12         * @access public
13         */
14        var $db;
15        /**
16         * @var int     $num_queries Debugging var
17         * @access private
18         */
19        var $num_queries = 0;
20        /**
21         * @var int     $num_queries_total Debugging var
22         * @access private
23         */
24        var $num_queries_total = 0;
25        /**
26         * @var array  $error Error messages
27         * @access public
28         */
29        var $error= Array();
30        /**
31         * @var array $warning Warning messages
32         * @access public
33         */
34        var $warning = array();
35        /**
36         * @var string $child_name Name of the current object
37         * @access public
38         */
39        var $child_name = 'Base';
40
41  /**
42   * Constructor receiving a database abstraction object
43   * @package Galaxia
44   * @param object &$db ADOdb
45   * @return object Base instance
46   * @access public
47   */
48  function Base(&$db)
49  {
50    if(!$db) {
51      die('Invalid db object passed to '.$this->child_name.' constructor');
52    }
53    //Force transactionnal mysql (Innodb) -> mysqlt
54    if ($db->databaseType=='mysql')
55    {
56        $GLOBALS['phpgw']->db->disconnect();
57        $db = $GLOBALS['phpgw']->db->connect(
58                        $GLOBALS['phpgw_info']['server']['db_name'],
59                        $GLOBALS['phpgw_info']['server']['db_host'],
60                        $GLOBALS['phpgw_info']['server']['db_port'],
61                        $GLOBALS['phpgw_info']['server']['db_user'],
62                        $GLOBALS['phpgw_info']['server']['db_pass'],
63                        'mysqlt'
64                );
65    }
66    $this->db = &$db;
67  }
68
69  /**
70   * Gets errors recorded by this object
71   * Always call this function after failed operations on a workflow object to obtain messages
72   *
73   * @param bool $as_array if true the result will be send as an array of errors or an empty array. Else, if you do not give any parameter
74   * or give a false parameter you will obtain a single string which can be empty or will contain error messages with <br /> html tags
75   * @param bool $debug is false by default, if true you wil obtain more messages
76   * @param string $prefix string appended to the debug message
77   * @return mixed Error and debug messages or an array of theses messages and empty the error messages
78   * @access public
79   */
80  function get_error($as_array=false, $debug=false, $prefix='')
81  {
82    //collect errors from used objects
83    $this->collect_errors($debug, $prefix.$this->child_name.'::');
84    if ($as_array)
85    {
86      $result = $this->error;
87      $this->error= Array();
88      return $result;
89    }
90    $result_str = implode('<br />',array_filter($this->error));
91    $this->error= Array();
92    return $result_str;
93  }
94
95  /**
96   * Gets warnings recorded by this object
97   *
98   * @param bool $as_array if true the result will be send as an array of warnings or an empty array. Else, if you do not give any parameter
99   * or give a false parameter you will obtain a single string which can be empty or will contain warning messages with <br /> html tags
100   * @return mixed Warning messages or an array of theses messages and empty the warning messages
101   * @access public
102   */
103  function get_warning($as_array=false)
104  {
105    if ($as_array)
106    {
107      $result = $this->warning;
108      $this->warning= Array();
109      return $result;
110    }
111    $result_str = implode('<br />',array_filter($this->warning));
112    $this->warning= Array();
113    return $result_str;
114  }
115
116  /**
117   * Collect errors from all linked objects which could have been used by this object
118   * Each child class should instantiate this function with her linked objetcs, calling get_error(true)
119   *
120   * @param bool $debug is false by default, if true debug messages can be added to 'normal' messages
121   * @param string $prefix is a string appended to the debug message
122   * @abstract
123   * @access public
124   * @return void
125   */
126  function collect_errors($debug=false, $prefix = '')
127  {
128        if ($debug)
129        {
130                $this->num_queries_total += $this->num_queries;
131                $this->error[] = $prefix.': number of queries: new='.$this->num_queries.'/ total='.$this->num_queries_total;
132                $this->num_queries = 0;
133        }
134  }
135
136        /**
137         * Performs a query on the AdoDB database object
138         *
139         * @param string $query sql query, parameters should be replaced with ?
140         * @param array $values array containing the parameters (going in the ?), use it to avoid security problems. If
141         * one of theses values is an array it will be serialized and encoded in Base64
142         * @param int $numrows maximum number of rows to return
143         * @param int $offset starting row number
144         * @param bool $reporterrors is true by default, if false no warning will be generated in the php log
145         * @param string $sort is the sort sql string for the query (without the "order by ")
146         * @param bool $bulk is false by default, if true the $values array parameters could contain arrays vars for bulk statement
147         * (see ADOdb help) theses arrays wont be serialized and encoded in Base64 like current arrays parameters,
148         * it will be checked for security reasons before being appended to the sql
149         * @return mixed false if something went wrong or the resulting recordset array if it was ok
150         * @access public
151         */
152        function query($query, $values = null, $numrows = -1, $offset = -1, $reporterrors = true, $sort='', $bulk=false)
153        {
154                //clean the parameters
155                $clean_values = Array();
156                if (!($values===null))
157                {
158                        if (!(is_array($values)))
159                        {
160                                $values= array($values);
161                        }
162                        foreach($values as $value)
163                        {
164                                $clean_values[] = $this->security_cleanup($value, !($bulk));
165                        }
166                }
167                //clean sort order as well and add it to the query
168                if (!(empty($sort)))
169                {
170                        $sort = $this->security_cleanup($sort, true, true);
171                        $query .= " order by $sort";
172                }
173
174
175                //conversion must be done after oder by is set
176                $this->convert_query($query);
177                // Galaxia needs to be call ADOdb in associative mode
178                $this->db->SetFetchMode(ADODB_FETCH_ASSOC);
179                if ($numrows == -1 && $offset == -1)
180                        $result = $this->db->Execute($query, $clean_values);
181                else
182                        $result = $this->db->SelectLimit($query, $numrows, $offset, $clean_values);
183                if (empty($result))
184                {
185                        $result = false;
186                }
187                $this->num_queries++;
188                if (!$result)
189                {
190                        $this->error[] = "there were some SQL errors in the database, please warn your sysadmin.";
191                        if ($reporterrors) $this->sql_error($query, $clean_values, $result);
192                }
193                return $result;
194        }
195
196        /**
197         * @see Base::query
198         * @param string $query sql query, parameters should be replaced with ?
199     * @param array $values array containing the parameters (going in the ?), use it to avoid security problems
200         * @param bool $reporterrors is true by default, if false no warning will be generated in the php log
201         * @return mixed NULL if something went wrong or the first value of the first row if it was ok
202         * @access public
203         */
204        function getOne($query, $values = null, $reporterrors = true) {
205                $this->convert_query($query);
206                $clean_values = Array();
207                if (!($values===null))
208                {
209                        if (!(is_array($values)))
210                        {
211                                $values= array($values);
212                        }
213                        foreach($values as $value)
214                        {
215                                $clean_values[] = $this->security_cleanup($value);
216                        }
217                }
218                $result = $this->db->SelectLimit($query, 1, 0, $clean_values);
219                if (empty($result))
220                {
221                        $result = false;
222                }
223                if (!$result && $reporterrors )
224                        $this->sql_error($query, $clean_values, $result);
225                if (!!$result)
226                {
227                        $res = $result->fetchRow();
228                }
229                else
230                {
231                        $res = false;
232                }
233                $this->num_queries++;
234                if ($res === false)
235                        return (NULL); //simulate pears behaviour
236                list($key, $value) = each($res);
237                return $value;
238        }
239
240        /**
241         * Throws error warnings
242         *
243         * @param string $query
244         * @param array $values
245         * @param mixed $result
246         * @access public
247         * @return void
248         */
249        function sql_error($query, $values, $result) {
250                trigger_error($this->db->databaseType . " error:  " . $this->db->ErrorMsg(). " in query:<br/>" . $query . "<br/>", E_USER_WARNING);
251                // DO NOT DIE, if transactions are there, they will do things in a better way
252        }
253
254        /**
255         * Clean the data before it is recorded on the database
256         *
257         * @param $value is a data we want to be stored in the database.
258         * If it is an array we'll make a serialize and then an base64_encode
259         * (you'll have to make an unserialize(base64_decode())
260         * If it is not an array we make an htmlspecialchars() on it
261         * @param bool $flat_arrays is true by default, if false arrays won't be serialized and encoded
262         * @param bool $check_for_injection is false by default, if true we'll perform some modifications
263         * on the string to avoid SQL injection
264         * @return mixed @access public
265         */
266        function security_cleanup($value, $flat_arrays = true, $check_for_injection = false)
267        {
268                if (is_array($value))
269                {
270                        if ($flat_arrays) {
271                                //serialize and \' are a big #!%*
272                                $res = base64_encode(serialize($value));
273                        }
274                        else
275                        {
276                                //recursive cleanup on the array
277                                $res = Array();
278                                foreach ($value as $key => $item)
279                                {
280                                        $res[$this->security_cleanup($key,$flat_arrays)] = $this->security_cleanup($item, $flat_arrays);
281                                }
282                        }
283                }
284                else
285                {
286                        $res = ($check_for_injection)? addslashes(str_replace(';','',$value)) : $value;
287                }
288                return $res;
289        }
290
291        /**
292         * Supports DB abstraction
293         *
294         * @param string &$query
295         * @return void
296         * @access public
297         */
298        function convert_query(&$query) {
299
300                switch ($this->db->databaseType) {
301                case "oci8":
302                        $query = preg_replace("/`/", "\"", $query);
303                        // convert bind variables - adodb does not do that
304                        $qe = explode("?", $query);
305                        $query = '';
306                        for ($i = 0; $i < sizeof($qe) - 1; $i++) {
307                                $query .= $qe[$i] . ":" . $i;
308                        }
309                        $query .= $qe[$i];
310                        break;
311                case "postgres7":
312                case "sybase":
313                        $query = preg_replace("/`/", "\"", $query);
314                        break;
315                }
316        }
317        /**
318         * Supports DB abstraction
319         *
320         * @param string $sort_mode
321         * @return string
322         * @access public
323         */
324        function convert_sortmode($sort_mode) {
325                $sort_mode = str_replace("__", "` ", $sort_mode);
326                $sort_mode = "`" . $sort_mode;
327                return $sort_mode;
328        }
329        /**
330         * Supports DB abstraction
331         *
332         * @return mixed
333         * @access public
334         */
335        function convert_binary() {
336
337                switch ($this->db->databaseType) {
338                case "pgsql72":
339                case "oci8":
340                case "postgres7":
341                        return;
342                        break;
343                case "mysql3":
344                case "mysql":
345                        return "binary";
346                        break;
347                }
348        }
349
350}
351?>
Note: See TracBrowser for help on using the repository browser.