[BUGFIX] Autoloader Cache is not updated
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_db.php
index da9e54e..3d614e4 100644 (file)
@@ -2,7 +2,7 @@
 /***************************************************************
  *  Copyright notice
  *
- *  (c) 2004-2010 Kasper Skårhøj (kasperYYYY@typo3.com)
+ *  (c) 2004-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
  *  All rights reserved
  *
  *  This script is part of the TYPO3 project. The TYPO3 project is
  * interaction.
  * This class is instantiated globally as $TYPO3_DB in TYPO3 scripts.
  *
- * $Id$
- *
  * @author     Kasper Skårhøj <kasperYYYY@typo3.com>
  */
-/**
- * [CLASS/FUNCTION INDEX of SCRIPT]
- *
- *
- *
- *  138: class t3lib_DB
- *
- *                       SECTION: Query execution
- *  175:        function exec_INSERTquery($table,$fields_values,$no_quote_fields=FALSE)
- *  192:        function exec_UPDATEquery($table,$where,$fields_values,$no_quote_fields=FALSE)
- *  206:        function exec_DELETEquery($table,$where)
- *  225:        function exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='')
- *  250:        function exec_SELECT_mm_query($select,$local_table,$mm_table,$foreign_table,$whereClause='',$groupBy='',$orderBy='',$limit='')
- *  278:        function exec_SELECT_queryArray($queryParts)
- *  301:        function exec_SELECTgetRows($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='',$uidIndexField='')
- *
- *                       SECTION: Query building
- *  346:        function INSERTquery($table,$fields_values,$no_quote_fields=FALSE)
- *  381:        function UPDATEquery($table,$where,$fields_values,$no_quote_fields=FALSE)
- *  422:        function DELETEquery($table,$where)
- *  451:        function SELECTquery($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='')
- *  492:        function listQuery($field, $value, $table)
- *  506:        function searchQuery($searchWords,$fields,$table)
- *
- *                       SECTION: Various helper functions
- *  552:        function fullQuoteStr($str, $table)
- *  569:        function fullQuoteArray($arr, $table, $noQuote=FALSE)
- *  596:        function quoteStr($str, $table)
- *  612:        function escapeStrForLike($str, $table)
- *  625:        function cleanIntArray($arr)
- *  641:        function cleanIntList($list)
- *  655:        function stripOrderBy($str)
- *  669:        function stripGroupBy($str)
- *  681:        function splitGroupOrderLimit($str)
- *
- *                       SECTION: MySQL wrapper functions
- *  749:        function sql($db,$query)
- *  763:        function sql_query($query)
- *  776:        function sql_error()
- *  788:        function sql_num_rows($res)
- *  800:        function sql_fetch_assoc($res)
- *  813:        function sql_fetch_row($res)
- *  825:        function sql_free_result($res)
- *  836:        function sql_insert_id()
- *  847:        function sql_affected_rows()
- *  860:        function sql_data_seek($res,$seek)
- *  873:        function sql_field_type($res,$pointer)
- *  887:        function sql_pconnect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password)
- *  915:        function sql_select_db($TYPO3_db)
- *
- *                       SECTION: SQL admin functions
- *  947:        function admin_get_dbs()
- *  965:        function admin_get_tables()
- *  984:        function admin_get_fields($tableName)
- * 1002:        function admin_get_keys($tableName)
- * 1020:        function admin_query($query)
- *
- *                       SECTION: Connecting service
- * 1048:        function connectDB()
- *
- *                       SECTION: Debugging
- * 1086:        function debug($func)
- *
- * TOTAL FUNCTIONS: 42
- * (This index is automatically created/updated by the extension "extdeveval")
- *
- */
 
 
 /**
@@ -131,7 +62,7 @@ class t3lib_DB {
 
 
                // Debug:
-       var $debugOutput = FALSE; // Set "TRUE" if you want database errors outputted.
+       var $debugOutput = FALSE; // Set "TRUE" or "1" if you want database errors outputted. Set to "2" if you also want successful database actions outputted.
        var $debug_lastBuiltQuery = ''; // Internally: Set to last built query (not necessarily executed...)
        var $store_lastBuiltQuery = FALSE; // Set "TRUE" if you want the last built query to be stored in $debug_lastBuiltQuery independent of $this->debugOutput
        var $explainOutput = 0; // Set this to 1 to get queries explained (devIPmask must match). Set the value to 2 to the same but disregarding the devIPmask. There is an alternative option to enable explain output in the admin panel under "TypoScript", which will produce much nicer output, but only works in FE.
@@ -142,6 +73,16 @@ class t3lib_DB {
                // Default character set, applies unless character set or collation are explicitely set
        var $default_charset = 'utf8';
 
+       /**
+        * @var t3lib_DB_preProcessQueryHook[]
+        */
+       protected $preProcessHookObjects = array();
+
+       /**
+        * @var t3lib_DB_postProcessQueryHook[]
+        */
+       protected $postProcessHookObjects = array();
+
 
        /************************************
         *
@@ -171,6 +112,9 @@ class t3lib_DB {
                if ($this->debugOutput) {
                        $this->debug('exec_INSERTquery');
                }
+               foreach ($this->postProcessHookObjects as $hookObject) {
+                       $hookObject->exec_INSERTquery_postProcessAction($table, $fields_values, $no_quote_fields, $this);
+               }
                return $res;
        }
 
@@ -188,6 +132,9 @@ class t3lib_DB {
                if ($this->debugOutput) {
                        $this->debug('exec_INSERTmultipleRows');
                }
+               foreach ($this->postProcessHookObjects as $hookObject) {
+                       $hookObject->exec_INSERTmultipleRows_postProcessAction($table, $fields, $rows, $no_quote_fields, $this);
+               }
                return $res;
        }
 
@@ -207,6 +154,9 @@ class t3lib_DB {
                if ($this->debugOutput) {
                        $this->debug('exec_UPDATEquery');
                }
+               foreach ($this->postProcessHookObjects as $hookObject) {
+                       $hookObject->exec_UPDATEquery_postProcessAction($table, $where, $fields_values, $no_quote_fields, $this);
+               }
                return $res;
        }
 
@@ -223,6 +173,9 @@ class t3lib_DB {
                if ($this->debugOutput) {
                        $this->debug('exec_DELETEquery');
                }
+               foreach ($this->postProcessHookObjects as $hookObject) {
+                       $hookObject->exec_DELETEquery_postProcessAction($table, $where, $this);
+               }
                return $res;
        }
 
@@ -233,7 +186,7 @@ class t3lib_DB {
         *
         * @param       string          List of fields to select from the table. This is what comes right after "SELECT ...". Required value.
         * @param       string          Table(s) from which to select. This is what comes right after "FROM ...". Required value.
-        * @param       string          Optional additional WHERE clauses put in the end of the query. NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself! DO NOT PUT IN GROUP BY, ORDER BY or LIMIT!
+        * @param       string          additional WHERE clauses put in the end of the query. NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself! DO NOT PUT IN GROUP BY, ORDER BY or LIMIT!
         * @param       string          Optional GROUP BY field(s), if none, supply blank string.
         * @param       string          Optional ORDER BY field(s), if none, supply blank string.
         * @param       string          Optional LIMIT value ([begin,]max), if none, supply blank string.
@@ -257,7 +210,7 @@ class t3lib_DB {
         * Creates and executes a SELECT query, selecting fields ($select) from two/three tables joined
         * Use $mm_table together with $local_table or $foreign_table to select over two tables. Or use all three tables to select the full MM-relation.
         * The JOIN is done with [$local_table].uid <--> [$mm_table].uid_local  / [$mm_table].uid_foreign <--> [$foreign_table].uid
-        * The function is very useful for selecting MM-relations between tables adhering to the MM-format used by TCE (TYPO3 Core Engine). See the section on $TCA in Inside TYPO3 for more details.
+        * The function is very useful for selecting MM-relations between tables adhering to the MM-format used by TCE (TYPO3 Core Engine). See the section on $GLOBALS['TCA'] in Inside TYPO3 for more details.
         *
         * Usage: 12 (spec. ext. sys_action, sys_messages, sys_todos)
         *
@@ -390,7 +343,7 @@ class t3lib_DB {
         * @param       string          $field: Name of the field to use in the COUNT() expression (e.g. '*')
         * @param       string          $table: Name of the table to count rows for
         * @param       string          $where: (optional) WHERE statement of the query
-        * @return      mixed           Number of rows counter (integer) or false if something went wrong (boolean)
+        * @return      mixed           Number of rows counter (integer) or FALSE if something went wrong (boolean)
         */
        public function exec_SELECTcountRows($field, $table, $where = '') {
                $count = FALSE;
@@ -413,6 +366,9 @@ class t3lib_DB {
                if ($this->debugOutput) {
                        $this->debug('exec_TRUNCATEquery');
                }
+               foreach ($this->postProcessHookObjects as $hookObject) {
+                       $hookObject->exec_TRUNCATEquery_postProcessAction($table, $this);
+               }
                return $res;
        }
 
@@ -430,13 +386,16 @@ class t3lib_DB {
         * @param       string          See exec_INSERTquery()
         * @param       array           See exec_INSERTquery()
         * @param       string/array            See fullQuoteArray()
-        * @return      string          Full SQL query for INSERT (unless $fields_values does not contain any elements in which case it will be false)
+        * @return      string          Full SQL query for INSERT (unless $fields_values does not contain any elements in which case it will be FALSE)
         */
        function INSERTquery($table, $fields_values, $no_quote_fields = FALSE) {
 
                        // Table and fieldnames should be "SQL-injection-safe" when supplied to this
                        // function (contrary to values in the arrays which may be insecure).
                if (is_array($fields_values) && count($fields_values)) {
+                       foreach ($this->preProcessHookObjects as $hookObject) {
+                               $hookObject->INSERTquery_preProcessAction($table, $fields_values, $no_quote_fields, $this);
+                       }
 
                                // quote and escape values
                        $fields_values = $this->fullQuoteArray($fields_values, $table, $no_quote_fields);
@@ -461,12 +420,16 @@ class t3lib_DB {
         * @param       array           Field names
         * @param       array           Table rows. Each row should be an array with field values mapping to $fields
         * @param       string/array            See fullQuoteArray()
-        * @return      string          Full SQL query for INSERT (unless $rows does not contain any elements in which case it will be false)
+        * @return      string          Full SQL query for INSERT (unless $rows does not contain any elements in which case it will be FALSE)
         */
        public function INSERTmultipleRows($table, array $fields, array $rows, $no_quote_fields = FALSE) {
                        // Table and fieldnames should be "SQL-injection-safe" when supplied to this
                        // function (contrary to values in the arrays which may be insecure).
                if (count($rows)) {
+                       foreach ($this->preProcessHookObjects as $hookObject) {
+                               $hookObject->INSERTmultipleRows_preProcessAction($table, $fields, $rows, $no_quote_fields, $this);
+                       }
+
                                // Build query:
                        $query = 'INSERT INTO ' . $table .
                                        ' (' . implode(', ', $fields) . ') VALUES ';
@@ -503,6 +466,10 @@ class t3lib_DB {
                        // Table and fieldnames should be "SQL-injection-safe" when supplied to this
                        // function (contrary to values in the arrays which may be insecure).
                if (is_string($where)) {
+                       foreach ($this->preProcessHookObjects as $hookObject) {
+                               $hookObject->UPDATEquery_preProcessAction($table, $where, $fields_values, $no_quote_fields, $this);
+                       }
+
                        $fields = array();
                        if (is_array($fields_values) && count($fields_values)) {
 
@@ -540,6 +507,9 @@ class t3lib_DB {
         */
        function DELETEquery($table, $where) {
                if (is_string($where)) {
+                       foreach ($this->preProcessHookObjects as $hookObject) {
+                               $hookObject->DELETEquery_preProcessAction($table, $where, $this);
+                       }
 
                                // Table and fieldnames should be "SQL-injection-safe" when supplied to this function
                        $query = 'DELETE FROM ' . $table .
@@ -622,6 +592,10 @@ class t3lib_DB {
         * @return      string          Full SQL query for TRUNCATE TABLE
         */
        public function TRUNCATEquery($table) {
+               foreach ($this->preProcessHookObjects as $hookObject) {
+                       $hookObject->TRUNCATEquery_preProcessAction($table, $this);
+               }
+
                        // Table should be "SQL-injection-safe" when supplied to this function
                        // Build basic query:
                $query = 'TRUNCATE TABLE ' . $table;
@@ -651,7 +625,7 @@ class t3lib_DB {
        public function listQuery($field, $value, $table) {
                $value = (string) $value;
                if (strpos(',', $value) !== FALSE) {
-                       throw new InvalidArgumentException('$value must not contain a comma (,) in $this->listQuery() !');
+                       throw new InvalidArgumentException('$value must not contain a comma (,) in $this->listQuery() !', 1294585862);
                }
                $pattern = $this->quoteStr($value, $table);
                $where = 'FIND_IN_SET(\'' . $pattern . '\',' . $field . ')';
@@ -938,27 +912,6 @@ class t3lib_DB {
 
        /**
         * Executes query
-        * mysql() wrapper function
-        * Usage count/core: 0
-        *
-        * @param       string          Database name
-        * @param       string          Query to execute
-        * @return      pointer         Result pointer / DBAL object
-        * @deprecated since TYPO3 3.6, will be removed in TYPO3 4.6
-        * @see sql_query()
-        */
-       function sql($db, $query) {
-               t3lib_div::logDeprecatedFunction();
-
-               $res = mysql_query($query, $this->link);
-               if ($this->debugOutput) {
-                       $this->debug('sql', $query);
-               }
-               return $res;
-       }
-
-       /**
-        * Executes query
         * mysql_query() wrapper function
         * Beware: Use of this method should be avoided as it is experimentally supported by DBAL. You should consider
         *         using exec_SELECTquery() and similar methods instead.
@@ -1143,7 +1096,7 @@ class t3lib_DB {
                $isLocalhost = ($TYPO3_db_host == 'localhost' || $TYPO3_db_host == '127.0.0.1');
                if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['no_pconnect']) {
                        if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['dbClientCompress'] && !$isLocalhost) {
-                                       // We use PHP's default value for 4th parameter (new_link), which is false.
+                                       // We use PHP's default value for 4th parameter (new_link), which is FALSE.
                                        // See PHP sources, for example: file php-5.2.5/ext/mysql/php_mysql.c,
                                        // function php_mysql_do_connect(), near line 525
                                $this->link = @mysql_connect($TYPO3_db_host, $TYPO3_db_username, $TYPO3_db_password, FALSE, MYSQL_CLIENT_COMPRESS);
@@ -1386,13 +1339,17 @@ class t3lib_DB {
         * @return      void
         */
        function connectDB($host = TYPO3_db_host, $user = TYPO3_db_username, $password = TYPO3_db_password, $db = TYPO3_db) {
+                       // If no db is given we throw immediately. This is a sign for a fresh (not configured)
+                       // TYPO3 installation and is used in FE to redirect to 1-2-3 install tool
+               if (!$db) {
+                       throw new RuntimeException(
+                               'TYPO3 Fatal Error: No database selected!',
+                               1270853882
+                       );
+               }
+
                if ($this->sql_pconnect($host, $user, $password)) {
-                       if (!$db) {
-                               throw new RuntimeException(
-                                       'TYPO3 Fatal Error: No database selected!',
-                                       1270853882
-                               );
-                       } elseif (!$this->sql_select_db($db)) {
+                       if (!$this->sql_select_db($db)) {
                                throw new RuntimeException(
                                        'TYPO3 Fatal Error: Cannot connect to the current database, "' . $db . '"!',
                                        1270853883
@@ -1404,6 +1361,25 @@ class t3lib_DB {
                                1270853884
                        );
                }
+
+                       // Prepare user defined objects (if any) for hooks which extend query methods
+               $this->preProcessHookObjects = array();
+               $this->postProcessHookObjects = array();
+               if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_db.php']['queryProcessors'])) {
+                       foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_db.php']['queryProcessors'] as $classRef) {
+                               $hookObject = t3lib_div::getUserObj($classRef);
+
+                               if (!($hookObject instanceof t3lib_DB_preProcessQueryHook || $hookObject instanceof t3lib_DB_postProcessQueryHook)) {
+                                       throw new UnexpectedValueException('$hookObject must either implement interface t3lib_DB_preProcessQueryHook or interface t3lib_DB_postProcessQueryHook', 1299158548);
+                               }
+                               if ($hookObject instanceof t3lib_DB_preProcessQueryHook) {
+                                       $this->preProcessHookObjects[] = $hookObject;
+                               }
+                               if ($hookObject instanceof t3lib_DB_postProcessQueryHook) {
+                                       $this->postProcessHookObjects[] = $hookObject;
+                               }
+                       }
+               }
        }
 
        /**
@@ -1432,7 +1408,7 @@ class t3lib_DB {
        function debug($func, $query = '') {
 
                $error = $this->sql_error();
-               if ($error || $this->debugOutput == 2) {
+               if ($error || (int)$this->debugOutput === 2) {
                        debug(
                                array(
                                        'caller' => 't3lib_DB::' . $func,
@@ -1450,7 +1426,7 @@ class t3lib_DB {
         * Checks if recordset is valid and writes debugging inormation into devLog if not.
         *
         * @param       resource        $res    Recordset
-        * @return      boolean <code>false</code> if recordset is not valid
+        * @return      boolean <code>FALSE</code> if recordset is not valid
         */
        function debug_check_recordset($res) {
                if (!$res) {
@@ -1496,7 +1472,7 @@ class t3lib_DB {
         * @param       string          SQL query
         * @param       string          Table(s) from which to select. This is what comes right after "FROM ...". Required value.
         * @param       integer         Number of resulting rows
-        * @return      boolean         True if explain was run, false otherwise
+        * @return      boolean         TRUE if explain was run, FALSE otherwise
         */
        protected function explain($query, $from_table, $row_count) {