Documentation TYPO3 par Ameos |
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 2004 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 ***************************************************************/ 00091 require_once(PATH_t3lib.'class.t3lib_sqlparser.php'); 00092 00093 00102 class t3lib_sqlengine extends t3lib_sqlparser { 00103 00104 // array with data records: [table name][num.index] = records 00105 var $data = array(); // Data source storage 00106 00107 00108 // Internal, SQL Status vars: 00109 var $errorStatus = ''; // Set with error message of last operation 00110 var $lastInsertedId = 0; // Set with last inserted unique ID 00111 var $lastAffectedRows = 0; // Set with last number of affected rows. 00112 00113 00114 00115 00116 00124 function init($config, &$pObj) { 00125 } 00126 00132 function resetStatusVars() { 00133 $this->errorStatus = ''; 00134 $this->lastInsertedId = 0; 00135 $this->lastAffectedRows = 0; 00136 } 00137 00145 function processAccordingToConfig(&$value,$fInfo) { 00146 $options = $this->parseFieldDef($fInfo['Type']); 00147 00148 switch(strtolower($options['fieldType'])) { 00149 case 'int': 00150 case 'smallint': 00151 case 'tinyint': 00152 case 'mediumint': 00153 $value = intval($value); 00154 if ($options['featureIndex']['UNSIGNED']) { 00155 $value = t3lib_div::intInRange($value,0); 00156 } 00157 break; 00158 case 'double': 00159 $value = (double)$value; 00160 break; 00161 case 'varchar': 00162 case 'char': 00163 $value = substr($value,0,trim($options['value'])); 00164 break; 00165 case 'text': 00166 case 'blob': 00167 $value = substr($value,0,65536); 00168 break; 00169 case 'tinytext': 00170 case 'tinyblob': 00171 $value = substr($value,0,256); 00172 break; 00173 case 'mediumtext': 00174 case 'mediumblob': 00175 // ?? 00176 break; 00177 } 00178 } 00179 00180 00181 00182 00183 00184 00185 00186 /******************************** 00187 * 00188 * SQL queries 00189 * This is the SQL access functions used when this class is instantiated as a SQL handler with DBAL. Override these in derived classes. 00190 * 00191 ********************************/ 00192 00200 function exec_INSERTquery($table,$fields_values) { 00201 00202 // Initialize 00203 $this->resetStatusVars(); 00204 00205 // Reading Data Source if not done already. 00206 $this->readDataSource($table); 00207 00208 // If data source is set: 00209 if (is_array($this->data[$table])) { 00210 00211 $fieldInformation = $this->admin_get_fields($table); // Should cache this...! 00212 00213 // Looking for unique keys: 00214 $saveArray = array(); 00215 foreach($fieldInformation as $fInfo) { 00216 00217 // Field name: 00218 $fN = $fInfo['Field']; 00219 00220 // Set value: 00221 $saveArray[$fN] = isset($fields_values[$fN]) ? $fields_values[$fN] : $options['Default']; 00222 00223 // Process value: 00224 $this->processAccordingToConfig($saveArray[$fN], $fInfo); 00225 00226 // If an auto increment field is found, find the largest current uid: 00227 if ($fInfo['Extra'] == 'auto_increment') { 00228 00229 // Get all UIDs: 00230 $uidArray = array(); 00231 foreach($this->data[$table] as $r) { 00232 $uidArray[] = $r[$fN]; 00233 } 00234 00235 // If current value is blank or already in array, we create a new: 00236 if (!$saveArray[$fN] || in_array(intval($saveArray[$fN]), $uidArray)) { 00237 if (count($uidArray)) { 00238 $saveArray[$fN] = max($uidArray)+1; 00239 } else $saveArray[$fN] = 1; 00240 } 00241 00242 // Update "last inserted id": 00243 $this->lastInsertedId = $saveArray[$fN]; 00244 } 00245 } 00246 #debug(array($fields_values,$saveArray)); 00247 // Insert row in table: 00248 $this->data[$table][] = $saveArray; 00249 00250 // Save data source 00251 $this->saveDataSource($table); 00252 00253 return TRUE; 00254 } else $this->errorStatus = 'No data loaded.'; 00255 00256 return FALSE; 00257 } 00258 00267 function exec_UPDATEquery($table,$where,$fields_values) { 00268 00269 // Initialize: 00270 $this->resetStatusVars(); 00271 00272 // Reading Data Source if not done already. 00273 $this->readDataSource($table); 00274 00275 // If anything is there: 00276 if (is_array($this->data[$table])) { 00277 00278 // Parse WHERE clause: 00279 $where = $this->parseWhereClause($where); 00280 00281 if (is_array($where)) { 00282 00283 // Field information 00284 $fieldInformation = $this->admin_get_fields($table); // Should cache this...! 00285 00286 // Traverse fields to update: 00287 foreach($fields_values as $fName => $fValue) { 00288 $this->processAccordingToConfig($fields_values[$fName],$fieldInformation[$fName]); 00289 } 00290 #debug($fields_values); 00291 // Do query, returns array with keys to the data array of the result: 00292 $itemKeys = $this->selectFromData($table,$where); 00293 00294 // Set "last affected rows": 00295 $this->lastAffectedRows = count($itemKeys); 00296 00297 // Update rows: 00298 if ($this->lastAffectedRows) { 00299 // Traverse result set here: 00300 foreach($itemKeys as $dataArrayKey) { 00301 00302 // Traverse fields to update: 00303 foreach($fields_values as $fName => $fValue) { 00304 $this->data[$table][$dataArrayKey][$fName] = $fValue; 00305 } 00306 } 00307 00308 // Save data source 00309 $this->saveDataSource($table); 00310 } 00311 00312 return TRUE; 00313 } else $this->errorStatus = 'WHERE clause contained errors: '.$where; 00314 } else $this->errorStatus = 'No data loaded.'; 00315 00316 return FALSE; 00317 } 00318 00326 function exec_DELETEquery($table,$where) { 00327 00328 // Initialize: 00329 $this->resetStatusVars(); 00330 00331 // Reading Data Source if not done already. 00332 $this->readDataSource($table); 00333 00334 // If anything is there: 00335 if (is_array($this->data[$table])) { 00336 00337 // Parse WHERE clause: 00338 $where = $this->parseWhereClause($where); 00339 00340 if (is_array($where)) { 00341 00342 // Do query, returns array with keys to the data array of the result: 00343 $itemKeys = $this->selectFromData($table,$where); 00344 00345 // Set "last affected rows": 00346 $this->lastAffectedRows = count($itemKeys); 00347 00348 // Remove rows: 00349 if ($this->lastAffectedRows) { 00350 // Traverse result set: 00351 foreach($itemKeys as $dataArrayKey) { 00352 unset($this->data[$table][$dataArrayKey]); 00353 } 00354 00355 // Saving data source 00356 $this->saveDataSource($table); 00357 } 00358 00359 return TRUE; 00360 } else $this->errorStatus = 'WHERE clause contained errors: '.$where; 00361 } else $this->errorStatus = 'No data loaded.'; 00362 00363 return FALSE; 00364 } 00365 00377 function exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit) { 00378 00379 // Initialize: 00380 $this->resetStatusVars(); 00381 00382 // Create result object 00383 $sqlObj = t3lib_div::makeInstance('t3lib_sqlengine_resultobj'); 00384 $sqlObj->result = array(); // Empty result as a beginning 00385 00386 // Get table list: 00387 $tableArray = $this->parseFromTables($from_table); 00388 $table = $tableArray[0]['table']; 00389 00390 // Reading Data Source if not done already. 00391 $this->readDataSource($table); 00392 00393 // If anything is there: 00394 if (is_array($this->data[$table])) { 00395 00396 // Parse WHERE clause: 00397 $where = $this->parseWhereClause($where_clause); 00398 if (is_array($where)) { 00399 00400 // Do query, returns array with keys to the data array of the result: 00401 $itemKeys = $this->selectFromData($table,$where); 00402 00403 // Finally, read the result rows into this variable: 00404 $sqlObj->result = $this->getResultSet($itemKeys,$table,'*'); 00405 // Reset and return result: 00406 reset($sqlObj->result); 00407 return $sqlObj; 00408 } else $this->errorStatus = 'WHERE clause contained errors: '.$where; 00409 } else $this->errorStatus = 'No data loaded: '.$this->errorStatus; 00410 00411 return FALSE; 00412 } 00413 00420 function sql_query($query) { 00421 $res = t3lib_div::makeInstance('t3lib_sqlengine_resultobj'); 00422 $res->result = array(); 00423 return $res; 00424 } 00425 00431 function sql_error() { 00432 return $this->errorStatus; 00433 } 00434 00440 function sql_insert_id() { 00441 return $this->lastInsertedId; 00442 } 00443 00449 function sql_affected_rows() { 00450 return $this->lastAffectedRows; 00451 } 00452 00459 function quoteStr($str) { 00460 return addslashes($str); 00461 } 00462 00463 00464 00465 00466 00467 00468 00469 00470 00471 00472 /************************************** 00473 * 00474 * SQL admin functions 00475 * (For use in the Install Tool and Extension Manager) 00476 * 00477 **************************************/ 00478 00484 function admin_get_tables() { 00485 $whichTables = array(); 00486 return $whichTables; 00487 } 00488 00495 function admin_get_fields($tableName) { 00496 $output = array(); 00497 return $output; 00498 } 00499 00506 function admin_get_keys($tableName) { 00507 $output = array(); 00508 return $output; 00509 } 00510 00517 function admin_query($query) { 00518 return $this->sql_query($query); 00519 } 00520 00521 00522 00523 00524 00525 00526 00527 00528 /******************************** 00529 * 00530 * Data Source I/O 00531 * 00532 ********************************/ 00533 00542 function readDataSource($table) { 00543 $this->data[$table] = array(); 00544 } 00545 00554 function saveDataSource($table) { 00555 debug($this->data[$table]); 00556 } 00557 00558 00559 00560 00561 00562 00563 00564 00565 00566 00567 00568 00569 00570 /******************************** 00571 * 00572 * SQL engine functions 00573 * 00574 ********************************/ 00575 00583 function selectFromData($table,$where) { 00584 00585 $output = array(); 00586 if (is_array($this->data[$table])) { 00587 00588 // All keys: 00589 $OR_index = 0; 00590 00591 foreach($where as $config) { 00592 00593 if (strtoupper($config['operator'])=='OR') { 00594 $OR_index++; 00595 } 00596 00597 if (!isset($itemKeys[$OR_index])) $itemKeys[$OR_index] = array_keys($this->data[$table]); 00598 00599 $this->select_evalSingle($table,$config,$itemKeys[$OR_index]); 00600 } 00601 00602 foreach($itemKeys as $uidKeys) { 00603 $output = array_merge($output, $uidKeys); 00604 } 00605 $output = array_unique($output); 00606 } 00607 00608 return $output; 00609 } 00610 00619 function select_evalSingle($table,$config,&$itemKeys) { 00620 $neg = ereg('^AND[[:space:]]+NOT$',trim($config['operator'])); 00621 00622 if (is_array($config['sub'])) { 00623 $subSelKeys = $this->selectFromData($table,$config['sub']); 00624 if ($neg) { 00625 foreach($itemKeys as $kk => $vv) { 00626 if (in_array($vv,$subSelKeys)) { 00627 unset($itemKeys[$kk]); 00628 } 00629 } 00630 } else { 00631 $itemKeys = array_intersect($itemKeys, $subSelKeys); 00632 } 00633 } else { 00634 $comp = strtoupper(ereg_replace('[[:space:]]','',$config['comparator'])); 00635 $mod = strtoupper($config['modifier']); 00636 switch($comp) { 00637 case 'NOTLIKE': 00638 case 'LIKE': 00639 $like_value = strtolower($config['value'][0]); 00640 if (substr($like_value,0,1)=='%') { 00641 $wildCard_begin = TRUE; 00642 $like_value = substr($like_value,1); 00643 } 00644 if (substr($like_value,-1)=='%') { 00645 $wildCard_end = TRUE; 00646 $like_value = substr($like_value,0,-1); 00647 } 00648 break; 00649 case 'NOTIN': 00650 case 'IN': 00651 $in_valueArray = array(); 00652 foreach($config['value'] as $vParts) { 00653 $in_valueArray[] = (string)$vParts[0]; 00654 } 00655 break; 00656 } 00657 00658 foreach($itemKeys as $kk => $v) { 00659 $field_value = $this->data[$table][$v][$config['field']]; 00660 00661 // Calculate it: 00662 if ($config['calc']=='&') { 00663 $field_value&=intval($config['calc_value']); 00664 } 00665 00666 // Compare it: 00667 switch($comp) { 00668 case '<=': 00669 $bool = $field_value <= $config['value'][0]; 00670 break; 00671 case '>=': 00672 $bool = $field_value >= $config['value'][0]; 00673 break; 00674 case '<': 00675 $bool = $field_value < $config['value'][0]; 00676 break; 00677 case '>': 00678 $bool = $field_value > $config['value'][0]; 00679 break; 00680 case '=': 00681 $bool = !strcmp($field_value,$config['value'][0]); 00682 break; 00683 case '!=': 00684 $bool = strcmp($field_value,$config['value'][0]); 00685 break; 00686 case 'NOTIN': 00687 case 'IN': 00688 $bool = in_array((string)$field_value, $in_valueArray); 00689 if ($comp=='NOTIN') $bool = !$bool; 00690 break; 00691 case 'NOTLIKE': 00692 case 'LIKE': 00693 if (!strlen($like_value)) { 00694 $bool = TRUE; 00695 } elseif ($wildCard_begin && !$wildCard_end) { 00696 $bool = !strcmp(substr(strtolower($field_value),-strlen($like_value)),$like_value); 00697 } elseif (!$wildCard_begin && $wildCard_end) { 00698 $bool = !strcmp(substr(strtolower($field_value),0,strlen($like_value)),$like_value); 00699 } elseif ($wildCard_begin && $wildCard_end) { 00700 $bool = strstr($field_value,$like_value); 00701 } else { 00702 $bool = !strcmp(strtolower($field_value),$like_value); 00703 } 00704 if ($comp=='NOTLIKE') $bool = !$bool; 00705 break; 00706 default: 00707 $bool = $field_value ? TRUE : FALSE; 00708 break; 00709 } 00710 00711 // General negation: 00712 if ($neg) $bool = !$bool; 00713 00714 // Modify? 00715 switch($mod) { 00716 case 'NOT': 00717 case '!': 00718 $bool = !$bool; 00719 break; 00720 } 00721 00722 // Action: 00723 if (!$bool) { 00724 unset($itemKeys[$kk]); 00725 } 00726 } 00727 00728 # echo $this->debug_printResultSet($this->getResultSet($itemKeys,$table,'uid,tstamp')); 00729 } 00730 } 00731 00740 function getResultSet($keys, $table, $fieldList) { 00741 $fields = t3lib_div::trimExplode(',',$fieldList); 00742 00743 $output = array(); 00744 foreach($keys as $kValue) { 00745 if ($fieldList=='*') { 00746 $output[$kValue] = $this->data[$table][$kValue]; 00747 } else { 00748 foreach($fields as $fieldName) { 00749 $output[$kValue][$fieldName] = $this->data[$table][$kValue][$fieldName]; 00750 } 00751 } 00752 } 00753 00754 return $output; 00755 } 00756 00757 00758 00759 00760 00761 00762 00763 00764 00765 00766 00767 00768 00769 00770 00771 00772 00773 /************************* 00774 * 00775 * Debugging 00776 * 00777 *************************/ 00778 00785 function debug_printResultSet($array) { 00786 00787 if (count($array)) { 00788 $tRows=array(); 00789 $fields = array_keys(current($array)); 00790 $tCell[]=' 00791 <td>IDX</td>'; 00792 foreach($fields as $fieldName) { 00793 $tCell[]=' 00794 <td>'.htmlspecialchars($fieldName).'</td>'; 00795 } 00796 $tRows[]='<tr>'.implode('',$tCell).'</tr>'; 00797 00798 00799 foreach($array as $index => $rec) { 00800 00801 $tCell=array(); 00802 $tCell[]=' 00803 <td>'.htmlspecialchars($index).'</td>'; 00804 foreach($fields as $fieldName) { 00805 $tCell[]=' 00806 <td>'.htmlspecialchars($rec[$fieldName]).'</td>'; 00807 } 00808 $tRows[]='<tr>'.implode('',$tCell).'</tr>'; 00809 } 00810 00811 return '<table border="1">'.implode('',$tRows).'</table>'; 00812 } else 'Empty resultset'; 00813 } 00814 } 00815 00816 00824 class t3lib_sqlengine_resultobj { 00825 00826 // Result array, must contain the fields in the order they were selected in the SQL statement (for sql_fetch_row()) 00827 var $result = array(); 00828 00829 var $TYPO3_DBAL_handlerType = ''; 00830 var $TYPO3_DBAL_tableList = ''; 00831 00832 00838 function sql_num_rows() { 00839 return count($this->result); 00840 } 00841 00847 function sql_fetch_assoc() { 00848 $row = current($this->result); 00849 next($this->result); 00850 return $row; 00851 } 00852 00858 function sql_fetch_row() { 00859 $resultRow = $this->sql_fetch_assoc(); 00860 00861 if (is_array($resultRow)) { 00862 $numArray = array(); 00863 foreach($resultRow as $value) { 00864 $numArray[]=$value; 00865 } 00866 return $numArray; 00867 } 00868 } 00869 00876 function sql_data_seek($pointer) { 00877 reset($this->result); 00878 for ($a=0;$a<$pointer;$a++) { 00879 next($this->result); 00880 } 00881 return TRUE; 00882 } 00883 00889 function sql_field_type() { 00890 return ''; 00891 } 00892 } 00893 00894 00895 00896 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_sqlengine.php']) { 00897 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_sqlengine.php']); 00898 } 00899 ?>