Initial revision
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_querygenerator.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2001-2003 Christian Jul Jensen (christian@typo3.com)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 *
29 * @author Christian Jul Jensen <christian@typo3.com>
30 * @author Kasper Skårhøj <kasper@typo3.com>
31 * @package TYPO3
32 * @subpackage t3lib
33 */
34
35 class t3lib_queryGenerator {
36 var $lang = array(
37 "OR" => "or",
38 "AND" => "and",
39 "comparison" => array(
40 // Type = text offset = 0
41 "0_" => "contains",
42 "1_" => "does not contain",
43 "2_" => "starts with",
44 "3_" => "does not start with",
45 "4_" => "ends with",
46 "5_" => "does not end with",
47 "6_" => "equals",
48 "7_" => "does not equal",
49 // Type = date,number , offset = 32
50 "32_" => "equals",
51 "33_" => "does not equal",
52 "34_" => "is greater than",
53 "35_" => "is less than",
54 "36_" => "is between",
55 "37_" => "is not between",
56 "38_" => "is in list",
57 "39_" => "is not in list",
58 "40_" => "binary AND equals",
59 "41_" => "binary AND does not equal",
60 "42_" => "binary OR equals",
61 "43_" => "binary OR does not equal"
62 )
63 );
64
65 var $compSQL = array(
66 // Type = text offset = 0
67 "0" => "#FIELD# LIKE '%#VALUE#%'",
68 "1" => "#FIELD# NOT LIKE '%#VALUE#%'",
69 "2" => "#FIELD# LIKE '#VALUE#%'",
70 "3" => "#FIELD# NOT LIKE '#VALUE#%'",
71 "4" => "#FIELD# LIKE '%#VALUE#'",
72 "5" => "#FIELD# NOT LIKE '%#VALUE#'",
73 "6" => "#FIELD# = '#VALUE#'",
74 "7" => "#FIELD# != '#VALUE#'",
75 // Type = date,number , offset = 32
76 "32" => "#FIELD# = '#VALUE#'",
77 "33" => "#FIELD# != '#VALUE#'",
78 "34" => "#FIELD# > #VALUE#",
79 "35" => "#FIELD# < #VALUE#",
80 "36" => "#FIELD# >= #VALUE# AND #FIELD# <= #VALUE1#",
81 "37" => "NOT (#FIELD# >= #VALUE# AND #FIELD# <= #VALUE1#)",
82 "38" => "#FIELD# IN (#VALUE#)",
83 "39" => "#FIELD# NOT IN (#VALUE#)",
84 "40" => "(#FIELD# & #VALUE#)=#VALUE#",
85 "41" => "(#FIELD# & #VALUE#)!=#VALUE#",
86 "42" => "(#FIELD# | #VALUE#)=#VALUE#",
87 "43" => "(#FIELD# | #VALUE#)!=#VALUE#"
88 );
89
90 var $comp_offsets = array(
91 "text" => 0,
92 "number" => 1,
93 "date" => 1
94 );
95 var $noWrap=" nowrap";
96
97 var $name; // Form data name prefix
98 var $table; // table for the query
99 var $fieldList; // field list
100 var $fields = array(); // Array of the fields possible
101 var $extFieldLists = array();
102 var $queryConfig=array(); // The query config
103 var $enablePrefix=0;
104 var $enableQueryParts = 0;
105 var $extJSCODE="";
106
107 function makeFieldList() {
108 global $TCA;
109 $fieldListArr = array();
110 if (is_array($TCA[$this->table])) {
111 t3lib_div::loadTCA($this->table);
112 reset($TCA[$this->table]["columns"]);
113 while(list($fN)=each($TCA[$this->table]["columns"])) {
114 $fieldListArr[]=$fN;
115 }
116 $fieldListArr[]="uid";
117 $fieldListArr[]="pid";
118 if ($TCA[$this->table]["ctrl"]["tstamp"]) $fieldListArr[]=$TCA[$this->table]["ctrl"]["tstamp"];
119 if ($TCA[$this->table]["ctrl"]["crdate"]) $fieldListArr[]=$TCA[$this->table]["ctrl"]["crdate"];
120 if ($TCA[$this->table]["ctrl"]["cruser_id"]) $fieldListArr[]=$TCA[$this->table]["ctrl"]["cruser_id"];
121 if ($TCA[$this->table]["ctrl"]["sortby"]) $fieldListArr[]=$TCA[$this->table]["ctrl"]["sortby"];
122 }
123 return implode(",",$fieldListArr);
124 }
125 function init($name,$table,$fieldList="") {
126 global $TCA;
127
128 // Analysing the fields in the table.
129 if (is_array($TCA[$table])) {
130 t3lib_div::loadTCA($table);
131 $this->name = $name;
132 $this->table = $table;
133 $this->fieldList = $fieldList ? $fieldList : $this->makeFieldList();
134
135 $fieldArr = t3lib_div::trimExplode(",",$this->fieldList,1);
136 reset($fieldArr);
137 while(list(,$fN)=each($fieldArr)) {
138 $fC = $TCA[$this->table]["columns"][$fN];
139 if (is_array($fC) && $fC["label"]) {
140 $this->fields[$fN]["label"] = stripslashes(ereg_replace(":$","",trim($GLOBALS["LANG"]->sL($fC["label"]))));
141 switch($fC["config"]["type"]) {
142 case "input":
143 if (eregi("int|year",$fC["config"]["eval"])) {
144 $this->fields[$fN]["type"]="number";
145 } elseif (eregi("date|time",$fC["config"]["eval"])) {
146 $this->fields[$fN]["type"]="date";
147 } else {
148 $this->fields[$fN]["type"]="text";
149 }
150 break;
151 case "check":
152 case "select":
153 $this->fields[$fN]["type"]="number";
154 break;
155 case "text":
156 default:
157 $this->fields[$fN]["type"]="text";
158 break;
159 }
160
161 } else {
162 $this->fields[$fN]["label"]="[FIELD: ".$fN."]";
163 $this->fields[$fN]["type"]="number";
164 }
165 }
166 }
167
168 /* // EXAMPLE:
169 $this->queryConfig = array(
170 array(
171 "operator" => "AND",
172 "type" => "FIELD_spaceBefore",
173 ),
174 array(
175 "operator" => "AND",
176 "type" => "FIELD_records",
177 "negate" => 1,
178 "inputValue" => "foo foo"
179 ),
180 array(
181 "type" => "newlevel",
182 "nl" => array(
183 array(
184 "operator" => "AND",
185 "type" => "FIELD_spaceBefore",
186 "negate" => 1,
187 "inputValue" => "foo foo"
188 ),
189 array(
190 "operator" => "AND",
191 "type" => "FIELD_records",
192 "negate" => 1,
193 "inputValue" => "foo foo"
194 )
195 )
196 ),
197 array(
198 "operator" => "OR",
199 "type" => "FIELD_maillist",
200 )
201 );
202 */
203 $this->initUserDef();
204 }
205 function setAndCleanUpExternalLists($name,$list,$force="") {
206 $fields = array_unique(t3lib_div::trimExplode(",",$list.",".$force,1));
207 reset($fields);
208 $reList=array();
209 while(list(,$fN)=each($fields)) {
210 if ($this->fields[$fN]) $reList[]=$fN;
211 }
212 $this->extFieldLists[$name]=implode(",",$reList);
213 }
214 function procesData($qC="") {
215 $this->queryConfig = $qC;
216 t3lib_div::stripSlashesOnArray($this->queryConfig);
217
218 /* // adjust queryConfig to match requests from user
219 if($GLOBALS["HTTP_POST_VARS"]["queryConfig"]) {
220 $this->queryConfig = $GLOBALS["HTTP_POST_VARS"]["queryConfig"];
221 t3lib_div::stripSlashesOnArray($this->queryConfig);
222 }
223 */
224 // if delete...
225 if($GLOBALS["HTTP_POST_VARS"]["qG_del"]) {
226 //initialize array to work on, save special parameters
227 $ssArr = $this->getSubscript($GLOBALS["HTTP_POST_VARS"]["qG_del"]);
228 $workArr =& $this->queryConfig;
229 for($i=0;$i<sizeof($ssArr)-1;$i++) {
230 $workArr =& $workArr[$ssArr[$i]];
231 }
232 // delete the entry and move the other entries
233 unset($workArr[$ssArr[$i]]);
234 for($j=$ssArr[$i];$j<sizeof($workArr);$j++) {
235 $workArr[$j] = $workArr[$j+1];
236 unset($workArr[$j+1]);
237 }
238 }
239
240 // if insert...
241 if($GLOBALS["HTTP_POST_VARS"]["qG_ins"]) {
242 //initialize array to work on, save special parameters
243 $ssArr = $this->getSubscript($GLOBALS["HTTP_POST_VARS"]["qG_ins"]);
244 $workArr =& $this->queryConfig;
245 for($i=0;$i<sizeof($ssArr)-1;$i++) {
246 $workArr =& $workArr[$ssArr[$i]];
247 }
248 // move all entries above position where new entry is to be inserted
249 for($j=sizeof($workArr);$j>$ssArr[$i];$j--) {
250 $workArr[$j] = $workArr[$j-1];
251 }
252 //clear new entry position
253 unset($workArr[$ssArr[$i]+1]);
254 $workArr[$ssArr[$i]+1]['type'] = "FIELD_";
255 }
256
257 // if move up...
258 if($GLOBALS["HTTP_POST_VARS"]["qG_up"]) {
259 //initialize array to work on
260 $ssArr = $this->getSubscript($GLOBALS["HTTP_POST_VARS"]["qG_up"]);
261 $workArr =& $this->queryConfig;
262 for($i=0;$i<sizeof($ssArr)-1;$i++) {
263 $workArr =& $workArr[$ssArr[$i]];
264 }
265 //swap entries
266 $qG_tmp = $workArr[$ssArr[$i]];
267 $workArr[$ssArr[$i]] = $workArr[$ssArr[$i]-1];
268 $workArr[$ssArr[$i]-1] = $qG_tmp;
269 }
270
271 // if new level...
272 if($GLOBALS["HTTP_POST_VARS"]["qG_nl"]) {
273 //initialize array to work on
274 $ssArr = $this->getSubscript($GLOBALS["HTTP_POST_VARS"]["qG_nl"]);
275 $workArr =& $this->queryConfig;
276 for($i=0;$i<sizeof($ssArr)-1;$i++) {
277 $workArr =& $workArr[$ssArr[$i]];
278 }
279 // Do stuff:
280 $tempEl = $workArr[$ssArr[$i]];
281 if (is_array($tempEl)) {
282 if ($tempEl["type"]!="newlevel") {
283 $workArr[$ssArr[$i]]=array(
284 "type" => "newlevel",
285 "operator" => $tempEl["operator"],
286 "nl" => array($tempEl)
287 );
288 }
289 }
290 }
291
292 // if collapse level...
293 if($GLOBALS["HTTP_POST_VARS"]["qG_remnl"]) {
294 //initialize array to work on
295 $ssArr = $this->getSubscript($GLOBALS["HTTP_POST_VARS"]["qG_remnl"]);
296 $workArr =& $this->queryConfig;
297 for($i=0;$i<sizeof($ssArr)-1;$i++) {
298 $workArr =& $workArr[$ssArr[$i]];
299 }
300
301 // Do stuff:
302 $tempEl = $workArr[$ssArr[$i]];
303 if (is_array($tempEl)) {
304 if ($tempEl["type"]=="newlevel") {
305 $a1 = array_slice($workArr,0,$ssArr[$i]);
306 $a2 = array_slice($workArr,$ssArr[$i]);
307 array_shift($a2);
308 $a3 = $tempEl["nl"];
309 $a3[0]["operator"] = $tempEl["operator"];
310 $workArr=array_merge($a1,$a3,$a2);
311 }
312 }
313 }
314 }
315 function cleanUpQueryConfig($queryConfig) {
316 //since we dont traverse the array using numeric keys in the upcoming whileloop make sure it's fresh and clean before displaying
317 if (is_array($queryConfig)) {
318 ksort($queryConfig);
319 } else {
320 //queryConfig should never be empty!
321 if(!$queryConfig[0] || !$queryConfig[0]["type"]) $queryConfig[0] = array("type"=>"FIELD_");
322 }
323 // Traverse:
324 reset($queryConfig);
325 $c=0;
326 $arrCount=0;
327 while(list($key,$conf)=each($queryConfig)) {
328 if(substr($conf["type"],0,6)=="FIELD_") {
329 $fName = substr($conf["type"],6);
330 $fType = $this->fields[$fName]["type"];
331 } elseif($conf["type"]=="newlevel") {
332 $fType = $conf["type"];
333 } else {
334 $fType = "ignore";
335 }
336 // debug($fType);
337 switch($fType) {
338 case "newlevel":
339 if(!$queryConfig[$key]["nl"]) $queryConfig[$key]["nl"][0]["type"] = "FIELD_";
340 $queryConfig[$key]["nl"]=$this->cleanUpQueryConfig($queryConfig[$key]["nl"]);
341 break;
342 case "userdef":
343 $queryConfig[$key]=$this->userDefCleanUp($queryConfig[$key]);
344 break;
345 case "ignore":
346 default:
347 // debug($queryConfig[$key]);
348 $verifiedName=$this->verifyType($fName);
349 $queryConfig[$key]["type"]="FIELD_".$this->verifyType($verifiedName);
350
351 if($conf["comparison"] >> 5 != $this->comp_offsets[$fType]) $conf["comparison"] = $this->comp_offsets[$fType] << 5;
352 $queryConfig[$key]["comparison"]=$this->verifyComparison($conf["comparison"],$conf["negate"]?1:0);
353
354 $queryConfig[$key]["inputValue"]=stripslashes($this->cleanInputVal($queryConfig[$key]));
355 $queryConfig[$key]["inputValue1"]=stripslashes($this->cleanInputVal($queryConfig[$key],1));
356
357 // debug($queryConfig[$key]);
358 break;
359 }
360 }
361 return $queryConfig;
362 }
363 function getFormElements($subLevel=0,$queryConfig="",$parent="") {
364 $codeArr=array();
365 if (!is_array($queryConfig)) $queryConfig=$this->queryConfig;
366
367 reset($queryConfig);
368 $c=0;
369 $arrCount=0;
370 while(list($key,$conf)=each($queryConfig)) {
371 $subscript = $parent."[$key]";
372 $lineHTML = "";
373 $lineHTML.=$this->mkOperatorSelect($this->name.$subscript,$conf["operator"],$c,($conf["type"]!="FIELD_"));
374 if(substr($conf["type"],0,6)=="FIELD_") {
375 $fName = substr($conf["type"],6);
376 $fType = $this->fields[$fName]["type"];
377 if($conf["comparison"] >> 5 != $this->comp_offsets[$fType]) $conf["comparison"] = $this->comp_offsets[$fType] << 5;
378
379 //nasty nasty...
380 //make sure queryConfig contains _actual_ comparevalue.
381 //mkCompSelect don't care, but getQuery does.
382 $queryConfig[$key]["comparison"] += (isset($conf["negate"])-($conf["comparison"]%2));
383
384 } elseif($conf["type"]=="newlevel") {
385 $fType = $conf["type"];
386 } else {
387 $fType = "ignore";
388 }
389 // debug($fType);
390 switch($fType) {
391 case "ignore":
392 break;
393 case "newlevel":
394 if(!$queryConfig[$key]["nl"]) $queryConfig[$key]["nl"][0]["type"] = "FIELD_";
395 $lineHTML.='<input type="hidden" name="'.$this->name.$subscript.'[type]" value="newlevel">';
396 $codeArr[$arrCount]["sub"] = $this->getFormElements($subLevel+1,$queryConfig[$key]["nl"],$subscript."[nl]");
397 break;
398 case "userdef":
399 $lineHTML.=$this->userDef($this->name.$subscript,$conf,$fName,$fType);
400 break;
401 default:
402 $lineHTML.=$this->mkTypeSelect($this->name.$subscript.'[type]',$fName);
403 $lineHTML.=$this->mkCompSelect($this->name.$subscript.'[comparison]',$conf["comparison"],$conf["negate"]?1:0);
404 $lineHTML.='<input type="checkbox" '.($conf["negate"]?"checked":"").' name="'.$this->name.$subscript.'[negate]'.'" onClick="submit();">';
405
406 if ($conf["comparison"]==37 || $conf["comparison"]==36) { // between:
407 $lineHTML.='<input type="text" value="'.htmlspecialchars($conf["inputValue"]).'" name="'.$this->name.$subscript.'[inputValue]'.'"'.$GLOBALS["TBE_TEMPLATE"]->formWidth(5).'>
408 <input type="text" value="'.htmlspecialchars($conf["inputValue1"]).'" name="'.$this->name.$subscript.'[inputValue1]'.'"'.$GLOBALS["TBE_TEMPLATE"]->formWidth(5).'>
409 '; // onChange="submit();"
410 } elseif ($fType=="date") {
411 $lineHTML.='<input type="text" name="'.$this->name.$subscript.'[inputValue]_hr'.'"'.$GLOBALS["TBE_TEMPLATE"]->formWidth(10).' onChange="typo3FormFieldGet(\''.$this->name.$subscript.'[inputValue]\', \'datetime\', \'\', 0,0);"><input type="hidden" value="'.htmlspecialchars($conf["inputValue"]).'" name="'.$this->name.$subscript.'[inputValue]'.'">';
412 $this->extJSCODE.='typo3FormFieldSet("'.$this->name.$subscript.'[inputValue]", "datetime", "", 0,0);';
413 } else {
414 $lineHTML.='<input type="text" value="'.htmlspecialchars($conf["inputValue"]).'" name="'.$this->name.$subscript.'[inputValue]'.'"'.$GLOBALS["TBE_TEMPLATE"]->formWidth(10).'>'; // onChange="submit();"
415 }
416 break;
417 }
418 if($fType != "ignore") {
419 $lineHTML .= $this->updateIcon();
420 $lineHTML .= '<input type="image" border=0 src="'.$GLOBALS["BACK_PATH"].'gfx/garbage.gif" align="absmiddle" width="11" height="12" hspace=3 vspace=3 title="Remove condition" name="qG_del'.$subscript.'">';
421 $lineHTML .= '<input type="image" border=0 src="'.$GLOBALS["BACK_PATH"].'gfx/add.gif" align="absmiddle" width="12" height="12" hspace=3 vspace=3 title="Add condition" name="qG_ins'.$subscript.'">';
422 if($c!=0) $lineHTML.= '<input type="image" border=0 src="'.$GLOBALS["BACK_PATH"].'gfx/pil2up.gif" align="absmiddle" width="12" height="7" hspace=3 vspace=3 title="Move up" name="qG_up'.$subscript.'">';
423
424 if($c!=0 && $fType!="newlevel") {
425 $lineHTML.= '<input type="image" border=0 src="'.$GLOBALS["BACK_PATH"].'gfx/pil2right.gif" align="absmiddle" height="12" width="7" hspace=3 vspace=3 title="New level" name="qG_nl'.$subscript.'">';
426 }
427 if($fType=="newlevel") {
428 $lineHTML.= '<input type="image" border=0 src="'.$GLOBALS["BACK_PATH"].'gfx/pil2left.gif" align="absmiddle" height="12" width="7" hspace=3 vspace=3 title="Collapse new level" name="qG_remnl'.$subscript.'">';
429 }
430
431 $codeArr[$arrCount]["html"] = $lineHTML;
432 $codeArr[$arrCount]["query"] = $this->getQuerySingle($conf,$c>0?0:1);
433 $arrCount++;
434 $c++;
435 }
436 }
437 // $codeArr[$arrCount] .='<input type="hidden" name="CMD" value="displayQuery">';
438 $this->queryConfig = $queryConfig;
439 //modifyHTMLColor($color,$R,$G,$B)
440 return $codeArr;
441 }
442 function printCodeArray($codeArr,$l=0) {
443 reset($codeArr);
444 $line="";
445 if ($l) $indent='<td><img height="1" width="50"></td>';
446 $lf=$l*30;
447 $bgColor = t3lib_div::modifyHTMLColor($GLOBALS["TBE_TEMPLATE"]->bgColor2,$lf,$lf,$lf);
448 while(list($k,$v)=each($codeArr)) {
449 $line.= '<tr>'.$indent.'<td bgcolor="'.$bgColor.'"'.$this->noWrap.'>'.$v["html"].'</td></tr>';
450 if ($this->enableQueryParts) {$line.= '<tr>'.$indent.'<td>'.$this->formatQ($v["query"]).'</td></tr>';}
451 if (is_array($v["sub"])) {
452 $line.= '<tr>'.$indent.'<td'.$this->noWrap.'>'.$this->printCodeArray($v["sub"],$l+1).'</td></tr>';
453 }
454 }
455 $out='<table border=0 cellpadding=0 cellspacing=1>'.$line.'</table>';
456 return $out;
457 }
458 function formatQ($str) {
459 return '<font size=1 face=verdana color=maroon><i>'.$str.'</i></font>';
460 }
461 function mkOperatorSelect($name,$op,$draw,$submit) {
462 if ($draw) {
463 $out='<select name="'.$name.'[operator]"'.($submit?' onChange="submit();"':'').'>'; //
464 $out.='<option value="AND"'.(!$op||$op=="AND" ? ' selected':'').'>'.$this->lang["AND"].'</option>';
465 $out.='<option value="OR"'.($op=="OR" ? ' selected':'').'>'.$this->lang["OR"].'</option>';
466 $out.='</select>';
467 } else {
468 $out.='<input type="hidden" value="'.$op.'" name="'.$name.'[operator]">';
469 $out.='<img src="clear.gif" height="1" width="47">';
470
471 }
472 return $out;
473 }
474 function mkTypeSelect($name,$fieldName,$prepend="FIELD_") {
475 $out='<select name="'.$name.'" onChange="submit();">';
476 $out.='<option value=""></option>';
477 reset($this->fields);
478 while(list($key,)=each($this->fields)) {
479 if ($GLOBALS["BE_USER"]->check("non_exclude_fields",$this->table.":".$key)) {
480 $out.='<option value="'.$prepend.$key.'"'.($key==$fieldName ? ' selected':'').'>'.$this->fields[$key]["label"].'</option>';
481 }
482 }
483 $out.='</select>';
484 return $out;
485 }
486 function verifyType($fieldName) {
487 reset($this->fields);
488 $first = "";
489 while(list($key,)=each($this->fields)) {
490 if (!$first) $first = $key;
491 if ($key==$fieldName) return $key;
492 }
493 return $first;
494 }
495 function verifyComparison($comparison,$neg) {
496 $compOffSet = $comparison >> 5;
497 $first=-1;
498 for($i=32*$compOffSet+$neg;$i<32*($compOffSet+1);$i+=2) {
499 if ($first==-1) $first = $i;
500 if (($i >> 1)==($comparison >> 1)) {
501 return $i;
502 }
503 }
504 return $first;
505 }
506 function mkFieldToInputSelect($name,$fieldName) {
507 $out='<input type="Text" value="'.htmlspecialchars($fieldName).'" name="'.$name.'"'.$GLOBALS["TBE_TEMPLATE"]->formWidth().'>'.$this->updateIcon();
508 $out.='<a href="#" onClick="document.forms[0][\''.$name.'\'].value=\'\';return false;"><img src="'.$GLOBALS["BACK_PATH"].'gfx/garbage.gif" align="absmiddle" width="11" height="12" hspace=3 vspace=3 title="Clear list" border=0></a>';
509 $out.='<BR><select name="_fieldListDummy" size=5 onChange="document.forms[0][\''.$name.'\'].value+=\',\'+this.value">';
510 reset($this->fields);
511 while(list($key,)=each($this->fields)) {
512 if ($GLOBALS["BE_USER"]->check("non_exclude_fields",$this->table.":".$key)) {
513 $out.='<option value="'.$prepend.$key.'"'.($key==$fieldName ? ' selected':'').'>'.$this->fields[$key]["label"].'</option>';
514 }
515 }
516 $out.='</select>';
517 return $out;
518 }
519 function mkTableSelect($name,$cur) {
520 global $TCA;
521 $out='<select name="'.$name.'" onChange="submit();">';
522 $out.='<option value=""></option>';
523 reset($TCA);
524 while(list($tN)=each($TCA)) {
525 if ($GLOBALS["BE_USER"]->check("tables_select",$tN)) {
526 $out.='<option value="'.$tN.'"'.($tN==$cur ? ' selected':'').'>'.$GLOBALS["LANG"]->sl($TCA[$tN]["ctrl"]["title"]).'</option>';
527 }
528 }
529 $out.='</select>';
530 return $out;
531 }
532 function mkCompSelect($name,$comparison,$neg) {
533 $compOffSet = $comparison >> 5;
534 $out='<select name="'.$name.'" onChange="submit();">';
535 for($i=32*$compOffSet+$neg;$i<32*($compOffSet+1);$i+=2) {
536 if($this->lang["comparison"][$i."_"]) {
537 $out.='<option value="'.$i.'"'.(($i >> 1)==($comparison >> 1) ? ' selected':'').'>'.$this->lang["comparison"][$i."_"].'</option>';
538 }
539 }
540 $out.='</select>';
541 return $out;
542 }
543
544 function getSubscript($arr) {
545 while(is_array($arr)) {
546 reset($arr);
547 list($key,)=each($arr);
548 $retArr[] = $key;
549 $arr = $arr[$key];
550 }
551 return $retArr;
552 }
553
554 function initUserDef() {
555
556 }
557
558 function userDef() {
559 }
560 function userDefCleanUp($queryConfig) {
561 return $queryConfig;
562 }
563
564 function getQuery ($queryConfig,$pad="") {
565 $qs = "";
566 //since wo dont traverse the array using numeric keys in the upcoming whileloop make sure it's fresh and clean
567 ksort($queryConfig);
568 reset($queryConfig);
569 $first=1;
570 while(list($key,$conf) = each($queryConfig)) {
571 switch($conf["type"]) {
572 case "newlevel":
573 $qs.=chr(10).$pad.trim($conf["operator"])." (".$this->getQuery($queryConfig[$key]["nl"],$pad." ").chr(10).$pad.")";
574 break;
575 case "userdef":
576 $qs.=chr(10).$pad.getUserDefQuery($conf,$first);
577 break;
578 default:
579 $qs.=chr(10).$pad.$this->getQuerySingle($conf,$first);
580 break;
581 }
582 $first=0;
583 }
584 return $qs;
585 }
586 function getQuerySingle($conf,$first) {
587 $prefix = $this->enablePrefix ? $this->table."." : "";
588 if (!$first) {$qs.= trim(($conf["operator"]?$conf["operator"]:"AND"))." ";} // Is it OK to insert the AND operator if none is set?
589 $qsTmp = str_replace("#FIELD#",$prefix.trim(substr($conf["type"],6)),$this->compSQL[$conf["comparison"]]);
590 $inputVal = $this->cleanInputVal($conf);
591 $qsTmp = str_replace("#VALUE#",$inputVal,$qsTmp);
592 if ($conf["comparison"]==37 || $conf["comparison"]==36) { // between:
593 $inputVal = $this->cleanInputVal($conf,"1");
594 $qsTmp = str_replace("#VALUE1#",$inputVal,$qsTmp);
595 }
596 $qs .= trim($qsTmp);
597 return $qs;
598 }
599 function cleanInputVal($conf,$suffix="") {
600 if(($conf["comparison"] >> 5==0) || ($conf["comparison"]==32 || $conf["comparison"]==33)) {
601 $inputVal = addslashes($conf["inputValue".$suffix]);
602 } else {
603 if ($conf["comparison"]==39 || $conf["comparison"]==38) { // in list:
604 $inputVal = implode(",",t3lib_div::intExplode(",",$conf["inputValue".$suffix]));
605 } else {
606 $inputVal = doubleval($conf["inputValue".$suffix]);
607 }
608 }
609 return $inputVal;
610 }
611 function getUserDefQuery ($qcArr) {
612 }
613 function updateIcon() {
614 return '<input type="image" border=0 src="'.$GLOBALS["BACK_PATH"].'gfx/refresh_n.gif" align="absmiddle" width="14" height="14" hspace=3 vspace=3 title="Update" name="just_update">';
615 }
616 function getLabelCol() {
617 global $TCA;
618 return $TCA[$this->table]["ctrl"]["label"];
619 }
620 function makeSelectorTable($modSettings,$enableList="table,fields,query,group,order,limit") {
621 $enableArr=explode(",",$enableList);
622 // Make output
623 $TDparams = ' bgColor="'.$GLOBALS["TBE_TEMPLATE"]->bgColor5.'" nowrap';;
624
625 if (in_array("table",$enableArr)) {
626 $out='
627 <tr>
628 <td'.$TDparams.'><strong>Select a table:</strong></td>
629 <td'.$TDparams.'>'.$this->mkTableSelect("SET[queryTable]",$this->table).'</td>
630 </tr>';
631 }
632 if ($this->table) {
633
634 // Init fields:
635 $this->setAndCleanUpExternalLists("queryFields",$modSettings["queryFields"],"uid,".$this->getLabelCol());
636 $this->setAndCleanUpExternalLists("queryGroup",$modSettings["queryGroup"]);
637 $this->setAndCleanUpExternalLists("queryOrder",$modSettings["queryOrder"].",".$modSettings["queryOrder2"]);
638
639 // Limit:
640 $this->extFieldLists["queryLimit"]=$modSettings["queryLimit"];
641 if (!$this->extFieldLists["queryLimit"]) $this->extFieldLists["queryLimit"]=100;
642 $parts = t3lib_div::intExplode(",",$this->extFieldLists["queryLimit"]);
643 $this->extFieldLists["queryLimit"] = implode(",",array_slice($parts,0,2));
644
645 // Insert Descending parts
646 if ($this->extFieldLists["queryOrder"]) {
647 $descParts = explode(",",$modSettings["queryOrderDesc"].",".$modSettings["queryOrder2Desc"]);
648 $orderParts = explode(",",$this->extFieldLists["queryOrder"]);
649 reset($orderParts);
650 $reList=array();
651 while(list($kk,$vv)=each($orderParts)) {
652 $reList[]=$vv.($descParts[$kk]?" DESC":"");
653 }
654 $this->extFieldLists["queryOrder_SQL"] = implode(",",$reList);
655 }
656
657 // Query Generator:
658 $this->procesData($modSettings["queryConfig"] ? unserialize($modSettings["queryConfig"]) : "");
659 // debug($this->queryConfig);
660 $this->queryConfig = $this->cleanUpQueryConfig($this->queryConfig);
661 // debug($this->queryConfig);
662 $this->enableQueryParts = $modSettings["search_query_smallparts"];
663
664 $codeArr=$this->getFormElements();
665 $queryCode=$this->printCodeArray($codeArr);
666
667 if (in_array("fields",$enableArr)) {
668 $out.='
669 <tr>
670 <td'.$TDparams.'><strong>Select fields:</strong></td>
671 <td'.$TDparams.'>'.$this->mkFieldToInputSelect("SET[queryFields]",$this->extFieldLists["queryFields"]).'</td>
672 </tr>';
673 }
674 if (in_array("query",$enableArr)) {
675 $out.='<tr>
676 <td colspan=2'.$TDparams.'><strong>Make Query:</strong></td>
677 </tr>
678 <tr>
679 <td colspan=2>'.$queryCode.'</td>
680 </tr>
681 ';
682 }
683 if (in_array("group",$enableArr)) {
684 $out.='<tr>
685 <td'.$TDparams.'><strong>Group By:</strong></td>
686 <td'.$TDparams.'>'.$this->mkTypeSelect("SET[queryGroup]",$this->extFieldLists["queryGroup"],"").'</td>
687 </tr>';
688 }
689 if (in_array("order",$enableArr)) {
690 $orderByArr = explode(",",$this->extFieldLists["queryOrder"]);
691 // debug($orderByArr);
692 $orderBy="";
693 $orderBy.=$this->mkTypeSelect("SET[queryOrder]",$orderByArr[0],"").
694 "&nbsp;".t3lib_BEfunc::getFuncCheck($GLOBALS["SOBE"]->id,"SET[queryOrderDesc]",$modSettings["queryOrderDesc"])."&nbsp;Descending";
695 if ($orderByArr[0]) {
696 $orderBy.= "<BR>".$this->mkTypeSelect("SET[queryOrder2]",$orderByArr[1],"").
697 "&nbsp;".t3lib_BEfunc::getFuncCheck($GLOBALS["SOBE"]->id,"SET[queryOrder2Desc]",$modSettings["queryOrder2Desc"])."&nbsp;Descending";
698 }
699 $out.='<tr>
700 <td'.$TDparams.'><strong>Order By:</strong></td>
701 <td'.$TDparams.'>'.$orderBy.'</td>
702 </tr>';
703 }
704 if (in_array("limit",$enableArr)) {
705 $limit = '<input type="Text" value="'.htmlspecialchars($this->extFieldLists["queryLimit"]).'" name="SET[queryLimit]"'.$GLOBALS["TBE_TEMPLATE"]->formWidth(10).'>'.$this->updateIcon();
706 $out.='<tr>
707 <td'.$TDparams.'><strong>Limit:</strong></td>
708 <td'.$TDparams.'>'.$limit.'</td>
709 </tr>
710 ';
711 }
712 }
713 $out='<table border=0 cellpadding=3 cellspacing=1>'.$out.'</table>';
714 $out.=$this->JSbottom();
715 return $out;
716 }
717 function getSelectQuery($qString="") {
718 if (!$qString) $qString=$this->getQuery($this->queryConfig);
719
720 $query = "SELECT ".$this->extFieldLists["queryFields"]."
721 FROM ".$this->table."
722 WHERE ".$qString."
723 ".t3lib_BEfunc::deleteClause($this->table);
724
725 if ($this->extFieldLists["queryGroup"]) {
726 $query.=chr(10)."GROUP BY ".$this->extFieldLists["queryGroup"];
727 }
728 if ($this->extFieldLists["queryOrder"]) {
729 $query.=chr(10)."ORDER BY ".$this->extFieldLists["queryOrder_SQL"];
730 }
731 $query.=chr(10)."LIMIT ".$this->extFieldLists["queryLimit"];
732 return $query;
733 }
734 function JSbottom($formname="forms[0]") {
735 if ($this->extJSCODE) {
736 $out.='
737 <script language="javascript" type="text/javascript" src="'.$GLOBALS["BACK_PATH"].'t3lib/jsfunc.evalfield.js"></script>
738 <script language="javascript" type="text/javascript">
739 var evalFunc = new evalFunc;
740 function typo3FormFieldSet(theField, evallist, is_in, checkbox, checkboxValue) {
741 var theFObj = new evalFunc_dummy (evallist,is_in, checkbox, checkboxValue);
742 var theValue = document.'.$formname.'[theField].value;
743 if (checkbox && theValue==checkboxValue) {
744 document.'.$formname.'[theField+"_hr"].value="";
745 if (document.'.$formname.'[theField+"_cb"]) document.'.$formname.'[theField+"_cb"].checked = "";
746 } else {
747 document.'.$formname.'[theField+"_hr"].value = evalFunc.outputObjValue(theFObj, theValue);
748 if (document.'.$formname.'[theField+"_cb"]) document.'.$formname.'[theField+"_cb"].checked = "on";
749 }
750 }
751 function typo3FormFieldGet(theField, evallist, is_in, checkbox, checkboxValue, checkbox_off) {
752 var theFObj = new evalFunc_dummy (evallist,is_in, checkbox, checkboxValue);
753 if (checkbox_off) {
754 document.'.$formname.'[theField].value=checkboxValue;
755 }else{
756 document.'.$formname.'[theField].value = evalFunc.evalObjValue(theFObj, document.'.$formname.'[theField+"_hr"].value);
757 }
758 typo3FormFieldSet(theField, evallist, is_in, checkbox, checkboxValue);
759 }
760 </script>
761 <script language="javascript" type="text/javascript">'.$this->extJSCODE.'</script>';
762 return $out;
763 }
764 }
765 }
766
767
768 if (defined("TYPO3_MODE") && $TYPO3_CONF_VARS[TYPO3_MODE]["XCLASS"]["t3lib/class.t3lib_querygenerator.php"]) {
769 include_once($TYPO3_CONF_VARS[TYPO3_MODE]["XCLASS"]["t3lib/class.t3lib_querygenerator.php"]);
770 }
771 ?>