Documentation TYPO3 par Ameos |
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 2004-2006 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 // FIXME $options not defined 00227 $saveArray[$fN] = isset($fields_values[$fN]) ? $fields_values[$fN] : $options['Default']; 00228 00229 // Process value: 00230 $this->processAccordingToConfig($saveArray[$fN], $fInfo); 00231 00232 // If an auto increment field is found, find the largest current uid: 00233 if ($fInfo['Extra'] == 'auto_increment') { 00234 00235 // Get all UIDs: 00236 $uidArray = array(); 00237 foreach($this->data[$table] as $r) { 00238 $uidArray[] = $r[$fN]; 00239 } 00240 00241 // If current value is blank or already in array, we create a new: 00242 if (!$saveArray[$fN] || in_array(intval($saveArray[$fN]), $uidArray)) { 00243 if (count($uidArray)) { 00244 $saveArray[$fN] = max($uidArray)+1; 00245 } else $saveArray[$fN] = 1; 00246 } 00247 00248 // Update "last inserted id": 00249 $this->lastInsertedId = $saveArray[$fN]; 00250 } 00251 } 00252 00253 // Insert row in table: 00254 $this->data[$table][] = $saveArray; 00255 00256 // Save data source 00257 $this->saveDataSource($table); 00258 00259 return TRUE; 00260 } else $this->errorStatus = 'No data loaded.'; 00261 00262 return FALSE; 00263 } 00264 00273 function exec_UPDATEquery($table,$where,$fields_values) { 00274 00275 // Initialize: 00276 $this->resetStatusVars(); 00277 00278 // Reading Data Source if not done already. 00279 $this->readDataSource($table); 00280 00281 // If anything is there: 00282 if (is_array($this->data[$table])) { 00283 00284 // Parse WHERE clause: 00285 $where = $this->parseWhereClause($where); 00286 00287 if (is_array($where)) { 00288 00289 // Field information 00290 $fieldInformation = $this->admin_get_fields($table); // Should cache this...! 00291 00292 // Traverse fields to update: 00293 foreach($fields_values as $fName => $fValue) { 00294 $this->processAccordingToConfig($fields_values[$fName],$fieldInformation[$fName]); 00295 } 00296 00297 // Do query, returns array with keys to the data array of the result: 00298 $itemKeys = $this->selectFromData($table,$where); 00299 00300 // Set "last affected rows": 00301 $this->lastAffectedRows = count($itemKeys); 00302 00303 // Update rows: 00304 if ($this->lastAffectedRows) { 00305 // Traverse result set here: 00306 foreach($itemKeys as $dataArrayKey) { 00307 00308 // Traverse fields to update: 00309 foreach($fields_values as $fName => $fValue) { 00310 $this->data[$table][$dataArrayKey][$fName] = $fValue; 00311 } 00312 } 00313 00314 // Save data source 00315 $this->saveDataSource($table); 00316 } 00317 00318 return TRUE; 00319 } else $this->errorStatus = 'WHERE clause contained errors: '.$where; 00320 } else $this->errorStatus = 'No data loaded.'; 00321 00322 return FALSE; 00323 } 00324 00332 function exec_DELETEquery($table,$where) { 00333 00334 // Initialize: 00335 $this->resetStatusVars(); 00336 00337 // Reading Data Source if not done already. 00338 $this->readDataSource($table); 00339 00340 // If anything is there: 00341 if (is_array($this->data[$table])) { 00342 00343 // Parse WHERE clause: 00344 $where = $this->parseWhereClause($where); 00345 00346 if (is_array($where)) { 00347 00348 // Do query, returns array with keys to the data array of the result: 00349 $itemKeys = $this->selectFromData($table,$where); 00350 00351 // Set "last affected rows": 00352 $this->lastAffectedRows = count($itemKeys); 00353 00354 // Remove rows: 00355 if ($this->lastAffectedRows) { 00356 // Traverse result set: 00357 foreach($itemKeys as $dataArrayKey) { 00358 unset($this->data[$table][$dataArrayKey]); 00359 } 00360 00361 // Saving data source 00362 $this->saveDataSource($table); 00363 } 00364 00365 return TRUE; 00366 } else $this->errorStatus = 'WHERE clause contained errors: '.$where; 00367 } else $this->errorStatus = 'No data loaded.'; 00368 00369 return FALSE; 00370 } 00371 00383 function exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy,$orderBy,$limit) { 00384 00385 // Initialize: 00386 $this->resetStatusVars(); 00387 00388 // Create result object 00389 $sqlObj = t3lib_div::makeInstance('t3lib_sqlengine_resultobj'); 00390 $sqlObj->result = array(); // Empty result as a beginning 00391 00392 // Get table list: 00393 $tableArray = $this->parseFromTables($from_table); 00394 $table = $tableArray[0]['table']; 00395 00396 // Reading Data Source if not done already. 00397 $this->readDataSource($table); 00398 00399 // If anything is there: 00400 if (is_array($this->data[$table])) { 00401 00402 // Parse WHERE clause: 00403 $where = $this->parseWhereClause($where_clause); 00404 if (is_array($where)) { 00405 00406 // Do query, returns array with keys to the data array of the result: 00407 $itemKeys = $this->selectFromData($table,$where); 00408 00409 // Finally, read the result rows into this variable: 00410 $sqlObj->result = $this->getResultSet($itemKeys,$table,'*'); 00411 // Reset and return result: 00412 reset($sqlObj->result); 00413 return $sqlObj; 00414 } else $this->errorStatus = 'WHERE clause contained errors: '.$where; 00415 } else $this->errorStatus = 'No data loaded: '.$this->errorStatus; 00416 00417 return FALSE; 00418 } 00419 00426 function sql_query($query) { 00427 $res = t3lib_div::makeInstance('t3lib_sqlengine_resultobj'); 00428 $res->result = array(); 00429 return $res; 00430 } 00431 00437 function sql_error() { 00438 return $this->errorStatus; 00439 } 00440 00446 function sql_insert_id() { 00447 return $this->lastInsertedId; 00448 } 00449 00455 function sql_affected_rows() { 00456 return $this->lastAffectedRows; 00457 } 00458 00465 function quoteStr($str) { 00466 return addslashes($str); 00467 } 00468 00469 00470 00471 00472 00473 00474 00475 00476 00477 00478 /************************************** 00479 * 00480 * SQL admin functions 00481 * (For use in the Install Tool and Extension Manager) 00482 * 00483 **************************************/ 00484 00490 function admin_get_tables() { 00491 $whichTables = array(); 00492 return $whichTables; 00493 } 00494 00501 function admin_get_fields($tableName) { 00502 $output = array(); 00503 return $output; 00504 } 00505 00512 function admin_get_keys($tableName) { 00513 $output = array(); 00514 return $output; 00515 } 00516 00523 function admin_query($query) { 00524 return $this->sql_query($query); 00525 } 00526 00527 00528 00529 00530 00531 00532 00533 00534 /******************************** 00535 * 00536 * Data Source I/O 00537 * 00538 ********************************/ 00539 00548 function readDataSource($table) { 00549 $this->data[$table] = array(); 00550 } 00551 00560 function saveDataSource($table) { 00561 debug($this->data[$table]); 00562 } 00563 00564 00565 00566 00567 00568 00569 00570 00571 00572 00573 00574 00575 00576 /******************************** 00577 * 00578 * SQL engine functions (PHP simulation of SQL) - still experimental 00579 * 00580 ********************************/ 00581 00590 function selectFromData($table,$where) { 00591 00592 $output = array(); 00593 if (is_array($this->data[$table])) { 00594 00595 // All keys: 00596 $OR_index = 0; 00597 00598 foreach($where as $config) { 00599 00600 if (strtoupper($config['operator'])=='OR') { 00601 $OR_index++; 00602 } 00603 00604 if (!isset($itemKeys[$OR_index])) $itemKeys[$OR_index] = array_keys($this->data[$table]); 00605 00606 $this->select_evalSingle($table,$config,$itemKeys[$OR_index]); 00607 } 00608 00609 foreach($itemKeys as $uidKeys) { 00610 $output = array_merge($output, $uidKeys); 00611 } 00612 $output = array_unique($output); 00613 } 00614 00615 return $output; 00616 } 00617 00628 function select_evalSingle($table,$config,&$itemKeys) { 00629 $neg = preg_match('/^AND[[:space:]]+NOT$/',trim($config['operator'])); 00630 00631 if (is_array($config['sub'])) { 00632 $subSelKeys = $this->selectFromData($table,$config['sub']); 00633 if ($neg) { 00634 foreach($itemKeys as $kk => $vv) { 00635 if (in_array($vv,$subSelKeys)) { 00636 unset($itemKeys[$kk]); 00637 } 00638 } 00639 } else { 00640 $itemKeys = array_intersect($itemKeys, $subSelKeys); 00641 } 00642 } else { 00643 $comp = strtoupper(str_replace(array(' ',"\t","\r","\n"),'',$config['comparator'])); 00644 $mod = strtoupper($config['modifier']); 00645 switch($comp) { 00646 case 'NOTLIKE': 00647 case 'LIKE': 00648 $like_value = strtolower($config['value'][0]); 00649 if (substr($like_value,0,1)=='%') { 00650 $wildCard_begin = TRUE; 00651 $like_value = substr($like_value,1); 00652 } 00653 if (substr($like_value,-1)=='%') { 00654 $wildCard_end = TRUE; 00655 $like_value = substr($like_value,0,-1); 00656 } 00657 break; 00658 case 'NOTIN': 00659 case 'IN': 00660 $in_valueArray = array(); 00661 foreach($config['value'] as $vParts) { 00662 $in_valueArray[] = (string)$vParts[0]; 00663 } 00664 break; 00665 } 00666 00667 foreach($itemKeys as $kk => $v) { 00668 $field_value = $this->data[$table][$v][$config['field']]; 00669 00670 // Calculate it: 00671 if ($config['calc']=='&') { 00672 $field_value&=intval($config['calc_value']); 00673 } 00674 00675 // Compare it: 00676 switch($comp) { 00677 case '<=': 00678 $bool = $field_value <= $config['value'][0]; 00679 break; 00680 case '>=': 00681 $bool = $field_value >= $config['value'][0]; 00682 break; 00683 case '<': 00684 $bool = $field_value < $config['value'][0]; 00685 break; 00686 case '>': 00687 $bool = $field_value > $config['value'][0]; 00688 break; 00689 case '=': 00690 $bool = !strcmp($field_value,$config['value'][0]); 00691 break; 00692 case '!=': 00693 $bool = strcmp($field_value,$config['value'][0]); 00694 break; 00695 case 'NOTIN': 00696 case 'IN': 00697 $bool = in_array((string)$field_value, $in_valueArray); 00698 if ($comp=='NOTIN') $bool = !$bool; 00699 break; 00700 case 'NOTLIKE': 00701 case 'LIKE': 00702 if (!strlen($like_value)) { 00703 $bool = TRUE; 00704 } elseif ($wildCard_begin && !$wildCard_end) { 00705 $bool = !strcmp(substr(strtolower($field_value),-strlen($like_value)),$like_value); 00706 } elseif (!$wildCard_begin && $wildCard_end) { 00707 $bool = !strcmp(substr(strtolower($field_value),0,strlen($like_value)),$like_value); 00708 } elseif ($wildCard_begin && $wildCard_end) { 00709 $bool = strstr($field_value,$like_value); 00710 } else { 00711 $bool = !strcmp(strtolower($field_value),$like_value); 00712 } 00713 if ($comp=='NOTLIKE') $bool = !$bool; 00714 break; 00715 default: 00716 $bool = $field_value ? TRUE : FALSE; 00717 break; 00718 } 00719 00720 // General negation: 00721 if ($neg) $bool = !$bool; 00722 00723 // Modify? 00724 switch($mod) { 00725 case 'NOT': 00726 case '!': 00727 $bool = !$bool; 00728 break; 00729 } 00730 00731 // Action: 00732 if (!$bool) { 00733 unset($itemKeys[$kk]); 00734 } 00735 } 00736 } 00737 } 00738 00747 function getResultSet($keys, $table, $fieldList) { 00748 $fields = t3lib_div::trimExplode(',',$fieldList); 00749 00750 $output = array(); 00751 foreach($keys as $kValue) { 00752 if ($fieldList=='*') { 00753 $output[$kValue] = $this->data[$table][$kValue]; 00754 } else { 00755 foreach($fields as $fieldName) { 00756 $output[$kValue][$fieldName] = $this->data[$table][$kValue][$fieldName]; 00757 } 00758 } 00759 } 00760 00761 return $output; 00762 } 00763 00764 00765 00766 00767 00768 00769 00770 00771 00772 00773 00774 00775 00776 00777 00778 /************************* 00779 * 00780 * Debugging 00781 * 00782 *************************/ 00783 00790 function debug_printResultSet($array) { 00791 00792 if (count($array)) { 00793 $tRows=array(); 00794 $fields = array_keys(current($array)); 00795 $tCell[]=' 00796 <td>IDX</td>'; 00797 foreach($fields as $fieldName) { 00798 $tCell[]=' 00799 <td>'.htmlspecialchars($fieldName).'</td>'; 00800 } 00801 $tRows[]='<tr>'.implode('',$tCell).'</tr>'; 00802 00803 00804 foreach($array as $index => $rec) { 00805 00806 $tCell=array(); 00807 $tCell[]=' 00808 <td>'.htmlspecialchars($index).'</td>'; 00809 foreach($fields as $fieldName) { 00810 $tCell[]=' 00811 <td>'.htmlspecialchars($rec[$fieldName]).'</td>'; 00812 } 00813 $tRows[]='<tr>'.implode('',$tCell).'</tr>'; 00814 } 00815 00816 return '<table border="1">'.implode('',$tRows).'</table>'; 00817 } else 'Empty resultset'; 00818 } 00819 } 00820 00821 00829 class t3lib_sqlengine_resultobj { 00830 00831 // Result array, must contain the fields in the order they were selected in the SQL statement (for sql_fetch_row()) 00832 var $result = array(); 00833 00834 var $TYPO3_DBAL_handlerType = ''; 00835 var $TYPO3_DBAL_tableList = ''; 00836 00837 00843 function sql_num_rows() { 00844 return count($this->result); 00845 } 00846 00852 function sql_fetch_assoc() { 00853 $row = current($this->result); 00854 next($this->result); 00855 return $row; 00856 } 00857 00863 function sql_fetch_row() { 00864 $resultRow = $this->sql_fetch_assoc(); 00865 00866 if (is_array($resultRow)) { 00867 $numArray = array(); 00868 foreach($resultRow as $value) { 00869 $numArray[]=$value; 00870 } 00871 return $numArray; 00872 } 00873 } 00874 00881 function sql_data_seek($pointer) { 00882 reset($this->result); 00883 for ($a=0;$a<$pointer;$a++) { 00884 next($this->result); 00885 } 00886 return TRUE; 00887 } 00888 00894 function sql_field_type() { 00895 return ''; 00896 } 00897 } 00898 00899 00900 00901 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_sqlengine.php']) { 00902 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_sqlengine.php']); 00903 } 00904 ?>