Documentation TYPO3 par Ameos |
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 2004-2005 Kasper Skaarhoj (kasperYYYY@typo3.com) 00006 * All rights reserved 00007 * 00008 * This script is part of the TYPO3 project. The TYPO3 project is 00009 * free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * The GNU General Public License can be found at 00015 * http://www.gnu.org/copyleft/gpl.html. 00016 * A copy is found in the textfile GPL.txt and important notices to the license 00017 * from the author is found in LICENSE.txt distributed with these scripts. 00018 * 00019 * 00020 * This script is distributed in the hope that it will be useful, 00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 * GNU General Public License for more details. 00024 * 00025 * This copyright notice MUST APPEAR in all copies of the script! 00026 ***************************************************************/ 00092 require_once(PATH_t3lib.'class.t3lib_sqlparser.php'); 00093 00094 00104 class t3lib_sqlengine extends t3lib_sqlparser { 00105 00106 // array with data records: [table name][num.index] = records 00107 var $data = array(); // Data source storage 00108 00109 00110 // Internal, SQL Status vars: 00111 var $errorStatus = ''; // Set with error message of last operation 00112 var $lastInsertedId = 0; // Set with last inserted unique ID 00113 var $lastAffectedRows = 0; // Set with last number of affected rows. 00114 00115 00116 00117 00118 00126 function init($config, &$pObj) { 00127 } 00128 00134 function resetStatusVars() { 00135 $this->errorStatus = ''; 00136 $this->lastInsertedId = 0; 00137 $this->lastAffectedRows = 0; 00138 } 00139 00150 function processAccordingToConfig(&$value,$fInfo) { 00151 $options = $this->parseFieldDef($fInfo['Type']); 00152 00153 switch(strtolower($options['fieldType'])) { 00154 case 'int': 00155 case 'smallint': 00156 case 'tinyint': 00157 case 'mediumint': 00158 $value = intval($value); 00159 if ($options['featureIndex']['UNSIGNED']) { 00160 $value = t3lib_div::intInRange($value,0); 00161 } 00162 break; 00163 case 'double': 00164 $value = (double)$value; 00165 break; 00166 case 'varchar': 00167 case 'char': 00168 $value = substr($value,0,trim($options['value'])); 00169 break; 00170 case 'text': 00171 case 'blob': 00172 $value = substr($value,0,65536); 00173 break; 00174 case 'tinytext': 00175 case 'tinyblob': 00176 $value = substr($value,0,256); 00177 break; 00178 case 'mediumtext': 00179 case 'mediumblob': 00180 // ?? 00181 break; 00182 } 00183 } 00184 00185 00186 00187 00188 00189 00190 00191 /******************************** 00192 * 00193 * SQL queries 00194 * This is the SQL access functions used when this class is instantiated as a SQL handler with DBAL. Override these in derived classes. 00195 * 00196 ********************************/ 00197 00205 function exec_INSERTquery($table,$fields_values) { 00206 00207 // Initialize 00208 $this->resetStatusVars(); 00209 00210 // Reading Data Source if not done already. 00211 $this->readDataSource($table); 00212 00213 // If data source is set: 00214 if (is_array($this->data[$table])) { 00215 00216 $fieldInformation = $this->admin_get_fields($table); // Should cache this...! 00217 00218 // Looking for unique keys: 00219 $saveArray = array(); 00220 foreach($fieldInformation as $fInfo) { 00221 00222 // Field name: 00223 $fN = $fInfo['Field']; 00224 00225 // Set value: 00226 $saveArray[$fN] = isset($fields_values[$fN]) ? $fields_values[$fN] : $options['Default']; // $options not defined, kasper! 00227 00228 // Process value: 00229 $this->processAccordingToConfig($saveArray[$fN], $fInfo); 00230 00231 // If an auto increment field is found, find the largest current uid: 00232 if ($fInfo['Extra'] == 'auto_increment') { 00233 00234 // Get all UIDs: 00235 $uidArray = array(); 00236 foreach($this->data[$table] as $r) { 00237 $uidArray[] = $r[$fN]; 00238 } 00239 00240 // If current value is blank or already in array, we create a new: 00241 if (!$saveArray[$fN] || in_array(intval($saveArray[$fN]), $uidArray)) { 00242 if (count($uidArray)) { 00243 $saveArray[$fN] = max($uidArray)+1; 00244 } else $saveArray[$fN] = 1; 00245 } 00246 00247 // Update "last inserted id": 00248 $this->lastInsertedId = $saveArray[$fN]; 00249 } 00250 } 00251 #debug(array($fields_values,$saveArray)); 00252 // Insert row in table: 00253 $this->data[$table][] = $saveArray; 00254 00255 // Save data source 00256 $this->saveDataSource($table); 00257 00258 return TRUE; 00259 } else $this->errorStatus = 'No data loaded.'; 00260 00261 return FALSE; 00262 } 00263 00272 function exec_UPDATEquery($table,$where,$fields_values) { 00273 00274 // Initialize: 00275 $this->resetStatusVars(); 00276 00277 // Reading Data Source if not done already. 00278 $this->readDataSource($table); 00279 00280 // If anything is there: 00281 if (is_array($this->data[$table])) { 00282 00283 // Parse WHERE clause: 00284 $where = $this->parseWhereClause($where); 00285 00286 if (is_array($where)) { 00287 00288 // Field information 00289 $fieldInformation = $this->admin_get_fields($table); // Should cache this...! 00290 00291 // Traverse fields to update: 00292 foreach($fields_values as $fName => $fValue) { 00293 $this->processAccordingToConfig($fields_values[$fName],$fieldInformation[$fName]); 00294 } 00295 #debug($fields_values); 00296 // Do query, returns array with keys to the data array of the result: 00297 $itemKeys = $this->selectFromData($table,$where); 00298 00299 // Set "last affected rows": 00300 $this->lastAffectedRows = count($itemKeys); 00301 00302 // Update rows: 00303 if ($this->lastAffectedRows) { 00304 // Traverse result set here: 00305 foreach($itemKeys as $dataArrayKey) { 00306 00307 // Traverse fields to update: 00308 foreach($fields_values as $fName => $fValue) { 00309 $this->data[$table][$dataArrayKey][$fName] = $fValue; 00310 } 00311 } 00312 00313 // Save data source 00314 $this->saveDataSource($table); 00315 } 00316 00317 return TRUE; 00318 } else $this->errorStatus = 'WHERE clause contained errors: '.$where; 00319 } else $this->errorStatus = 'No data loaded.'; 00320 00321 return FALSE; 00322 } 00323 00331 function exec_DELETEquery($table,$where) { 00332 00333 // Initialize: 00334 $this->resetStatusVars(); 00335 00336 // Reading Data Source if not done already. 00337 $this->readDataSource($table); 00338 00339 // If anything is there: 00340 if (is_array($this->data[$table])) { 00341 00342 // Parse WHERE clause: 00343 $where = $this->parseWhereClause($where); 00344 00345 if (is_array($where)) { 00346 00347 // Do query, returns array with keys to the data array of the result: 00348 $itemKeys = $this->selectFromData($table,$where); 00349 00350 // Set "last affected rows": 00351 $this->lastAffectedRows = count($itemKeys); 00352 00353 // Remove rows: 00354 if ($this->lastAffectedRows) { 00355 // Traverse result set: 00356 foreach($itemKeys as $dataArrayKey) { 00357 unset($this->data[$table][$dataArrayKey]); 00358 } 00359 00360 // Saving data source 00361 $this->saveDataSource($table); 00362 } 00363 00364 return TRUE; 00365 } else $this->errorStatus = 'WHERE clause contained errors: '.$where; 00366 } else $this->errorStatus = 'No data loaded.'; 00367 00368 return FALSE; 00369 } 00370 00382 function exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit) { 00383 00384 // Initialize: 00385 $this->resetStatusVars(); 00386 00387 // Create result object 00388 $sqlObj = t3lib_div::makeInstance('t3lib_sqlengine_resultobj'); 00389 $sqlObj->result = array(); // Empty result as a beginning 00390 00391 // Get table list: 00392 $tableArray = $this->parseFromTables($from_table); 00393 $table = $tableArray[0]['table']; 00394 00395 // Reading Data Source if not done already. 00396 $this->readDataSource($table); 00397 00398 // If anything is there: 00399 if (is_array($this->data[$table])) { 00400 00401 // Parse WHERE clause: 00402 $where = $this->parseWhereClause($where_clause); 00403 if (is_array($where)) { 00404 00405 // Do query, returns array with keys to the data array of the result: 00406 $itemKeys = $this->selectFromData($table,$where); 00407 00408 // Finally, read the result rows into this variable: 00409 $sqlObj->result = $this->getResultSet($itemKeys,$table,'*'); 00410 // Reset and return result: 00411 reset($sqlObj->result); 00412 return $sqlObj; 00413 } else $this->errorStatus = 'WHERE clause contained errors: '.$where; 00414 } else $this->errorStatus = 'No data loaded: '.$this->errorStatus; 00415 00416 return FALSE; 00417 } 00418 00425 function sql_query($query) { 00426 $res = t3lib_div::makeInstance('t3lib_sqlengine_resultobj'); 00427 $res->result = array(); 00428 return $res; 00429 } 00430 00436 function sql_error() { 00437 return $this->errorStatus; 00438 } 00439 00445 function sql_insert_id() { 00446 return $this->lastInsertedId; 00447 } 00448 00454 function sql_affected_rows() { 00455 return $this->lastAffectedRows; 00456 } 00457 00464 function quoteStr($str) { 00465 return addslashes($str); 00466 } 00467 00468 00469 00470 00471 00472 00473 00474 00475 00476 00477 /************************************** 00478 * 00479 * SQL admin functions 00480 * (For use in the Install Tool and Extension Manager) 00481 * 00482 **************************************/ 00483 00489 function admin_get_tables() { 00490 $whichTables = array(); 00491 return $whichTables; 00492 } 00493 00500 function admin_get_fields($tableName) { 00501 $output = array(); 00502 return $output; 00503 } 00504 00511 function admin_get_keys($tableName) { 00512 $output = array(); 00513 return $output; 00514 } 00515 00522 function admin_query($query) { 00523 return $this->sql_query($query); 00524 } 00525 00526 00527 00528 00529 00530 00531 00532 00533 /******************************** 00534 * 00535 * Data Source I/O 00536 * 00537 ********************************/ 00538 00547 function readDataSource($table) { 00548 $this->data[$table] = array(); 00549 } 00550 00559 function saveDataSource($table) { 00560 debug($this->data[$table]); 00561 } 00562 00563 00564 00565 00566 00567 00568 00569 00570 00571 00572 00573 00574 00575 /******************************** 00576 * 00577 * SQL engine functions (PHP simulation of SQL) - still experimental 00578 * 00579 ********************************/ 00580 00589 function selectFromData($table,$where) { 00590 00591 $output = array(); 00592 if (is_array($this->data[$table])) { 00593 00594 // All keys: 00595 $OR_index = 0; 00596 00597 foreach($where as $config) { 00598 00599 if (strtoupper($config['operator'])=='OR') { 00600 $OR_index++; 00601 } 00602 00603 if (!isset($itemKeys[$OR_index])) $itemKeys[$OR_index] = array_keys($this->data[$table]); 00604 00605 $this->select_evalSingle($table,$config,$itemKeys[$OR_index]); 00606 } 00607 00608 foreach($itemKeys as $uidKeys) { 00609 $output = array_merge($output, $uidKeys); 00610 } 00611 $output = array_unique($output); 00612 } 00613 00614 return $output; 00615 } 00616 00627 function select_evalSingle($table,$config,&$itemKeys) { 00628 $neg = preg_match('/^AND[[:space:]]+NOT$/',trim($config['operator'])); 00629 00630 if (is_array($config['sub'])) { 00631 $subSelKeys = $this->selectFromData($table,$config['sub']); 00632 if ($neg) { 00633 foreach($itemKeys as $kk => $vv) { 00634 if (in_array($vv,$subSelKeys)) { 00635 unset($itemKeys[$kk]); 00636 } 00637 } 00638 } else { 00639 $itemKeys = array_intersect($itemKeys, $subSelKeys); 00640 } 00641 } else { 00642 $comp = strtoupper(str_replace(array(' ',"\t","\r","\n"),'',$config['comparator'])); 00643 $mod = strtoupper($config['modifier']); 00644 switch($comp) { 00645 case 'NOTLIKE': 00646 case 'LIKE': 00647 $like_value = strtolower($config['value'][0]); 00648 if (substr($like_value,0,1)=='%') { 00649 $wildCard_begin = TRUE; 00650 $like_value = substr($like_value,1); 00651 } 00652 if (substr($like_value,-1)=='%') { 00653 $wildCard_end = TRUE; 00654 $like_value = substr($like_value,0,-1); 00655 } 00656 break; 00657 case 'NOTIN': 00658 case 'IN': 00659 $in_valueArray = array(); 00660 foreach($config['value'] as $vParts) { 00661 $in_valueArray[] = (string)$vParts[0]; 00662 } 00663 break; 00664 } 00665 00666 foreach($itemKeys as $kk => $v) { 00667 $field_value = $this->data[$table][$v][$config['field']]; 00668 00669 // Calculate it: 00670 if ($config['calc']=='&') { 00671 $field_value&=intval($config['calc_value']); 00672 } 00673 00674 // Compare it: 00675 switch($comp) { 00676 case '<=': 00677 $bool = $field_value <= $config['value'][0]; 00678 break; 00679 case '>=': 00680 $bool = $field_value >= $config['value'][0]; 00681 break; 00682 case '<': 00683 $bool = $field_value < $config['value'][0]; 00684 break; 00685 case '>': 00686 $bool = $field_value > $config['value'][0]; 00687 break; 00688 case '=': 00689 $bool = !strcmp($field_value,$config['value'][0]); 00690 break; 00691 case '!=': 00692 $bool = strcmp($field_value,$config['value'][0]); 00693 break; 00694 case 'NOTIN': 00695 case 'IN': 00696 $bool = in_array((string)$field_value, $in_valueArray); 00697 if ($comp=='NOTIN') $bool = !$bool; 00698 break; 00699 case 'NOTLIKE': 00700 case 'LIKE': 00701 if (!strlen($like_value)) { 00702 $bool = TRUE; 00703 } elseif ($wildCard_begin && !$wildCard_end) { 00704 $bool = !strcmp(substr(strtolower($field_value),-strlen($like_value)),$like_value); 00705 } elseif (!$wildCard_begin && $wildCard_end) { 00706 $bool = !strcmp(substr(strtolower($field_value),0,strlen($like_value)),$like_value); 00707 } elseif ($wildCard_begin && $wildCard_end) { 00708 $bool = strstr($field_value,$like_value); 00709 } else { 00710 $bool = !strcmp(strtolower($field_value),$like_value); 00711 } 00712 if ($comp=='NOTLIKE') $bool = !$bool; 00713 break; 00714 default: 00715 $bool = $field_value ? TRUE : FALSE; 00716 break; 00717 } 00718 00719 // General negation: 00720 if ($neg) $bool = !$bool; 00721 00722 // Modify? 00723 switch($mod) { 00724 case 'NOT': 00725 case '!': 00726 $bool = !$bool; 00727 break; 00728 } 00729 00730 // Action: 00731 if (!$bool) { 00732 unset($itemKeys[$kk]); 00733 } 00734 } 00735 00736 # echo $this->debug_printResultSet($this->getResultSet($itemKeys,$table,'uid,tstamp')); 00737 } 00738 } 00739 00748 function getResultSet($keys, $table, $fieldList) { 00749 $fields = t3lib_div::trimExplode(',',$fieldList); 00750 00751 $output = array(); 00752 foreach($keys as $kValue) { 00753 if ($fieldList=='*') { 00754 $output[$kValue] = $this->data[$table][$kValue]; 00755 } else { 00756 foreach($fields as $fieldName) { 00757 $output[$kValue][$fieldName] = $this->data[$table][$kValue][$fieldName]; 00758 } 00759 } 00760 } 00761 00762 return $output; 00763 } 00764 00765 00766 00767 00768 00769 00770 00771 00772 00773 00774 00775 00776 00777 00778 00779 /************************* 00780 * 00781 * Debugging 00782 * 00783 *************************/ 00784 00791 function debug_printResultSet($array) { 00792 00793 if (count($array)) { 00794 $tRows=array(); 00795 $fields = array_keys(current($array)); 00796 $tCell[]=' 00797 <td>IDX</td>'; 00798 foreach($fields as $fieldName) { 00799 $tCell[]=' 00800 <td>'.htmlspecialchars($fieldName).'</td>'; 00801 } 00802 $tRows[]='<tr>'.implode('',$tCell).'</tr>'; 00803 00804 00805 foreach($array as $index => $rec) { 00806 00807 $tCell=array(); 00808 $tCell[]=' 00809 <td>'.htmlspecialchars($index).'</td>'; 00810 foreach($fields as $fieldName) { 00811 $tCell[]=' 00812 <td>'.htmlspecialchars($rec[$fieldName]).'</td>'; 00813 } 00814 $tRows[]='<tr>'.implode('',$tCell).'</tr>'; 00815 } 00816 00817 return '<table border="1">'.implode('',$tRows).'</table>'; 00818 } else 'Empty resultset'; 00819 } 00820 } 00821 00822 00830 class t3lib_sqlengine_resultobj { 00831 00832 // Result array, must contain the fields in the order they were selected in the SQL statement (for sql_fetch_row()) 00833 var $result = array(); 00834 00835 var $TYPO3_DBAL_handlerType = ''; 00836 var $TYPO3_DBAL_tableList = ''; 00837 00838 00844 function sql_num_rows() { 00845 return count($this->result); 00846 } 00847 00853 function sql_fetch_assoc() { 00854 $row = current($this->result); 00855 next($this->result); 00856 return $row; 00857 } 00858 00864 function sql_fetch_row() { 00865 $resultRow = $this->sql_fetch_assoc(); 00866 00867 if (is_array($resultRow)) { 00868 $numArray = array(); 00869 foreach($resultRow as $value) { 00870 $numArray[]=$value; 00871 } 00872 return $numArray; 00873 } 00874 } 00875 00882 function sql_data_seek($pointer) { 00883 reset($this->result); 00884 for ($a=0;$a<$pointer;$a++) { 00885 next($this->result); 00886 } 00887 return TRUE; 00888 } 00889 00895 function sql_field_type() { 00896 return ''; 00897 } 00898 } 00899 00900 00901 00902 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_sqlengine.php']) { 00903 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_sqlengine.php']); 00904 } 00905 ?>