* Added Karsten D.s patches for DBAL.
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_querygenerator.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2001-2004 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 * Class for generating front end for building queries
29 *
30 * $Id$
31 *
32 * @author Christian Jul Jensen <christian@typo3.com>
33 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
34 */
35 /**
36 * [CLASS/FUNCTION INDEX of SCRIPT]
37 *
38 *
39 *
40 * 95: class t3lib_queryGenerator
41 * 176: function makeFieldList()
42 * 203: function init($name,$table,$fieldList="")
43 * 292: function setAndCleanUpExternalLists($name,$list,$force="")
44 * 308: function procesData($qC="")
45 * 411: function cleanUpQueryConfig($queryConfig)
46 * 468: function getFormElements($subLevel=0,$queryConfig="",$parent="")
47 * 555: function printCodeArray($codeArr,$l=0)
48 * 578: function formatQ($str)
49 * 591: function mkOperatorSelect($name,$op,$draw,$submit)
50 * 613: function mkTypeSelect($name,$fieldName,$prepend="FIELD_")
51 * 632: function verifyType($fieldName)
52 * 649: function verifyComparison($comparison,$neg)
53 * 668: function mkFieldToInputSelect($name,$fieldName)
54 * 689: function mkTableSelect($name,$cur)
55 * 711: function mkCompSelect($name,$comparison,$neg)
56 * 729: function getSubscript($arr)
57 * 744: function initUserDef()
58 * 753: function userDef()
59 * 762: function userDefCleanUp($queryConfig)
60 * 773: function getQuery ($queryConfig,$pad="")
61 * 803: function getQuerySingle($conf,$first)
62 * 824: function cleanInputVal($conf,$suffix="")
63 * 843: function getUserDefQuery ($qcArr)
64 * 851: function updateIcon()
65 * 860: function getLabelCol()
66 * 872: function makeSelectorTable($modSettings,$enableList="table,fields,query,group,order,limit")
67 * 976: function getSelectQuery($qString="")
68 * 996: function JSbottom($formname="forms[0]")
69 * 1002: function typo3FormFieldSet(theField, evallist, is_in, checkbox, checkboxValue)
70 * 1020: function typo3FormFieldGet(theField, evallist, is_in, checkbox, checkboxValue, checkbox_off)
71 *
72 * TOTAL FUNCTIONS: 30
73 * (This index is automatically created/updated by the extension "extdeveval")
74 *
75 */
76
77
78
79
80
81
82
83
84
85
86
87 /**
88 * Class for generating front end for building queries
89 *
90 * @author Christian Jul Jensen <christian@typo3.com>
91 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
92 * @package TYPO3
93 * @subpackage t3lib
94 */
95 class t3lib_queryGenerator {
96 var $lang = array(
97 "OR" => "or",
98 "AND" => "and",
99 "comparison" => array(
100 // Type = text offset = 0
101 "0_" => "contains",
102 "1_" => "does not contain",
103 "2_" => "starts with",
104 "3_" => "does not start with",
105 "4_" => "ends with",
106 "5_" => "does not end with",
107 "6_" => "equals",
108 "7_" => "does not equal",
109 // Type = date,number , offset = 32
110 "32_" => "equals",
111 "33_" => "does not equal",
112 "34_" => "is greater than",
113 "35_" => "is less than",
114 "36_" => "is between",
115 "37_" => "is not between",
116 "38_" => "is in list",
117 "39_" => "is not in list",
118 "40_" => "binary AND equals",
119 "41_" => "binary AND does not equal",
120 "42_" => "binary OR equals",
121 "43_" => "binary OR does not equal"
122 )
123 );
124
125 var $compSQL = array(
126 // Type = text offset = 0
127 "0" => "#FIELD# LIKE '%#VALUE#%'",
128 "1" => "#FIELD# NOT LIKE '%#VALUE#%'",
129 "2" => "#FIELD# LIKE '#VALUE#%'",
130 "3" => "#FIELD# NOT LIKE #VALUE#%",
131 "4" => "#FIELD# LIKE '%#VALUE#'",
132 "5" => "#FIELD# NOT LIKE '%#VALUE#'",
133 "6" => "#FIELD# = #VALUE#",
134 "7" => "#FIELD# != #VALUE#",
135 // Type = date,number , offset = 32
136 "32" => "#FIELD# = #VALUE#",
137 "33" => "#FIELD# != #VALUE#",
138 "34" => "#FIELD# > #VALUE#",
139 "35" => "#FIELD# < #VALUE#",
140 "36" => "#FIELD# >= #VALUE# AND #FIELD# <= #VALUE1#",
141 "37" => "NOT (#FIELD# >= #VALUE# AND #FIELD# <= #VALUE1#)",
142 "38" => "#FIELD# IN (#VALUE#)",
143 "39" => "#FIELD# NOT IN (#VALUE#)",
144 "40" => "(#FIELD# & #VALUE#)=#VALUE#",
145 "41" => "(#FIELD# & #VALUE#)!=#VALUE#",
146 "42" => "(#FIELD# | #VALUE#)=#VALUE#",
147 "43" => "(#FIELD# | #VALUE#)!=#VALUE#"
148 );
149
150 var $comp_offsets = array(
151 "text" => 0,
152 "number" => 1,
153 "date" => 1
154 );
155 var $noWrap=" nowrap";
156
157 var $name; // Form data name prefix
158 var $table; // table for the query
159 var $fieldList; // field list
160 var $fields = array(); // Array of the fields possible
161 var $extFieldLists = array();
162 var $queryConfig=array(); // The query config
163 var $enablePrefix=0;
164 var $enableQueryParts = 0;
165 var $extJSCODE="";
166
167
168
169
170
171
172
173 /**
174 * @return [type] ...
175 */
176 function makeFieldList() {
177 global $TCA;
178 $fieldListArr = array();
179 if (is_array($TCA[$this->table])) {
180 t3lib_div::loadTCA($this->table);
181 reset($TCA[$this->table]["columns"]);
182 while(list($fN)=each($TCA[$this->table]["columns"])) {
183 $fieldListArr[]=$fN;
184 }
185 $fieldListArr[]="uid";
186 $fieldListArr[]="pid";
187 if ($TCA[$this->table]["ctrl"]["tstamp"]) $fieldListArr[]=$TCA[$this->table]["ctrl"]["tstamp"];
188 if ($TCA[$this->table]["ctrl"]["crdate"]) $fieldListArr[]=$TCA[$this->table]["ctrl"]["crdate"];
189 if ($TCA[$this->table]["ctrl"]["cruser_id"]) $fieldListArr[]=$TCA[$this->table]["ctrl"]["cruser_id"];
190 if ($TCA[$this->table]["ctrl"]["sortby"]) $fieldListArr[]=$TCA[$this->table]["ctrl"]["sortby"];
191 }
192 return implode(",",$fieldListArr);
193 }
194
195 /**
196 * [Describe function...]
197 *
198 * @param [type] $name: ...
199 * @param [type] $table: ...
200 * @param [type] $fieldList: ...
201 * @return [type] ...
202 */
203 function init($name,$table,$fieldList="") {
204 global $TCA;
205
206 // Analysing the fields in the table.
207 if (is_array($TCA[$table])) {
208 t3lib_div::loadTCA($table);
209 $this->name = $name;
210 $this->table = $table;
211 $this->fieldList = $fieldList ? $fieldList : $this->makeFieldList();
212
213 $fieldArr = t3lib_div::trimExplode(",",$this->fieldList,1);
214 reset($fieldArr);
215 while(list(,$fN)=each($fieldArr)) {
216 $fC = $TCA[$this->table]["columns"][$fN];
217 if (is_array($fC) && $fC["label"]) {
218 $this->fields[$fN]["label"] = ereg_replace(":$","",trim($GLOBALS["LANG"]->sL($fC["label"])));
219 switch($fC["config"]["type"]) {
220 case "input":
221 if (eregi("int|year",$fC["config"]["eval"])) {
222 $this->fields[$fN]["type"]="number";
223 } elseif (eregi("date|time",$fC["config"]["eval"])) {
224 $this->fields[$fN]["type"]="date";
225 } else {
226 $this->fields[$fN]["type"]="text";
227 }
228 break;
229 case "check":
230 case "select":
231 $this->fields[$fN]["type"]="number";
232 break;
233 case "text":
234 default:
235 $this->fields[$fN]["type"]="text";
236 break;
237 }
238
239 } else {
240 $this->fields[$fN]["label"]="[FIELD: ".$fN."]";
241 $this->fields[$fN]["type"]="number";
242 }
243 }
244 }
245
246 /* // EXAMPLE:
247 $this->queryConfig = array(
248 array(
249 "operator" => "AND",
250 "type" => "FIELD_spaceBefore",
251 ),
252 array(
253 "operator" => "AND",
254 "type" => "FIELD_records",
255 "negate" => 1,
256 "inputValue" => "foo foo"
257 ),
258 array(
259 "type" => "newlevel",
260 "nl" => array(
261 array(
262 "operator" => "AND",
263 "type" => "FIELD_spaceBefore",
264 "negate" => 1,
265 "inputValue" => "foo foo"
266 ),
267 array(
268 "operator" => "AND",
269 "type" => "FIELD_records",
270 "negate" => 1,
271 "inputValue" => "foo foo"
272 )
273 )
274 ),
275 array(
276 "operator" => "OR",
277 "type" => "FIELD_maillist",
278 )
279 );
280 */
281 $this->initUserDef();
282 }
283
284 /**
285 * [Describe function...]
286 *
287 * @param [type] $name: ...
288 * @param [type] $list: ...
289 * @param [type] $force: ...
290 * @return [type] ...
291 */
292 function setAndCleanUpExternalLists($name,$list,$force="") {
293 $fields = array_unique(t3lib_div::trimExplode(",",$list.",".$force,1));
294 reset($fields);
295 $reList=array();
296 while(list(,$fN)=each($fields)) {
297 if ($this->fields[$fN]) $reList[]=$fN;
298 }
299 $this->extFieldLists[$name]=implode(",",$reList);
300 }
301
302 /**
303 * [Describe function...]
304 *
305 * @param [type] $qC: ...
306 * @return [type] ...
307 */
308 function procesData($qC="") {
309 $this->queryConfig = $qC;
310
311 $POST = t3lib_div::_POST();
312
313 // if delete...
314 if($POST["qG_del"]) {
315 //initialize array to work on, save special parameters
316 $ssArr = $this->getSubscript($POST["qG_del"]);
317 $workArr =& $this->queryConfig;
318 for($i=0;$i<sizeof($ssArr)-1;$i++) {
319 $workArr =& $workArr[$ssArr[$i]];
320 }
321 // delete the entry and move the other entries
322 unset($workArr[$ssArr[$i]]);
323 for($j=$ssArr[$i];$j<sizeof($workArr);$j++) {
324 $workArr[$j] = $workArr[$j+1];
325 unset($workArr[$j+1]);
326 }
327 }
328
329 // if insert...
330 if($POST["qG_ins"]) {
331 //initialize array to work on, save special parameters
332 $ssArr = $this->getSubscript($POST["qG_ins"]);
333 $workArr =& $this->queryConfig;
334 for($i=0;$i<sizeof($ssArr)-1;$i++) {
335 $workArr =& $workArr[$ssArr[$i]];
336 }
337 // move all entries above position where new entry is to be inserted
338 for($j=sizeof($workArr);$j>$ssArr[$i];$j--) {
339 $workArr[$j] = $workArr[$j-1];
340 }
341 //clear new entry position
342 unset($workArr[$ssArr[$i]+1]);
343 $workArr[$ssArr[$i]+1]['type'] = "FIELD_";
344 }
345
346 // if move up...
347 if($POST["qG_up"]) {
348 //initialize array to work on
349 $ssArr = $this->getSubscript($POST["qG_up"]);
350 $workArr =& $this->queryConfig;
351 for($i=0;$i<sizeof($ssArr)-1;$i++) {
352 $workArr =& $workArr[$ssArr[$i]];
353 }
354 //swap entries
355 $qG_tmp = $workArr[$ssArr[$i]];
356 $workArr[$ssArr[$i]] = $workArr[$ssArr[$i]-1];
357 $workArr[$ssArr[$i]-1] = $qG_tmp;
358 }
359
360 // if new level...
361 if($POST["qG_nl"]) {
362 //initialize array to work on
363 $ssArr = $this->getSubscript($POST["qG_nl"]);
364 $workArr =& $this->queryConfig;
365 for($i=0;$i<sizeof($ssArr)-1;$i++) {
366 $workArr =& $workArr[$ssArr[$i]];
367 }
368 // Do stuff:
369 $tempEl = $workArr[$ssArr[$i]];
370 if (is_array($tempEl)) {
371 if ($tempEl["type"]!="newlevel") {
372 $workArr[$ssArr[$i]]=array(
373 "type" => "newlevel",
374 "operator" => $tempEl["operator"],
375 "nl" => array($tempEl)
376 );
377 }
378 }
379 }
380
381 // if collapse level...
382 if($POST["qG_remnl"]) {
383 //initialize array to work on
384 $ssArr = $this->getSubscript($POST["qG_remnl"]);
385 $workArr =& $this->queryConfig;
386 for($i=0;$i<sizeof($ssArr)-1;$i++) {
387 $workArr =& $workArr[$ssArr[$i]];
388 }
389
390 // Do stuff:
391 $tempEl = $workArr[$ssArr[$i]];
392 if (is_array($tempEl)) {
393 if ($tempEl["type"]=="newlevel") {
394 $a1 = array_slice($workArr,0,$ssArr[$i]);
395 $a2 = array_slice($workArr,$ssArr[$i]);
396 array_shift($a2);
397 $a3 = $tempEl["nl"];
398 $a3[0]["operator"] = $tempEl["operator"];
399 $workArr=array_merge($a1,$a3,$a2);
400 }
401 }
402 }
403 }
404
405 /**
406 * [Describe function...]
407 *
408 * @param [type] $queryConfig: ...
409 * @return [type] ...
410 */
411 function cleanUpQueryConfig($queryConfig) {
412 //since we dont traverse the array using numeric keys in the upcoming whileloop make sure it's fresh and clean before displaying
413 if (is_array($queryConfig)) {
414 ksort($queryConfig);
415 } else {
416 //queryConfig should never be empty!
417 if(!$queryConfig[0] || !$queryConfig[0]["type"]) $queryConfig[0] = array("type"=>"FIELD_");
418 }
419 // Traverse:
420 reset($queryConfig);
421 $c=0;
422 $arrCount=0;
423 while(list($key,$conf)=each($queryConfig)) {
424 if(substr($conf["type"],0,6)=="FIELD_") {
425 $fName = substr($conf["type"],6);
426 $fType = $this->fields[$fName]["type"];
427 } elseif($conf["type"]=="newlevel") {
428 $fType = $conf["type"];
429 } else {
430 $fType = "ignore";
431 }
432 // debug($fType);
433 switch($fType) {
434 case "newlevel":
435 if(!$queryConfig[$key]["nl"]) $queryConfig[$key]["nl"][0]["type"] = "FIELD_";
436 $queryConfig[$key]["nl"]=$this->cleanUpQueryConfig($queryConfig[$key]["nl"]);
437 break;
438 case "userdef":
439 $queryConfig[$key]=$this->userDefCleanUp($queryConfig[$key]);
440 break;
441 case "ignore":
442 default:
443 // debug($queryConfig[$key]);
444 $verifiedName=$this->verifyType($fName);
445 $queryConfig[$key]["type"]="FIELD_".$this->verifyType($verifiedName);
446
447 if($conf["comparison"] >> 5 != $this->comp_offsets[$fType]) $conf["comparison"] = $this->comp_offsets[$fType] << 5;
448 $queryConfig[$key]["comparison"]=$this->verifyComparison($conf["comparison"],$conf["negate"]?1:0);
449
450 $queryConfig[$key]["inputValue"]=$this->cleanInputVal($queryConfig[$key]);
451 $queryConfig[$key]["inputValue1"]=$this->cleanInputVal($queryConfig[$key],1);
452
453 // debug($queryConfig[$key]);
454 break;
455 }
456 }
457 return $queryConfig;
458 }
459
460 /**
461 * [Describe function...]
462 *
463 * @param [type] $subLevel: ...
464 * @param [type] $queryConfig: ...
465 * @param [type] $parent: ...
466 * @return [type] ...
467 */
468 function getFormElements($subLevel=0,$queryConfig="",$parent="") {
469 $codeArr=array();
470 if (!is_array($queryConfig)) $queryConfig=$this->queryConfig;
471
472 reset($queryConfig);
473 $c=0;
474 $arrCount=0;
475 while(list($key,$conf)=each($queryConfig)) {
476 $subscript = $parent."[$key]";
477 $lineHTML = "";
478 $lineHTML.=$this->mkOperatorSelect($this->name.$subscript,$conf["operator"],$c,($conf["type"]!="FIELD_"));
479 if(substr($conf["type"],0,6)=="FIELD_") {
480 $fName = substr($conf["type"],6);
481 $fType = $this->fields[$fName]["type"];
482 if($conf["comparison"] >> 5 != $this->comp_offsets[$fType]) $conf["comparison"] = $this->comp_offsets[$fType] << 5;
483
484 //nasty nasty...
485 //make sure queryConfig contains _actual_ comparevalue.
486 //mkCompSelect don't care, but getQuery does.
487 $queryConfig[$key]["comparison"] += (isset($conf["negate"])-($conf["comparison"]%2));
488
489 } elseif($conf["type"]=="newlevel") {
490 $fType = $conf["type"];
491 } else {
492 $fType = "ignore";
493 }
494 // debug($fType);
495 switch($fType) {
496 case "ignore":
497 break;
498 case "newlevel":
499 if(!$queryConfig[$key]["nl"]) $queryConfig[$key]["nl"][0]["type"] = "FIELD_";
500 $lineHTML.='<input type="hidden" name="'.$this->name.$subscript.'[type]" value="newlevel">';
501 $codeArr[$arrCount]["sub"] = $this->getFormElements($subLevel+1,$queryConfig[$key]["nl"],$subscript."[nl]");
502 break;
503 case "userdef":
504 $lineHTML.=$this->userDef($this->name.$subscript,$conf,$fName,$fType);
505 break;
506 default:
507 $lineHTML.=$this->mkTypeSelect($this->name.$subscript.'[type]',$fName);
508 $lineHTML.=$this->mkCompSelect($this->name.$subscript.'[comparison]',$conf["comparison"],$conf["negate"]?1:0);
509 $lineHTML.='<input type="checkbox" '.($conf["negate"]?"checked":"").' name="'.$this->name.$subscript.'[negate]'.'" onClick="submit();">';
510
511 if ($conf["comparison"]==37 || $conf["comparison"]==36) { // between:
512 $lineHTML.='<input type="text" value="'.htmlspecialchars($conf["inputValue"]).'" name="'.$this->name.$subscript.'[inputValue]'.'"'.$GLOBALS["TBE_TEMPLATE"]->formWidth(5).'>
513 <input type="text" value="'.htmlspecialchars($conf["inputValue1"]).'" name="'.$this->name.$subscript.'[inputValue1]'.'"'.$GLOBALS["TBE_TEMPLATE"]->formWidth(5).'>
514 '; // onChange="submit();"
515 } elseif ($fType=="date") {
516 $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]'.'">';
517 $this->extJSCODE.='typo3FormFieldSet("'.$this->name.$subscript.'[inputValue]", "datetime", "", 0,0);';
518 } else {
519 $lineHTML.='<input type="text" value="'.htmlspecialchars($conf["inputValue"]).'" name="'.$this->name.$subscript.'[inputValue]'.'"'.$GLOBALS["TBE_TEMPLATE"]->formWidth(10).'>'; // onChange="submit();"
520 }
521 break;
522 }
523 if($fType != "ignore") {
524 $lineHTML .= $this->updateIcon();
525 $lineHTML .= '<input type="image" border=0 src="'.$GLOBALS["BACK_PATH"].'gfx/garbage.gif" class="absmiddle" width="11" height="12" hspace=3 vspace=3 title="Remove condition" name="qG_del'.$subscript.'">';
526 $lineHTML .= '<input type="image" border=0 src="'.$GLOBALS["BACK_PATH"].'gfx/add.gif" class="absmiddle" width="12" height="12" hspace=3 vspace=3 title="Add condition" name="qG_ins'.$subscript.'">';
527 if($c!=0) $lineHTML.= '<input type="image" border=0 src="'.$GLOBALS["BACK_PATH"].'gfx/pil2up.gif" class="absmiddle" width="12" height="7" hspace=3 vspace=3 title="Move up" name="qG_up'.$subscript.'">';
528
529 if($c!=0 && $fType!="newlevel") {
530 $lineHTML.= '<input type="image" border=0 src="'.$GLOBALS["BACK_PATH"].'gfx/pil2right.gif" class="absmiddle" height="12" width="7" hspace=3 vspace=3 title="New level" name="qG_nl'.$subscript.'">';
531 }
532 if($fType=="newlevel") {
533 $lineHTML.= '<input type="image" border=0 src="'.$GLOBALS["BACK_PATH"].'gfx/pil2left.gif" class="absmiddle" height="12" width="7" hspace=3 vspace=3 title="Collapse new level" name="qG_remnl'.$subscript.'">';
534 }
535
536 $codeArr[$arrCount]["html"] = $lineHTML;
537 $codeArr[$arrCount]["query"] = $this->getQuerySingle($conf,$c>0?0:1);
538 $arrCount++;
539 $c++;
540 }
541 }
542 // $codeArr[$arrCount] .='<input type="hidden" name="CMD" value="displayQuery">';
543 $this->queryConfig = $queryConfig;
544 //modifyHTMLColor($color,$R,$G,$B)
545 return $codeArr;
546 }
547
548 /**
549 * [Describe function...]
550 *
551 * @param [type] $codeArr: ...
552 * @param [type] $l: ...
553 * @return [type] ...
554 */
555 function printCodeArray($codeArr,$l=0) {
556 reset($codeArr);
557 $line="";
558 if ($l) $indent='<td><img height="1" width="50"></td>';
559 $lf=$l*30;
560 $bgColor = t3lib_div::modifyHTMLColor($GLOBALS["TBE_TEMPLATE"]->bgColor2,$lf,$lf,$lf);
561 while(list($k,$v)=each($codeArr)) {
562 $line.= '<tr>'.$indent.'<td bgcolor="'.$bgColor.'"'.$this->noWrap.'>'.$v["html"].'</td></tr>';
563 if ($this->enableQueryParts) {$line.= '<tr>'.$indent.'<td>'.$this->formatQ($v["query"]).'</td></tr>';}
564 if (is_array($v["sub"])) {
565 $line.= '<tr>'.$indent.'<td'.$this->noWrap.'>'.$this->printCodeArray($v["sub"],$l+1).'</td></tr>';
566 }
567 }
568 $out='<table border=0 cellpadding=0 cellspacing=1>'.$line.'</table>';
569 return $out;
570 }
571
572 /**
573 * [Describe function...]
574 *
575 * @param [type] $str: ...
576 * @return [type] ...
577 */
578 function formatQ($str) {
579 return '<font size=1 face=verdana color=maroon><i>'.$str.'</i></font>';
580 }
581
582 /**
583 * [Describe function...]
584 *
585 * @param [type] $name: ...
586 * @param [type] $op: ...
587 * @param [type] $draw: ...
588 * @param [type] $submit: ...
589 * @return [type] ...
590 */
591 function mkOperatorSelect($name,$op,$draw,$submit) {
592 if ($draw) {
593 $out='<select name="'.$name.'[operator]"'.($submit?' onChange="submit();"':'').'>'; //
594 $out.='<option value="AND"'.(!$op||$op=="AND" ? ' selected':'').'>'.$this->lang["AND"].'</option>';
595 $out.='<option value="OR"'.($op=="OR" ? ' selected':'').'>'.$this->lang["OR"].'</option>';
596 $out.='</select>';
597 } else {
598 $out.='<input type="hidden" value="'.$op.'" name="'.$name.'[operator]">';
599 $out.='<img src="clear.gif" height="1" width="47">';
600
601 }
602 return $out;
603 }
604
605 /**
606 * [Describe function...]
607 *
608 * @param [type] $name: ...
609 * @param [type] $fieldName: ...
610 * @param [type] $prepend: ...
611 * @return [type] ...
612 */
613 function mkTypeSelect($name,$fieldName,$prepend="FIELD_") {
614 $out='<select name="'.$name.'" onChange="submit();">';
615 $out.='<option value=""></option>';
616 reset($this->fields);
617 while(list($key,)=each($this->fields)) {
618 if ($GLOBALS["BE_USER"]->check("non_exclude_fields",$this->table.":".$key)) {
619 $out.='<option value="'.$prepend.$key.'"'.($key==$fieldName ? ' selected':'').'>'.$this->fields[$key]["label"].'</option>';
620 }
621 }
622 $out.='</select>';
623 return $out;
624 }
625
626 /**
627 * [Describe function...]
628 *
629 * @param [type] $fieldName: ...
630 * @return [type] ...
631 */
632 function verifyType($fieldName) {
633 reset($this->fields);
634 $first = "";
635 while(list($key,)=each($this->fields)) {
636 if (!$first) $first = $key;
637 if ($key==$fieldName) return $key;
638 }
639 return $first;
640 }
641
642 /**
643 * [Describe function...]
644 *
645 * @param [type] $comparison: ...
646 * @param [type] $neg: ...
647 * @return [type] ...
648 */
649 function verifyComparison($comparison,$neg) {
650 $compOffSet = $comparison >> 5;
651 $first=-1;
652 for($i=32*$compOffSet+$neg;$i<32*($compOffSet+1);$i+=2) {
653 if ($first==-1) $first = $i;
654 if (($i >> 1)==($comparison >> 1)) {
655 return $i;
656 }
657 }
658 return $first;
659 }
660
661 /**
662 * [Describe function...]
663 *
664 * @param [type] $name: ...
665 * @param [type] $fieldName: ...
666 * @return [type] ...
667 */
668 function mkFieldToInputSelect($name,$fieldName) {
669 $out='<input type="Text" value="'.htmlspecialchars($fieldName).'" name="'.$name.'"'.$GLOBALS["TBE_TEMPLATE"]->formWidth().'>'.$this->updateIcon();
670 $out.='<a href="#" onClick="document.forms[0][\''.$name.'\'].value=\'\';return false;"><img src="'.$GLOBALS["BACK_PATH"].'gfx/garbage.gif" class="absmiddle" width="11" height="12" hspace=3 vspace=3 title="Clear list" border=0></a>';
671 $out.='<BR><select name="_fieldListDummy" size=5 onChange="document.forms[0][\''.$name.'\'].value+=\',\'+this.value">';
672 reset($this->fields);
673 while(list($key,)=each($this->fields)) {
674 if ($GLOBALS["BE_USER"]->check("non_exclude_fields",$this->table.":".$key)) {
675 $out.='<option value="'.$prepend.$key.'"'.($key==$fieldName ? ' selected':'').'>'.$this->fields[$key]["label"].'</option>';
676 }
677 }
678 $out.='</select>';
679 return $out;
680 }
681
682 /**
683 * [Describe function...]
684 *
685 * @param [type] $name: ...
686 * @param [type] $cur: ...
687 * @return [type] ...
688 */
689 function mkTableSelect($name,$cur) {
690 global $TCA;
691 $out='<select name="'.$name.'" onChange="submit();">';
692 $out.='<option value=""></option>';
693 reset($TCA);
694 while(list($tN)=each($TCA)) {
695 if ($GLOBALS["BE_USER"]->check("tables_select",$tN)) {
696 $out.='<option value="'.$tN.'"'.($tN==$cur ? ' selected':'').'>'.$GLOBALS["LANG"]->sl($TCA[$tN]["ctrl"]["title"]).'</option>';
697 }
698 }
699 $out.='</select>';
700 return $out;
701 }
702
703 /**
704 * [Describe function...]
705 *
706 * @param [type] $name: ...
707 * @param [type] $comparison: ...
708 * @param [type] $neg: ...
709 * @return [type] ...
710 */
711 function mkCompSelect($name,$comparison,$neg) {
712 $compOffSet = $comparison >> 5;
713 $out='<select name="'.$name.'" onChange="submit();">';
714 for($i=32*$compOffSet+$neg;$i<32*($compOffSet+1);$i+=2) {
715 if($this->lang["comparison"][$i."_"]) {
716 $out.='<option value="'.$i.'"'.(($i >> 1)==($comparison >> 1) ? ' selected':'').'>'.$this->lang["comparison"][$i."_"].'</option>';
717 }
718 }
719 $out.='</select>';
720 return $out;
721 }
722
723 /**
724 * [Describe function...]
725 *
726 * @param [type] $arr: ...
727 * @return [type] ...
728 */
729 function getSubscript($arr) {
730 while(is_array($arr)) {
731 reset($arr);
732 list($key,)=each($arr);
733 $retArr[] = $key;
734 $arr = $arr[$key];
735 }
736 return $retArr;
737 }
738
739 /**
740 * [Describe function...]
741 *
742 * @return [type] ...
743 */
744 function initUserDef() {
745
746 }
747
748 /**
749 * [Describe function...]
750 *
751 * @return [type] ...
752 */
753 function userDef() {
754 }
755
756 /**
757 * [Describe function...]
758 *
759 * @param [type] $queryConfig: ...
760 * @return [type] ...
761 */
762 function userDefCleanUp($queryConfig) {
763 return $queryConfig;
764 }
765
766 /**
767 * [Describe function...]
768 *
769 * @param [type] $queryConfig: ...
770 * @param [type] $pad: ...
771 * @return [type] ...
772 */
773 function getQuery ($queryConfig,$pad="") {
774 $qs = "";
775 //since wo dont traverse the array using numeric keys in the upcoming whileloop make sure it's fresh and clean
776 ksort($queryConfig);
777 reset($queryConfig);
778 $first=1;
779 while(list($key,$conf) = each($queryConfig)) {
780 switch($conf["type"]) {
781 case "newlevel":
782 $qs.=chr(10).$pad.trim($conf["operator"])." (".$this->getQuery($queryConfig[$key]["nl"],$pad." ").chr(10).$pad.")";
783 break;
784 case "userdef":
785 $qs.=chr(10).$pad.getUserDefQuery($conf,$first);
786 break;
787 default:
788 $qs.=chr(10).$pad.$this->getQuerySingle($conf,$first);
789 break;
790 }
791 $first=0;
792 }
793 return $qs;
794 }
795
796 /**
797 * [Describe function...]
798 *
799 * @param [type] $conf: ...
800 * @param [type] $first: ...
801 * @return [type] ...
802 */
803 function getQuerySingle($conf,$first) {
804 $prefix = $this->enablePrefix ? $this->table."." : "";
805 if (!$first) {$qs.= trim(($conf["operator"]?$conf["operator"]:"AND"))." ";} // Is it OK to insert the AND operator if none is set?
806 $qsTmp = str_replace("#FIELD#",$prefix.trim(substr($conf["type"],6)),$this->compSQL[$conf["comparison"]]);
807 $inputVal = $this->cleanInputVal($conf);
808 $qsTmp = str_replace("#VALUE#", $GLOBALS['TYPO3_DB']->quoteStr($inputVal, $this->table),$qsTmp);
809 if ($conf["comparison"]==37 || $conf["comparison"]==36) { // between:
810 $inputVal = $this->cleanInputVal($conf,"1");
811 $qsTmp = str_replace("#VALUE1#", $GLOBALS['TYPO3_DB']->quoteStr($inputVal, $this->table),$qsTmp);
812 }
813 $qs .= trim($qsTmp);
814 return $qs;
815 }
816
817 /**
818 * [Describe function...]
819 *
820 * @param [type] $conf: ...
821 * @param [type] $suffix: ...
822 * @return [type] ...
823 */
824 function cleanInputVal($conf,$suffix="") {
825 if(($conf["comparison"] >> 5==0) || ($conf["comparison"]==32 || $conf["comparison"]==33)) {
826 $inputVal = $conf["inputValue".$suffix];
827 } else {
828 if ($conf["comparison"]==39 || $conf["comparison"]==38) { // in list:
829 $inputVal = implode(",",t3lib_div::intExplode(",",$conf["inputValue".$suffix]));
830 } else {
831 $inputVal = doubleval($conf["inputValue".$suffix]);
832 }
833 }
834 return $inputVal;
835 }
836
837 /**
838 * [Describe function...]
839 *
840 * @param [type] $qcArr: ...
841 * @return [type] ...
842 */
843 function getUserDefQuery ($qcArr) {
844 }
845
846 /**
847 * [Describe function...]
848 *
849 * @return [type] ...
850 */
851 function updateIcon() {
852 return '<input type="image" border=0 src="'.$GLOBALS["BACK_PATH"].'gfx/refresh_n.gif" class="absmiddle" width="14" height="14" hspace=3 vspace=3 title="Update" name="just_update">';
853 }
854
855 /**
856 * [Describe function...]
857 *
858 * @return [type] ...
859 */
860 function getLabelCol() {
861 global $TCA;
862 return $TCA[$this->table]["ctrl"]["label"];
863 }
864
865 /**
866 * [Describe function...]
867 *
868 * @param [type] $modSettings: ...
869 * @param [type] $enableList: ...
870 * @return [type] ...
871 */
872 function makeSelectorTable($modSettings,$enableList="table,fields,query,group,order,limit") {
873 $enableArr=explode(",",$enableList);
874 // Make output
875 $TDparams = ' class="bgColor5" nowrap';
876
877 if (in_array("table",$enableArr)) {
878 $out='
879 <tr>
880 <td'.$TDparams.'><strong>Select a table:</strong></td>
881 <td'.$TDparams.'>'.$this->mkTableSelect("SET[queryTable]",$this->table).'</td>
882 </tr>';
883 }
884 if ($this->table) {
885
886 // Init fields:
887 $this->setAndCleanUpExternalLists("queryFields",$modSettings["queryFields"],"uid,".$this->getLabelCol());
888 $this->setAndCleanUpExternalLists("queryGroup",$modSettings["queryGroup"]);
889 $this->setAndCleanUpExternalLists("queryOrder",$modSettings["queryOrder"].",".$modSettings["queryOrder2"]);
890
891 // Limit:
892 $this->extFieldLists["queryLimit"]=$modSettings["queryLimit"];
893 if (!$this->extFieldLists["queryLimit"]) $this->extFieldLists["queryLimit"]=100;
894 $parts = t3lib_div::intExplode(",",$this->extFieldLists["queryLimit"]);
895 $this->extFieldLists["queryLimit"] = implode(",",array_slice($parts,0,2));
896
897 // Insert Descending parts
898 if ($this->extFieldLists["queryOrder"]) {
899 $descParts = explode(",",$modSettings["queryOrderDesc"].",".$modSettings["queryOrder2Desc"]);
900 $orderParts = explode(",",$this->extFieldLists["queryOrder"]);
901 reset($orderParts);
902 $reList=array();
903 while(list($kk,$vv)=each($orderParts)) {
904 $reList[]=$vv.($descParts[$kk]?" DESC":"");
905 }
906 $this->extFieldLists["queryOrder_SQL"] = implode(",",$reList);
907 }
908
909 // Query Generator:
910 $this->procesData($modSettings["queryConfig"] ? unserialize($modSettings["queryConfig"]) : "");
911 // debug($this->queryConfig);
912 $this->queryConfig = $this->cleanUpQueryConfig($this->queryConfig);
913 // debug($this->queryConfig);
914 $this->enableQueryParts = $modSettings["search_query_smallparts"];
915
916 $codeArr=$this->getFormElements();
917 $queryCode=$this->printCodeArray($codeArr);
918
919 if (in_array("fields",$enableArr)) {
920 $out.='
921 <tr>
922 <td'.$TDparams.'><strong>Select fields:</strong></td>
923 <td'.$TDparams.'>'.$this->mkFieldToInputSelect("SET[queryFields]",$this->extFieldLists["queryFields"]).'</td>
924 </tr>';
925 }
926 if (in_array("query",$enableArr)) {
927 $out.='<tr>
928 <td colspan=2'.$TDparams.'><strong>Make Query:</strong></td>
929 </tr>
930 <tr>
931 <td colspan=2>'.$queryCode.'</td>
932 </tr>
933 ';
934 }
935 if (in_array("group",$enableArr)) {
936 $out.='<tr>
937 <td'.$TDparams.'><strong>Group By:</strong></td>
938 <td'.$TDparams.'>'.$this->mkTypeSelect("SET[queryGroup]",$this->extFieldLists["queryGroup"],"").'</td>
939 </tr>';
940 }
941 if (in_array("order",$enableArr)) {
942 $orderByArr = explode(",",$this->extFieldLists["queryOrder"]);
943 // debug($orderByArr);
944 $orderBy="";
945 $orderBy.=$this->mkTypeSelect("SET[queryOrder]",$orderByArr[0],"").
946 "&nbsp;".t3lib_BEfunc::getFuncCheck($GLOBALS["SOBE"]->id,"SET[queryOrderDesc]",$modSettings["queryOrderDesc"])."&nbsp;Descending";
947 if ($orderByArr[0]) {
948 $orderBy.= "<BR>".$this->mkTypeSelect("SET[queryOrder2]",$orderByArr[1],"").
949 "&nbsp;".t3lib_BEfunc::getFuncCheck($GLOBALS["SOBE"]->id,"SET[queryOrder2Desc]",$modSettings["queryOrder2Desc"])."&nbsp;Descending";
950 }
951 $out.='<tr>
952 <td'.$TDparams.'><strong>Order By:</strong></td>
953 <td'.$TDparams.'>'.$orderBy.'</td>
954 </tr>';
955 }
956 if (in_array("limit",$enableArr)) {
957 $limit = '<input type="Text" value="'.htmlspecialchars($this->extFieldLists["queryLimit"]).'" name="SET[queryLimit]"'.$GLOBALS["TBE_TEMPLATE"]->formWidth(10).'>'.$this->updateIcon();
958 $out.='<tr>
959 <td'.$TDparams.'><strong>Limit:</strong></td>
960 <td'.$TDparams.'>'.$limit.'</td>
961 </tr>
962 ';
963 }
964 }
965 $out='<table border=0 cellpadding=3 cellspacing=1>'.$out.'</table>';
966 $out.=$this->JSbottom();
967 return $out;
968 }
969
970 /**
971 * [Describe function...]
972 *
973 * @param [type] $qString: ...
974 * @return [type] ...
975 */
976 function getSelectQuery($qString="") {
977 if (!$qString) $qString=$this->getQuery($this->queryConfig);
978
979 $query = $GLOBALS['TYPO3_DB']->SELECTquery(
980 $this->extFieldLists["queryFields"],
981 $this->table,
982 $qString.t3lib_BEfunc::deleteClause($this->table),
983 trim($this->extFieldLists["queryGroup"]),
984 $this->extFieldLists["queryOrder"] ? trim($this->extFieldLists["queryOrder_SQL"]) : '',
985 $this->extFieldLists["queryLimit"]
986 );
987 return $query;
988 }
989
990 /**
991 * [Describe function...]
992 *
993 * @param [type] $formname: ...
994 * @return [type] ...
995 */
996 function JSbottom($formname="forms[0]") {
997 if ($this->extJSCODE) {
998 $out.='
999 <script language="javascript" type="text/javascript" src="'.$GLOBALS["BACK_PATH"].'t3lib/jsfunc.evalfield.js"></script>
1000 <script language="javascript" type="text/javascript">
1001 var evalFunc = new evalFunc;
1002 function typo3FormFieldSet(theField, evallist, is_in, checkbox, checkboxValue) {
1003 var theFObj = new evalFunc_dummy (evallist,is_in, checkbox, checkboxValue);
1004 var theValue = document.'.$formname.'[theField].value;
1005 if (checkbox && theValue==checkboxValue) {
1006 document.'.$formname.'[theField+"_hr"].value="";
1007 if (document.'.$formname.'[theField+"_cb"]) document.'.$formname.'[theField+"_cb"].checked = "";
1008 } else {
1009 document.'.$formname.'[theField+"_hr"].value = evalFunc.outputObjValue(theFObj, theValue);
1010 if (document.'.$formname.'[theField+"_cb"]) document.'.$formname.'[theField+"_cb"].checked = "on";
1011 }
1012 }
1013
1014 /**
1015 * [Describe function...]
1016 *
1017 * @param [type] $theField, evallist, is_in, checkbox, checkboxValue, checkbox_off: ...
1018 * @return [type] ...
1019 */
1020 function typo3FormFieldGet(theField, evallist, is_in, checkbox, checkboxValue, checkbox_off) {
1021 var theFObj = new evalFunc_dummy (evallist,is_in, checkbox, checkboxValue);
1022 if (checkbox_off) {
1023 document.'.$formname.'[theField].value=checkboxValue;
1024 }else{
1025 document.'.$formname.'[theField].value = evalFunc.evalObjValue(theFObj, document.'.$formname.'[theField+"_hr"].value);
1026 }
1027 typo3FormFieldSet(theField, evallist, is_in, checkbox, checkboxValue);
1028 }
1029 </script>
1030 <script language="javascript" type="text/javascript">'.$this->extJSCODE.'</script>';
1031 return $out;
1032 }
1033 }
1034 }
1035
1036
1037 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_querygenerator.php']) {
1038 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_querygenerator.php']);
1039 }
1040 ?>