From 8f61176da8e3f215cec70b3320c956d3e3ace73f Mon Sep 17 00:00:00 2001 From: Urban Müller Date: Wed, 18 Jul 2007 11:58:42 +0000 Subject: compatibility with auto-startup, some cleanups --- db_table.class | 102 +------------------------- dbi.class | 226 +++++++++++++++++++++++++++++++++++++++++++-------------- debug.class | 18 ++--- functions.php | 139 +++++++++++++++++++++++++++++++++++ itools.lib | 6 +- support.pinc | 226 --------------------------------------------------------- text.class | 61 ++++------------ 7 files changed, 343 insertions(+), 435 deletions(-) create mode 100644 functions.php delete mode 100644 support.pinc diff --git a/db_table.class b/db_table.class index f45155f..567bb7f 100644 --- a/db_table.class +++ b/db_table.class @@ -53,108 +53,12 @@ function safe_sql_select($query, $fields="*") /** - * Create an SQL query (the stuff after 'WHERE') according to - * an array of selection criteria.
- * Example:
- * $sql = $table->construct_sql_clause(array('Type' => 'bar', - * 'Date >=' => '1999-01-01', '-Date <' => 'NOW()', - * 'User NI' => 'chris'), 'ORDER BY Date'); - * - * @param $params optional array of fieldname => value tupels. - * These are ANDed to form a WHERE clause. - * fieldname can contain an operator (separated by space), the - * default operator is '='. The special operator 'NI' specifies - * that the argument must be contained in a comma-separated list. - * @param $sql Optional SQL addendum (added after $params), for ORDER BY etc. - * @param $omit_where (optional) Do not add 'WHERE ' at beginning of result (default: false) - * @return The generated SQL clause - * @see it_db_record::select, it_db_record::fetch_next + * Create an SQL query (the stuff after 'WHERE'). + * @see it_dbi::_where() for more details. */ function construct_sql_clause($params='', $sql='', $omit_where=false) { - if (is_array($params) && (count($params) > 0)) - { - $query = ''; - $sep = ''; - - foreach($params as $field => $value) - { - if (is_int($field)) /* no key specified; just append */ - { - if ($field === $value) /* ignore array(1 => 1) et al */ - continue; - - $query .= " $value"; - } - else - { - $needs_where = true; - - if (!isset($value)) - { - $op = 'IS'; - $qval = 'NULL'; - } - else - { - if (preg_match('/^(\S+)\s+(\S.*)$/', $field, $regs)) - { - $field = $regs[1]; - $op = strtoupper($regs[2]); - } - else - $op = '='; - - /* If the field name starts with '-', the value is taken as raw, - no escaping is done and no quotes are put around it. */ - if (substr($field, 0, 1) == '-') - { - $field = substr($field, 1); /* Strip that '-' sign */ - $qval = $value; - } - else if (!is_array($value)) - $qval = "'".mysql_real_escape_string((string)$value)."'"; - } - - switch ($op) - { - case 'NI': - $query .= $sep."CONCAT(',',$field,',') LIKE '%,$value,%'"; - break; - - case 'IN': - case 'NOT IN': - if (is_array($value)) - { - if ($value) - $query .= "$sep$field $op ('" . join("','", array_map('mysql_real_escape_string', $value)) . "')"; # null is mapped to '' - else - $query .= $sep . "0"; - - break; - } - /* FALLTHROUGH */ - - default: - if (isset($qval)) - $query .= "$sep$field $op $qval"; - else - it::fatal('Undefined $qval when constructing query due to invalid $value (array)'); - break; - } - $sep = ' AND '; - } - } - - if ($needs_where && !$omit_where) - $query = 'WHERE '.$query; - - if ($sql) - $query .= ' '; - } - $query .= $sql; - - return $query; + return it_dbi::_where($params, $sql, $omit_where); } diff --git a/dbi.class b/dbi.class index 727f3a9..84f780d 100644 --- a/dbi.class +++ b/dbi.class @@ -65,9 +65,39 @@ function it_dbi($config, $query = null) else $this->_db = $GLOBALS['ULTRADB']; - $dbid = "$this->_db/$this->_server/$this->_user"; + $this->_dbid = "$this->_db/$this->_server/$this->_user"; - if (!($this->_link = $GLOBALS['it_dbi_link'][$dbid])) + if ($this->_createclasses) + { + $this->_connect(); + + if (!($tables = mysql_list_tables($this->_db, $this->_link))) + $this->_fatal("it_dbi(): can't list on tables \"$this->_db\": " . mysql_error($this->_link)); + + $this->_defaults = ""; + foreach($config as $key => $value) + if ($key != 'createclasses') + $this->_defaults .= "'$key' => '".strtr($value, array('\'' => '\\\'', '$' => '\\$'))."', "; + + for ($i = 0; $i < mysql_num_rows($tables); $i++) + $this->createclass(mysql_tablename($tables, $i)); + } + + if (!$GLOBALS['it_dbi']) + $GLOBALS['it_dbi'] =& $this; + + if (isset($query)) + { + if (is_array($query)) + $this->select($query); + else + $this->read($query); + } +} + +function _connect() +{ + if (!($this->_link = $GLOBALS['it_dbi_link'][$this->_dbid])) { # Use persistent connections but prevent reuse if only DB differs if (!$this->_persistent || $GLOBALS['it_dbi_connected']["$this->_server/$this->_user"]++) @@ -89,74 +119,64 @@ function it_dbi($config, $query = null) if (!(@mysql_select_db($this->_db, $this->_link))) $this->_fatal("it_dbi(): can't select database \"$this->_db\": " . mysql_error($this->_link)); - $GLOBALS['it_dbi_link'][$dbid] = $this->_link; + $GLOBALS['it_dbi_link'][$this->_dbid] = $this->_link; } +} - if ($this->_createclasses) - { - if (!($tables = mysql_list_tables($this->_db, $this->_link))) - $this->_fatal("it_dbi(): can't list on tables \"$this->_db\": " . mysql_error($this->_link)); - $defaults = ''; - foreach($config as $key => $value) - if ($key != 'createclasses') - $defaults .= "'$key' => '".strtr($value, array('\'' => '\\\'', '$' => '\\$'))."', "; +/** + * Convert table given by name into a class + */ +function createclass($table) +{ + $this->_connect(); + $classname = "$this->_classprefix$table"; - for ($i = 0; $i < mysql_num_rows($tables); $i++) - { - $table = mysql_tablename($tables, $i); - $classname = "$this->_classprefix$table"; + if (!($result = @mysql_list_fields($this->_db, $table, $this->_link))) + $this->_fatal("it_dbi(): can't list fields \"$this->_db\": " . mysql_error($this->_link)); - if ($result = @mysql_list_fields($this->_db, $table, $this->_link)) - { - for ($fields=array(), $j=0; $j < mysql_num_fields($result); $j++) - { - $fields[mysql_field_name($result, $j)] = mysql_field_len($result, $j); - $flags = mysql_field_flags($result, $j); + for ($fields=array(), $j=0; $j < mysql_num_fields($result); $j++) + { + $fields[mysql_field_name($result, $j)] = mysql_field_len($result, $j); + $flags = mysql_field_flags($result, $j); - if (strstr($flags, "primary_key")) - { - $keyfield = mysql_field_name($result, $j); - $autoincrement = (bool)strstr($flags, "auto_increment"); - $randomid = (mysql_field_type($result, $j) == "string"); - } - } + if (strstr($flags, "primary_key")) + { + $keyfield = mysql_field_name($result, $j); + $autoincrement = (bool)strstr($flags, "auto_increment"); + $randomid = (mysql_field_type($result, $j) == "string"); + } + } - $fields = var_export($fields, true); + $fields = var_export($fields, true); - if ($this->_createclasses && (substr($classname, 0, 4) != 'PMA_') && !class_exists($classname)) + if ((substr($classname, 0, 4) != 'PMA_') && !class_exists($classname)) + { + debug("it_dbi: creating class $classname", 5); + eval(" + class $classname extends it_dbi + { + function $classname(\$query = null, \$config = array()) { - debug("it_dbi: creating class $classname", 5); - eval(" - class $classname extends it_dbi - { - function $classname(\$query = null, \$config = array()) - { - \$config += array($defaults'table' => '$table', 'keyfield' => '$keyfield', 'autoincrement' => '$autoincrement', 'randomid' => '$randomid'); - \$this->_fields = $fields; - \$this->it_dbi(\$config, \$query); - } - } - "); + \$config += array({$this->_defaults}'table' => '$table', 'keyfield' => '$keyfield', 'autoincrement' => '$autoincrement', 'randomid' => '$randomid'); + \$this->_fields = $fields; + \$this->it_dbi(\$config, \$query); } } - } + "); } - - if (isset($query)) - if (is_array($query)) - $this->select($query); - else - $this->read($query); } + /** * Internal: construct SQL SET clause of changed values from member vars and tags array. * Merge current values into $tags. Modifies caller's array (callers rely on it)! */ function _set(&$tags) { + $this->_connect(); + # Add member vars to tags, considering unquoted fields foreach (get_object_vars($this) as $field => $value) # Don't use isset($tags[$field]) (would not handle null values correctly) @@ -177,10 +197,109 @@ function _set(&$tags) } -/* Intermal: construct SQL WHERE clause */ -function _where($where) +/** + * Create an SQL query (the stuff after 'WHERE') according to + * an array of selection criteria.
+ * Example:
+ * $sql = $table->construct_sql_clause(array('Type' => 'bar', + * 'Date >=' => '1999-01-01', '-Date <' => 'NOW()', + * 'User NI' => 'chris'), 'ORDER BY Date'); + * + * @param $params optional array of fieldname => value tupels. + * These are ANDed to form a WHERE clause. + * fieldname can contain an operator (separated by space), the + * default operator is '='. The special operator 'NI' specifies + * that the argument must be contained in a comma-separated list. + * @param $sql Optional SQL addendum (added after $params), for ORDER BY etc. + * @param $omit_where (optional) Do not add 'WHERE ' at beginning of result (default: false) + * @return The generated SQL clause + * @see it_db_record::select, it_db_record::fetch_next + */ +function _where($params='', $sql='', $omit_where=false) { - return isset($where) ? ' ' . it_db_table::construct_sql_clause($where) : ''; + if (is_array($params) && (count($params) > 0)) + { + $query = ''; + $sep = ''; + + foreach($params as $field => $value) + { + if (is_int($field)) /* no key specified; just append */ + { + if ($field === $value) /* ignore array(1 => 1) et al */ + continue; + + $query .= " $value"; + } + else + { + $needs_where = true; + + if (!isset($value)) + { + $op = 'IS'; + $qval = 'NULL'; + } + else + { + if (preg_match('/^(\S+)\s+(\S.*)$/', $field, $regs)) + { + $field = $regs[1]; + $op = strtoupper($regs[2]); + } + else + $op = '='; + + /* If the field name starts with '-', the value is taken as raw, + no escaping is done and no quotes are put around it. */ + if (substr($field, 0, 1) == '-') + { + $field = substr($field, 1); /* Strip that '-' sign */ + $qval = $value; + } + else if (!is_array($value)) + $qval = "'".mysql_real_escape_string((string)$value)."'"; + } + + switch ($op) + { + case 'NI': + $query .= $sep."CONCAT(',',$field,',') LIKE '%,$value,%'"; + break; + + case 'IN': + case 'NOT IN': + if (is_array($value)) + { + if ($value) + $query .= "$sep$field $op ('" . join("','", array_map('mysql_real_escape_string', $value)) . "')"; # null is mapped to '' + else + $query .= $sep . "0"; + + break; + } + /* FALLTHROUGH */ + + default: + if (isset($qval)) + $query .= "$sep$field $op $qval"; + else + it::fatal('Undefined $qval when constructing query due to invalid $value (array)'); + break; + } + $sep = ' AND '; + } + } + + if ($needs_where && !$omit_where) + $query = 'WHERE '.$query; + + if ($sql) + $query .= ' '; + } + $query .= $sql; + + return $query; } @@ -233,6 +352,7 @@ function clear($pp = true) */ function query($query) { + $this->_connect(); debug(get_class($this)."::query(\"$query\")", 4); $start = gettimeofday(); @@ -458,7 +578,7 @@ function delete($query = null) if ($query) { - if ($sres = $this->query(($sql = "DELETE FROM $this->_table " . $this->_where($query)))) + if ($this->query(($sql = "DELETE FROM $this->_table " . $this->_where($query)))) $result = mysql_affected_rows($this->_link); } diff --git a/debug.class b/debug.class index 956b0d0..fa6f314 100644 --- a/debug.class +++ b/debug.class @@ -98,17 +98,17 @@ function internal_error($text) /** * Function to return dump of all it's parameters, - * normally used through D(), ED(), EDX() in support.pinc + * normally used through D(), ED(), EDX() in functions.php * @param Varargs of mixed stuff to dump * @return String representation of dump */ -function dump() +function dump($args) { $stack = debug_backtrace(); - $line = $stack[2]['line']; - $file = $stack[2]['file']; + $line = $stack[1]['line']; + $file = $stack[1]['file']; - if (!$_SERVER['REMOTE_ADDR'] && !preg_match('/class/', $file)) + if (!$_SERVER['REMOTE_ADDR'] && (substr(file_get_contents($file), 0, 2) == "#!")) $line++; if (ereg('(csv|txt|gif|jpg)', $_SERVER['PHP_SELF']) || !ereg('Mozilla', $_SERVER['HTTP_USER_AGENT'])) @@ -134,12 +134,12 @@ function dump() $paramlist = preg_match('/(D|ED|EDC|EDX)\s*\(\s*([^)]+)/i', $src, $parts) ? $parts[2] : ""; $argnames = preg_split('/\s*,\s*/', $paramlist); - foreach (func_get_args() as $arg) + if ($parts[1] == "EDC") # First argument was stripped by EDC + array_shift($argnames); + + foreach ($args as $arg) { $var = array_shift($argnames); - if ($arg==='_ignoreme') - continue; - $item = gettype($arg) == 'resource' ? trim(print_r($arg, true)) : trim(var_export($arg, true)); # Replace PHP 5 var_export object representation by old style diff --git a/functions.php b/functions.php new file mode 100644 index 0000000..ddb6012 --- /dev/null +++ b/functions.php @@ -0,0 +1,139 @@ +debug($text, $level); +} + +/** + * Convert a htmlentities-encoded string back to normal + */ +function it_htmlentities_decode($string) +{ + return strtr($string, array_flip(get_html_translation_table(HTML_ENTITIES))); +} + +/** + * Clone an object and return copy, works for all PHP versions + */ +function &it_clone(&$object) +{ + $result = (is_object($object) && version_compare(zend_version(), 2, '>=')) ? clone($object) : $object; + return $result; # PHP internals need a tmp var to return by ref +} + +/** + * Return string containing names and values of all arguments + */ +function D() +{ + $args = func_get_args(); + return it_debug::dump($args); +} + +/** + * Echo string containing names and values of all arguments + */ +function ED() +{ + $args = func_get_args(); + echo it_debug::dump($args); + return $args[0]; +} + +/** + * Same as ED(), but first argument is string that must be in $_REQUEST['debug'] + */ +function EDC() +{ + $args = func_get_args(); + $var = array_shift($args); + $GLOBALS['ULTRADEBUGVARS'][$var] = 1; + + if (($result = $GLOBALS["debug_$var"]) && $args) + echo it_debug::dump($args); + + if (!$result || $result === true) # Compatibility with old map relying on 0|1 + $result = intval($result); + + return $result; +} + +/** + * Echo string containing names and values of all arguments, then exit + */ +function EDX() +{ + $args = func_get_args(); + exit(it_debug::dump($args)); +} + +/** + * Shortcut to $it_text->Text() + */ +function T($label, $raw = null, $language = null) +{ + it_text::init(); + return $GLOBALS['it_text']->text($label, $raw, $language); +} + + +/** + * Shortcut to $it_text->etext() + */ +function ET($label, $values = null, $language = null) +{ + it_text::init(); + return $GLOBALS['it_text']->etext($label, $values, $language); +} + +/** + * Return "db4" or "db2" depending on availability + */ +function db_version() +{ + return in_array("db4", dba_handlers()) ? "db4" : "db2"; +} + +/** + * Shortcut to $it_text->get_language() + */ +function T_lang() +{ + it_text::init(); + return isset($GLOBALS['it_text']) ? $GLOBALS['it_text']->get_language() : "de"; +} + +/** + * Shortcut to $it_text->get_language() + */ +function T_set_language($language, $setcookie = true) +{ + it_text::init(); + return $GLOBALS['it_text']->set_language($language, $setcookie); +} + +/** + * Shortcut to $it_text->text_exists() + */ +function T_exists($label, $language = null) +{ + it_text::init(); + return $GLOBALS['it_text']->text_exists($label, $language); +} + +?> diff --git a/itools.lib b/itools.lib index de049cd..1e2f1b9 100644 --- a/itools.lib +++ b/itools.lib @@ -1,5 +1,9 @@ debug($text, $level); -} - - -/** - * Global shortcut for $it_debug::intermal_error() - * @see it_debug - */ -function internal_error($text) -{ - if (isset($GLOBALS['it_debug'])) - $GLOBALS['it_debug']->internal_error($text); - else - exit; - /* NOT REACHED */ -} - - -/** - * Convert a htmlentities-encoded string back to normal - */ -function it_htmlentities_decode($string) -{ - return strtr($string, array_flip(get_html_translation_table(HTML_ENTITIES))); -} - - -/** - * Clone an object and return copy, works for all PHP versions - */ -function &it_clone(&$object) -{ - $result = (is_object($object) && version_compare(zend_version(), 2, '>=')) ? clone($object) : $object; - - return $result; # PHP internals need a tmp var to return by ref -} - - -/** - * Defines a new error_handler which gives a Stacktrace - * To activate, use: set_error_handler('it_error_handler'); - */ -function it_error_handler($errno, $errstr, $errfile, $errline) -{ - $errors = array( - 1 => 'ERROR', - 2 => 'WARNING', - 4 => 'PARSE', - 8 => 'NOTICE', - 16 => 'CORE_ERROR', - 32 => 'CORE_WARNING', - 64 => 'COMPILE_ERROR', - 128 => 'COMPILE_WARNING', - 256 => 'USER_ERROR', - 512 => 'USER_WARNING', - 1024 => 'USER_NOTICE', - 2048 => 'STRICT', - ); - - $error = isset($errors[$errno]) ? $errors[$errno] : $errno; - - if (ini_get('display_errors') && ($errno & ini_get('error_reporting'))) - { - $stack = debug_backtrace(); - array_shift($stack); - - $url = "http://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"; - $ref = $_SERVER['HTTP_REFERER']; - $errfile = preg_replace('#^/data./www/#', '/www/', $errfile); - - foreach ($stack as $level) - { - if (isset($level['class'])) - $level['function'] = "{$level['class']}->{$level['function']}"; - - $file = preg_replace('#^/data./www/#', '/www/', $level['file']); - $args = array(); - - foreach ((array)$level['args'] as $arg) - { - switch (gettype($arg)) - { - case 'array': - $args[] = 'Array[' . count($arg) . ']'; - break; - case 'object': - $args[] = 'Object:' . get_class($arg); - break; - case 'boolean': - $args[] = $arg ? 'true' : 'false'; - break; - default: - $args[] = '"' . (string)$arg . '"'; - break; - } - - - } - - if ($levelnum++ == 0) - $message .= "Line {$level['line']} $file # $error: $errstr\n"; - else - $message .= "Line {$level['line']} $file # {$level['function']}(" . join(', ', $args) . ")\n"; - } - - if ($_SERVER['HTTP_HOST']) - { - foreach((array)$_COOKIE as $key => $val) - $cookies .= "$key=$val "; - - error_log("$error: $errstr at Line $errline $errfile url=$url ref=$ref $cookies"); - echo "\n\n
\n$message

\n\n"; - } - else - error_log(strip_tags($message)); - } - - if (!preg_match('/(WARNING|NOTICE|STRICT)$/', $error)) - exit(1); -} - -/** - * Return string containing names and values of all arguments - */ -function D() -{ - $args = func_get_args(); - return call_user_func_array(array('it_debug', 'dump'), $args); -} - -/** - * Echo string containing names and values of all arguments - */ -function ED() -{ - $args = func_get_args(); - echo call_user_func_array(array('it_debug', 'dump'), $args); - return $args[0]; -} - -/** - * Same as ED(), but first argument is string that must be in $_REQUEST['debug'] - */ -function EDC() -{ - $args = func_get_args(); - $GLOBALS['ULTRADEBUGVARS'][$args[0]] = 1; - if (strstr($_REQUEST['debug'], $args[0]) || $GLOBALS["debug_" . $args[0]]) { - $active = $GLOBALS['debug_'.$args[0]]; - if( !$active ) - $active = 1; - $args[0] = '_ignoreme'; - if (count($args) > 1) - echo call_user_func_array(array('it_debug', 'dump'), $args); - } else - $active = 0; - return $active; -} - -/** - * Echo string containing names and values of all arguments, then exit - */ -function EDX() -{ - $args = func_get_args(); - exit(call_user_func_array(array('it_debug', 'dump'), $args)); -} - -/** - * Return "db4" or "db2" depending on availability - */ -function db_version() -{ - return in_array("db4", dba_handlers()) ? "db4" : "db2"; -} - -/** - * Append a line to a logfile in log/. Date will be added to filename and line - * @param $name Name of logfile - * @param $line Line to append - */ -function log_append($name, $line) -{ - if ($fh = fopen($GLOBALS['ULTRAHOME'] . "/log/$name-" . date('Ymd'), "a")) { - fputs($fh, date("Y-m-d H:i:s") . "\t$line\n"); - fclose($fh); - } -} - -?> diff --git a/text.class b/text.class index de5e906..d96fb74 100644 --- a/text.class +++ b/text.class @@ -104,9 +104,23 @@ function it_text($p = null) # And finally, record the name of our active language. $this->actlanguagename = $this->languages[$this->actlanguage]; + # Make this object available under $GLOBALS['it_text'], or add my texts to $GLOBALS['it_text'] if it exists + if (!$GLOBALS['it_text']) + $GLOBALS['it_text'] =& $this; + else + $GLOBALS['it_text']->statictext += $this->statictext; + debug("Used language is {$this->actlanguagename}, default language is {$this->defaultlanguage}.", 6); } +/** + * Instanciate singleton if necessary + */ +function init() +{ + if (!$GLOBALS['it_text']) + new it_text; +} /** * Return a text in the selected language. @@ -361,51 +375,4 @@ function dump_php() } } /* End class it_text */ - - -/* - * Globally available functions without need for object - */ - - -/* - * Shortcut to $it_text->Text() - */ -function T($label, $raw = null, $language = null) -{ - return $GLOBALS['it_text']->text($label, $raw, $language); -} - - -/* - * Shortcut to $it_text->etext() - */ -function ET($label, $values = null, $language = null) -{ - return $GLOBALS['it_text']->etext($label, $values, $language); -} - -/** - * Shortcut to $it_text->get_language() - */ -function T_lang() -{ - return isset($GLOBALS['it_text']) ? $GLOBALS['it_text']->get_language() : "de"; -} - -/** - * Shortcut to $it_text->get_language() - */ -function T_set_language($language, $setcookie = true) -{ - return $GLOBALS['it_text']->set_language($language, $setcookie); -} - -/** - * Shortcut to $it_text->text_exists() - */ -function T_exists($label, $language = null) -{ - return $GLOBALS['it_text']->text_exists($label, $language); -} ?> -- cgit v1.2.3